微服務Tars入門以及踩坑記錄


微服務Tars入門以及踩坑記錄

     什么是微服務

      近幾年,微服務這個詞闖入我們的視線范圍。通常跟微服務相對的是單體應用,即將所有功能都打包成在一個獨立單元的應用程序。微服務的架構就是將單個應用程序划分成各種小的、互相連接的微服務,一個微服務完成一個比較單一的功能,相互之間保持獨立和解耦合。不同服務內部的開發技術可以不一致。

      當然,拆分成多個服務,關於服務的管理也引出了一系列問題。為了解決這些問題,提出了一系列概念:服務注冊與發現、服務監控、服務治理等等。微服務的這些問題可以通過引入微服務框架來幫助我們去解決。

      目前業界比較成熟的微服務框架有阿里的Dubbo、Pivotal公司的Spring Cloud、騰訊的Tars、google的gRPC等等。

      我這里選擇Tars作為入門學習的微服務框架。學習過程中,發現這跟我平時使用的PHP框架很不一樣,除了要學習使用TarsPHP這一開發框架,微服務的環境部署和發布節點之外,還涉及到很多網絡、服務器方面的知識。都是自己所欠缺需要惡補的。而且還需要考慮服務邊界的划分服務與服務之間是如何調用的。

     發布節點時報錯

      使用docker-compose進行部署,發布節點的時候遇到問題: 出現batchPatch err:NodeImp.cpp:patchPro:111| error:ip 172.25.0.1 is invalid錯誤

      

      看似一個ip無效的報錯,其實涉及到容器通信方面,必須先了解很多關於網絡的知識,才能逐一排查錯誤原因。這里就所涉及到的知識進行一個梳理,然后再排查分析。

    docker 網絡

     1.  docker network操作

     先查看下docker針對網絡有哪些操作,使用命令:docker  network  --help

     

    比如create命令:

    # 創建一個名為tars的橋接(bridge)虛擬網絡,網關172.25.0.1,網段為172.25.0.0

    使用命令:docker network create -d bridge --subnet=172.25.0.0/16 --gateway=172.25.0.1 tars

    我們也可以使用命令查看創建網絡的可選配置項:docker network create --help

    如下圖:

 

   2.  docker的網絡模式

   安裝 Docker 以后,會默認創建三種網絡,可以通過 docker network ls 查看:

   

   1)bridge(橋接模式)

   橋接模式是docker 的默認網絡設置,當docker服務啟動時,會在主機上創建一個名為docker0的虛擬以太網橋,並選擇一個和宿主機不同的IP地址和子網分配給docker0網橋。

   示意圖:

    

    網絡模式選擇橋接模式的容器,就會連接上docker0這個網橋,再通過nat的轉換,通過宿主機的網卡,連接外網,就能達到上外網的目的。

    默認情況下,守護進程會創建一對對等虛擬設備接口 veth pair,將其中一個接口設置為容器的 eth0 接口(容器的網卡),另一個接口放置在宿主機的命名空間中,以類似 vethxxx 這樣的名字命名,從而將宿主機上的所有容器都連接到這個內部網絡上。

    這里,我啟動了三個容器mysql、tars-node ,tars-framework,就會有三個容器網卡,以及一個docker0虛擬網卡,這三個容器網卡都會橋接到docker0網卡,docker0網卡與物理機網卡連接使用的是nat技術,如下圖:

    使用命令:ip addr (ip a 或  ip add list),查看網卡狀態

       

     使用命令查看bridge模式的詳細信息:docker network inspect bridge

     

     2)host模式

      該模式下容器是不會擁有自己的ip地址,而是使用宿主機的ip地址和端口。這種模式的好處就是網絡性能比橋接模式的好。缺點就是會占用宿主機的端口,網絡的隔離性不太好

      

3)none

      none模式沒有IP地址,無法連接外網,等於就是斷網的狀態,作用就是用於測試,生產環境一般不會用到這種

4)container

     新創建的容器不會創建自己的網卡和配置自己的 IP,而是和一個指定的容器共享 IP、端口范圍等。 

3.  docker-compose.yml文件分析

 1 version: "3"
 2 
 3 services:
 4   mysql:
 5     image: mysql:5.6
 6     container_name: compose-tars-mysql
 7     ports:
 8       - "3307:3306"
 9     restart: always
10     environment:
11       MYSQL_ROOT_PASSWORD: "123456"
12     volumes:
13       - ./mysql/data:/var/lib/mysql:rw
14       - ./source/Shanghai:/etc/localtime
15     networks:
16       internal:
17         ipv4_address: 172.25.1.2
18   framework:
19     image: tarscloud/framework:v2.4.0
20     container_name: compose-tars-framework
21     ports:
22       - "3000:3000"
23       - "3001:3001"
24     restart: always
25     networks:
26       internal:
27         ipv4_address: 172.25.1.3
28     environment:
29       MYSQL_HOST: "172.25.1.2"
30 #      MYSQL_HOST: "123.56.***.184"
31       MYSQL_ROOT_PASSWORD: "123456"
32       MYSQL_USER: "root"
33       MYSQL_PORT: 3306
34 #      MYSQL_PORT: 3307
35       REBUILD: "false"
36       INET: eth0
37       SLAVE: "false"
38     volumes:
39       - ./framework/data:/data/tars:rw
40       - ./source/Shanghai:/etc/localtime
41     depends_on:
42       - mysql
43   node:
44     image: tarscloud/tars-node:latest
45     container_name: compose-tars-node
46     restart: always
47     networks:
48       internal:
49         ipv4_address: 172.25.1.5
50     volumes:
51       - ./node/data:/data/tars:rw
52       - ./source/Shanghai:/etc/localtime
53     environment:
54       INET: eth0
55       WEB_HOST: http://172.25.1.3:3000
56 #      WEB_HOST: http://123.56.***.184:3000
57     ports:
58       - "9000-9009:9000-9009"
59     depends_on:
60       - framework
61 networks:
62   internal:
63     driver: bridge
64     ipam:
65       config:
66         - subnet: 172.25.1.0/16

    depends_on:定義容器啟動順序 (此選項解決了容器之間的依賴關系)

    4.   IP、網段、子網掩碼(網絡掩碼)

        從上面看到networks的設置中,網段為172.25.1.0/16,這里面就涉及到ip、相同網段、網絡掩碼的相關知識。

        1)什么是IP地址

        IP地址相當於網絡中的身份唯一認證ID,跟身份證ID一樣是唯一的,唯一不同的是,IP地址是可以變的,只是不管怎么變,都將會是唯一的。Mac地址的性質更加接近於身份證ID,它是設備的唯一ID。

        IP地址目前普遍是IPv4版本,由32位二進制數分成4組,每組1字節Byte(8Bit)組成。分別用十進制表示再用圓點隔開,就是現在的172.25.1.0。

        2)IP地址的構成

        IP地址 = 網絡地址 + 主機地址

        比如:192.168.1.168(IP地址) = 192.168.1.0 (網絡地址) + 0.0.0.168(主機地址)

        網絡地址、主機地址是怎么計算出來的呢?就需要先簡單學習下子網掩碼

        3)子網掩碼(subnet mask)

        比如這里的172.25.1.0/16中的16,指的是子網掩碼的長度,16代表16個1,用子網掩碼來表示,就是:255.255.0.0。它的作用主要是用來區分網絡地址和主機地址。

        將ip地址轉為二進制,子網掩碼轉為二進制,通過按位與最終得到網段號。根據按位與的特性,可以看到172.25這個網段是不變的,后面的都可以改變。

    排查錯誤原因

    下面我們就開始提到用TarsDocker部署后,針對發布節點時遇到的錯誤進行排查分析。

    分析:這個錯誤是這台機器上的tarnode識別過來的發布請求的非法,不是tarsAdminRegistry的ip。

    1)查看想要發布節點到的對應容器

    可以看到,這里發布的結點是172.25.1.5,我們是想通過這個ip發布到對應的容器tars-node

   

    現在我們來看下這個容器的詳細信息:docker inspect containerid

    根據報錯的信息:error:ip 172.25.0.1 is invalid,反應出tars找到的容器節點錯誤,找到的其實是網關,tars無法根據ip:172.25.0.1找到與它連接對應的容器,因此也就無法將服務發布到對相應容器。因此很快報ip無效的錯誤,流程根本都還沒有走到檢查打包的代碼這一步。

    2) 考慮換成容器逐個啟動的方式,看能否成功發布節點

    我先使用docker-compose down將啟動的容器都卸載,然后用docker run將mysql、tars-node、tars-framework逐個啟動

 1 docker run --name tars-mysql -e MYSQL_ROOT_PASSWORD='123456' -d -p 3307:3306 \
 2         -v/etc/localtime:/etc/localtime \
 3         -v /data/mysql-data:/var/lib/mysql mysql:5.6
 4 
 5 docker run -d \
 6     --name=tars-framework \
 7     -e MYSQL_HOST="123.56.***.184" \
 8     -e MYSQL_ROOT_PASSWORD="123456" \
 9     -e MYSQL_USER=root \
10     -e MYSQL_PORT=3307 \
11     -e REBUILD=false \
12     -e SLAVE=false \
13     -e INET=eth0 \
14     -p 3000:3000 \
15     -p 3001:3001 \
16     -v /etc/localtime:/etc/localtime \
17     -v /tmp/test/data:/data/tars \
18     tarscloud/framework:v2.4.0
19     
20 docker run -d \
21     --name=tars-node \
22     -e INET=eth0 \
23     -e WEB_HOST="http://123.56.***.184:3000" \
24     -p "9000-9010:9000-9010" \
25     -v /data/tars:/data/tars \
26     -v /etc/localtime:/etc/localtime \
27     tarscloud/tars-node:latest
28     

     這里將服務部署和發布節點的流程走一遍,可以發布成功。於是進行分析:

     容器通信的兩種方式

     1)不需要給容器建立虛擬網絡,直接通過eth0,也就是宿主機的外網環境直接訪問

     2)容器的虛擬網絡,通過暴露端口給宿主機映射的端口,通過宿主機+映射的端口訪問。

     這個地方用單個容器逐一啟動,發布節點時能把服務成功發布到相應容器,容器之間的通信是通過宿主機的外網環境直接訪問。

     經過反復排查,最終定位到問題到docker的網絡設置不對,導致發布時tarnode獲得的ip地址是網關地址172.25.0.1,而不是容器的網絡地址,因而無法發布服務到相應的容器。

     我這邊使用的是阿里雲服務器,通過重啟雲服務器,以及重新啟動docker。恢復正常。

    TarsDocker重新部署

    1.  重新部署,然后發布節點

    docker-compose up 不加-d,我們來看下容器啟動的流程

    

    可以看到,一個容器要等待它所依賴的其他容器啟動成功后,才能夠啟動。這期間開啟着定時任務,一直在嘗試着啟動各個容器,串行執行。

    啟動之后,通過宿主機地址+端口訪問,注意右上角是tars-framework版本

    

    2.  運維管理-服務部署

     

    3. 發布節點

    

    

 

    4.  切換到服務管理,刷新下頁面

    

      5.  輸入地址,訪問下運行的服務

      

     Ok,發布成功了,服務正常運行,並且能夠成功訪問了。

     部署和發布的過程中可能會遇到各種各樣的問題,有問題是好事,重點是我們要有足夠的知識儲備,去一步一步排查,分析原因,解決問題。

 

參考鏈接:

https://juejin.cn/post/6868086876751085581#heading-1

https://blog.csdn.net/qq_33355821/article/details/104173831

https://segmentfault.com/a/1190000022864573

https://doc.tarsyun.com/adminer/start/index.html#/tarsdoc/gateway/README.md 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM