您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關如何實踐Service Mesh微服務架構的基礎部署,文章內(nèi)容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
當下,已經(jīng)有很大一部分公司完成了單體架構向微服務架構的遷移改造,并在疲于應對大量微服務間通信問題時,開始考慮采用Service Mesh微服務架構作為服務與服務直接通信的透明化管理框架,以插件式的方式實現(xiàn)各種業(yè)務所需的高級管理功能。
而開源PaaS Rainbond提供了開箱即用的Service Mesh微服務架構,部署在Rainbond上的應用原生即是Service Mesh微服務架構應用。
接下來,我們將以 Rainbond v3.7.0 為基礎平臺,以開源商城項目 sockshop 為例,演示如何在源代碼無入侵的情況下,將項目改造為具有服務注冊與發(fā)現(xiàn)
、分布式跟蹤
、A/B測試
、灰度發(fā)布
、限流
、熔斷
、 性能分析
、高可用
、日志分析
等能力的高可靠性電商業(yè)務系統(tǒng).
sockshop是一個典型的微服務架構案例,具備用戶管理、商品管理、購物車、訂單流程、地址管理等完善的電商相關功能。sockshop主要由Spring boot
、Golang
、Nodejs
等多種語言開發(fā),使用MySQL
和MongoDB
等多種數(shù)據(jù)庫,原方案采用單機環(huán)境下的部署方式,缺乏服務治理能力和分布式能力。
sockshop部署后的拓撲圖總覽
sockshop商城首頁預覽圖
sockshop架構圖
更多信息
源碼地址
weavesocksdemo 樣例
Rainbond支持從源碼、鏡像、應用市場等多種方式進行應用部署,這里我們采用DockerCompose配置文件
的創(chuàng)建方式,批量創(chuàng)建 sockshop 中包含的所有服務。
docker-compose 創(chuàng)建
需要注意的是,在檢測和創(chuàng)建過程中,獲取大量鏡像需要一定時間,請耐心等待完成!
docker-compose 源碼: 下載
version: '2' services: front-end: image: weaveworksdemos/front-end:0.3.12 hostname: front-end restart: always cap_drop: - all ports: - "8079:8079" - "9001:9001" depends_on: - catalogue - carts - payment - user - orders edge-router: image: weaveworksdemos/edge-router:0.1.1 ports: - '80:80' - '8080:8080' cap_drop: - all cap_add: - NET_BIND_SERVICE - CHOWN - SETGID - SETUID - DAC_OVERRIDE tmpfs: - /var/run:rw,noexec,nosuid hostname: edge-router restart: always depends_on: - front-end catalogue: image: weaveworksdemos/catalogue:0.3.5 hostname: catalogue restart: always cap_drop: - all cap_add: - NET_BIND_SERVICE depends_on: - catalogue-db - zipkin catalogue-db: image: rilweic/catalog-db hostname: catalogue-db restart: always environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} - MYSQL_ALLOW_EMPTY_PASSWORD=true - MYSQL_DATABASE=socksdb carts: image: weaveworksdemos/carts:0.4.8 hostname: carts restart: always cap_drop: - all cap_add: - NET_BIND_SERVICE tmpfs: - /tmp:rw,noexec,nosuid environment: - JAVA_OPTS=-Xms64m -Xmx128m -XX:+UseG1GC -Djava.security.egd=file:/dev/urandom -Dspring.zipkin.enabled=false ports: - "80:80" depends_on: - carts-db - zipkin carts-db: image: mongo:3.4 hostname: carts-db restart: always cap_drop: - all cap_add: - CHOWN - SETGID - SETUID tmpfs: - /tmp:rw,noexec,nosuid orders: image: rilweic/orders hostname: orders restart: always cap_drop: - all cap_add: - NET_BIND_SERVICE tmpfs: - /tmp:rw,noexec,nosuid environment: - JAVA_OPTS=-Xms64m -Xmx128m -XX:+UseG1GC -Djava.security.egd=file:/dev/urandom -Dspring.zipkin.enabled=false ports: - "8848:8848" depends_on: - orders-db - zipkin - shipping - carts - payment - user orders-db: image: mongo:3.4 hostname: orders-db restart: always cap_drop: - all cap_add: - CHOWN - SETGID - SETUID tmpfs: - /tmp:rw,noexec,nosuid shipping: image: Rainbond/shipping:0.4.8 hostname: shipping restart: always cap_drop: - all cap_add: - NET_BIND_SERVICE tmpfs: - /tmp:rw,noexec,nosuid environment: - JAVA_OPTS=-Xms64m -Xmx128m -XX:+UseG1GC -Djava.security.egd=file:/dev/urandom -Dspring.zipkin.enabled=false ports: - "8080:8080" depends_on: - rabbitmq - zipkin queue-master: image: weaveworksdemos/queue-master:0.3.1 hostname: queue-master restart: always cap_drop: - all cap_add: - NET_BIND_SERVICE tmpfs: - /tmp:rw,noexec,nosuid depends_on: - rabbitmq rabbitmq: image: rabbitmq:3.6.8 hostname: rabbitmq restart: always cap_drop: - all cap_add: - CHOWN - SETGID - SETUID - DAC_OVERRIDE payment: image: weaveworksdemos/payment:0.4.3 hostname: payment restart: always cap_drop: - all cap_add: - NET_BIND_SERVICE depends_on: - zipkin user: image: weaveworksdemos/user:0.4.4 hostname: user restart: always cap_drop: - all cap_add: - NET_BIND_SERVICE environment: - MONGO_HOST=user-db:27017 depends_on: - user-db - zipkin user-db: image: weaveworksdemos/user-db:0.4.0 hostname: user-db restart: always cap_drop: - all cap_add: - CHOWN - SETGID - SETUID tmpfs: - /tmp:rw,noexec,nosuid zipkin: image: openzipkin/zipkin hostname: zipkin restart: always cap_drop: - all cap_add: - CHOWN - SETGID - SETUID tmpfs: - /tmp:rw,noexec,nosuid environment: - reschedule=on-node-failure ports: - "9411:9411"
源碼、應用市場等其他創(chuàng)建方式請參考Rainbond文檔:創(chuàng)建一個應用
服務創(chuàng)建完成后,我們需要對批量創(chuàng)建的服務進行注冊和對部署內(nèi)存的調(diào)整,根據(jù)服務之間的調(diào)用關系,分析出哪些服務是作為內(nèi)部服務供給其它服務調(diào)用、哪個服務是對用戶提供訪問的,并進行接下來的操作:
在 Rainbond 平臺,我們可以通過在服務的端口頁打開端口來進行服務的注冊。關于服務注冊的詳細文檔可參考Rainbond 平臺服務注冊
各服務對應的端口和部署內(nèi)存大小如下:
請注意,這里必須確定對每個服務組件的服務注冊信息和資源分配信息設置正確。
sockshop通過內(nèi)部域名來進行服務調(diào)用,也就是說,在完成服務的注冊后,調(diào)用服務需要發(fā)現(xiàn)被調(diào)用服務。
在 Rainbond 平臺,我們可以通過服務依賴來實現(xiàn)(詳情參考文檔服務發(fā)現(xiàn))。
各服務依賴的詳情可參考上圖
商城在Rainbond平臺的概覽
如果使用上面的 docker-compose 文件創(chuàng)建應用,無需手動添加依賴,在創(chuàng)建應用時系統(tǒng)已根據(jù) docker-compose 文件內(nèi)容自動配置了服務發(fā)現(xiàn)
在sockshop案例中,front-end
為nodejs
項目,該服務會調(diào)用其他 5 個服務來獲取數(shù)據(jù),如圖所示:
front-end
在調(diào)用其他服務時,會使用域名+端口的調(diào)用方式(該項目所有調(diào)用均為此方式) 如 front-end
調(diào)用 orders
時,內(nèi)部訪問地址為 http://orders/xxx
.
Rainbond 平臺在服務進行調(diào)用時,會默認將頂級域名
解析到127.0.0.1
,如果調(diào)用的服務對應的端口都不沖突沒有任何問題,而在此案例中,front-end
調(diào)用的其他 5 個服務的端口均為 80。因此這里需要第一個治理功能:端口復用。
在不安裝 7 層網(wǎng)絡治理插件的情況下,平臺默認使用 4 層網(wǎng)絡治理插件,無法提供端口復用的機制。因此,我們?yōu)榉?code>front-end orders
分別安裝網(wǎng)絡治理插件。
在我的插件
中選擇服務網(wǎng)絡治理插件
進行安裝。
特別注意
工作在 7 層的 Mesh 插件默認會占用 80 端口,因此需要安裝此插件的服務本身不能占用 80 端口。因此我們推薦服務盡量監(jiān)聽非 80 端口。插件內(nèi)存使用量需要根據(jù)流量大小調(diào)節(jié)。
在應用詳情頁面選擇插件
標簽,然后開通指定的插件。
Rainbond默認提供的服務網(wǎng)絡治理插件是基于Envoy制作,Rainbond ServiceMesh架構為Envoy提供了標準的運行支持。安裝插件后需重啟應用生效。
配置域名路由,實現(xiàn)端口復用。為了front-end
服務能根據(jù)代碼已有的域名調(diào)用選擇對應的服務提供方,我們需要根據(jù)其調(diào)用的域名來進行配置。將應用進行依賴后,服務網(wǎng)絡治理插件
能夠自動識別出其依賴的應用。我們只需在插件的配置的域名項中進行域名配置即可。如下圖:
詳細配置
更新插件相關的配置后進行保存并重啟相關應用即可。此處暫時先只用到基于域名的路由配置,關于網(wǎng)絡治理插件的更對詳情可參考 服務路由,灰度發(fā)布,A/B 測試
微服務是一個分布式的架構模式,它一直以來都會有一些自身的問題。當一個應用的運行狀態(tài)出現(xiàn)異常時,對于運維和開發(fā)人員來說,即時發(fā)現(xiàn)應用的狀態(tài)異常并解決是非常有必要的。我們可以通過監(jiān)控手段對服務進行衡量,或者做一個數(shù)據(jù)支撐。
Rainbond 平臺為我們提供了服務監(jiān)控與性能監(jiān)控,可以簡單直觀的了解服務當前的狀態(tài)和信息。
目前支持 HTTP 與 mysql 協(xié)議的應用
安裝插件
應用安裝插件
同上應用網(wǎng)絡治理插件安裝
安裝完成效果圖
安裝完成性能分析插件,可以在安裝該插件的應用概覽頁面查看應用的平均響應時間
和吞吐率
。
除此以外,我們也可以在該組應用的組概覽中看到應用的訪問情況。
案例上的性能測試工具服務
sockshop 商城案例自帶性能測試的服務,但是與該項目不是持續(xù)運行,而是運行一次后程序便會退出。在這里,我們根據(jù)源碼進行了一點小的修改。主要是將程序變?yōu)椴煌顺鲞\行。源碼地址
我們可以通過源碼方式來創(chuàng)建項目——
創(chuàng)建完成后,我們需要在 sockshop 商城創(chuàng)建一個賬號為user
、密碼為password
的用戶,負載測試需要使用該用戶名來和密碼進行模擬請求。
完成以上步驟,接下來我們對sockshop的分布式跟蹤進行處理。
隨著業(yè)務越來越復雜,系統(tǒng)也隨之進行各種拆分,特別是隨著微服務架構和容器技術的興起,看似簡單的一個應用,后臺可能有幾十個甚至幾百個服務在支撐;一個前端的請求可能需要多次的服務調(diào)用最后才能完成;當請求變慢或者不可用時,我們無法得知是哪個后臺服務引起的,這時就需要解決如何快速定位服務故障點,Zipkin 分布式跟蹤系統(tǒng)就能很好的解決這樣的問題。
Zipkin 分布式跟蹤系統(tǒng);它可以幫助收集時間數(shù)據(jù),解決在 microservice 架構下的延遲問題;它管理這些數(shù)據(jù)的收集和查找;Zipkin 的設計是基于谷歌的 Google Dapper 論文。 每個應用程序向 Zipkin 報告定時數(shù)據(jù),Zipkin UI 呈現(xiàn)了一個依賴圖表來展示多少跟蹤請求經(jīng)過了每個應用程序;如果想解決延遲問題,可以過濾或者排序所有的跟蹤請求,并且可以查看每個跟蹤請求占總跟蹤時間的百分比。
zipkin 架構
裝配了 zipkin 跟蹤器的服務可以將服務的每次調(diào)用(可以是 http 或者 rpc 或數(shù)據(jù)庫調(diào)用等)延時通過Transport
(目前有 4 總共發(fā)送方式,http,kafka,scribe,rabbitmq
)發(fā)送給zipkin
服務。
zipkin 主要包含 4 個模塊
collector: 接收或收集各應用傳輸?shù)臄?shù)據(jù)。 storage: 存儲接受或收集過來的數(shù)據(jù),當前支持 Memory,MySQL,Cassandra,ElasticSearch 等,默認存儲在內(nèi)存中。 API(Query): 負責查詢 Storage 中存儲的數(shù)據(jù),提供簡單的 JSON API 獲取數(shù)據(jù),主要提供給 web UI 使用 Web: 提供簡單的 web 界面
zipkin 服務追蹤流程
從上圖可以簡單概括為一次請求調(diào)用,zipkin 會在請求中加入跟蹤的頭部信息和相應的注釋,并記錄調(diào)用的時間并將數(shù)據(jù)返回給 zipkin 的收集器 collector。
在 Rinbond 平臺,我們可以直接通過 docker run 方式運行 zipkin.
注意開啟對外訪問端口和調(diào)整應用內(nèi)存大小
此時創(chuàng)建的 zipkin 的數(shù)據(jù)存在于內(nèi)存中,服務關閉或重啟數(shù)據(jù)都會丟失。因此在生產(chǎn)環(huán)境中,我們需要將數(shù)據(jù)存入存儲。
zipkin 支持 MySQL,Cassandra,ElasticSearch 三種存儲。我們以 Mysql 為例說明。目前 zipkin 至此的 mysql 版本為 5.6 和 5.7 版本。
在 Rainbond 平臺應用市場創(chuàng)建版本為 5.7 的 mysql 應用,如圖。
創(chuàng)建完成 mysql 以后,我們需要進行數(shù)據(jù)庫的初始化操作,zipkin 需要使用到 zipkin 數(shù)據(jù)和相應的表結構,需要我們自行創(chuàng)建。
在應用的詳情頁面,我們可以選擇管理容器
進入到容器進行操作,如圖。
進入容器后,使用命令登錄 mysql 命令行。
mysql -uusername -ppassword
mysql 的用戶和密碼可以在應用的依賴里看到 如圖
進入 mysql 命令行后,創(chuàng)建數(shù)據(jù)庫 zipkin
CREATE DATABASE zipkin ;
創(chuàng)建 zipkin 相關的表:下載
CREATE TABLE IF NOT EXISTS zipkin_spans ( `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit', `trace_id` BIGINT NOT NULL, `id` BIGINT NOT NULL, `name` VARCHAR(255) NOT NULL, `parent_id` BIGINT, `debug` BIT(1), `start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL', `duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query' ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; ALTER TABLE zipkin_spans ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `id`) COMMENT 'ignore insert on duplicate'; ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`, `id`) COMMENT 'for joining with zipkin_annotations'; ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds'; ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames'; ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range'; CREATE TABLE IF NOT EXISTS zipkin_annotations ( `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit', `trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id', `span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id', `a_key` VARCHAR(255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1', `a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB', `a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation', `a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp', `endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null', `endpoint_ipv6` BINARY(16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address', `endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null', `endpoint_service_name` VARCHAR(255) COMMENT 'Null when Binary/Annotation.endpoint is null' ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate'; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans'; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds'; ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames'; ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces'; ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces'; ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job'; CREATE TABLE IF NOT EXISTS zipkin_dependencies ( `day` DATE NOT NULL, `parent` VARCHAR(255) NOT NULL, `child` VARCHAR(255) NOT NULL, `call_count` BIGINT, `error_count` BIGINT ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; ALTER TABLE zipkin_dependencies ADD UNIQUE KEY(`day`, `parent`, `child`);
在 zipkin 服務中添加環(huán)境變量 STORAGE_TYPE
為 mysql
,此變量標志 zipkin 使用的存儲方式??蛇x擇值為 mysql
,elasticsearch
、cassandra
將 zipkin 與 mysql 建立依賴關系后,zipkin 服務便安裝完成。
zipkin 內(nèi)部會默認調(diào)用環(huán)境變量
MYSQL_USER
(用戶名),MYSQL_PASS
(密碼),MYSQL_HOST
(連接地址),MYSQL_PORT
(端口)。剛好與 Rainbond 平臺默認設置的變量一致,所以無需做任何修改。
其他服務如果連接的變量與 Rainbond 平臺默認提供的不一致,我們可以在應用的設置也添加相應的環(huán)境變量來達到訪問的目的。
sockshop 案例集成了zipkin
做分布式跟蹤。集成的組件為 users
、carts
、orders
、payment
、catalogue
、shipping
。
其中 carts
、orders
、shipping
為spring-boot項目,只需在設置中將環(huán)境變量JAVA_OPTS
的-Dspring.zipkin.enabled
改為true
即可。
如圖
payment
、catalogue
、users
為golang
項目,項目已在內(nèi)部集成了 zipkin 組件,我們需要添加環(huán)境變量ZIPKIN
為http://zipkin:9411/api/v1/spans
來明確服務調(diào)用 zipkin 的地址。
如圖
設置完成后,可以做直接訪問 zipkin 應用對外提供的訪問地址。訪問詳情如圖
我們可以在該圖中查看各個服務調(diào)用的延時詳情。
至此,我們已經(jīng)完成了基礎部署,可以看到完整的業(yè)務拓撲圖,sockshop也已經(jīng)可以正常工作了。
關于如何實踐Service Mesh微服務架構的基礎部署就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。