自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一個可供小團隊參考的微服務落地實踐

開發(fā) 架構 開發(fā)工具
微服務是否適合小團隊是個見仁見智的問題。但小團隊并不代表出品的一定是小產品,當業(yè)務變得越來越復雜,如何使用微服務分而治之就成為一個不得不面對的問題。

 微服務是否適合小團隊是個見仁見智的問題。但小團隊并不代表出品的一定是小產品,當業(yè)務變得越來越復雜,如何使用微服務分而治之就成為一個不得不面對的問題。

因為微服務是對整個團隊的考驗,從開發(fā)到交付,每一步都充滿了挑戰(zhàn)。經過 1 年多的探索和實踐,本著將 DevOps 落實到產品中的愿景,一步步建設出適合我們的微服務平臺。

要不要微服務

我們的產品是 Linkflow,企業(yè)運營人員使用的客戶數據平臺(CDP)。產品的一個重要部分類似企業(yè)版的“捷徑",讓運營人員可以像搭樂高積木一樣創(chuàng)建企業(yè)的自動化流程,無需編程即可讓數據流動起來。

從這一點上,我們的業(yè)務特點就是聚少成多,把一個個服務連接起來就成了數據的海洋。

理念上跟微服務一致,一個個獨立的小服務最終實現大功能。當然我們一開始也沒有使用微服務,當業(yè)務還未成型就開始考慮架構,那么就是“過度設計"。

另一方面需要考慮的因素就是“人",有沒有經歷過微服務項目的人,團隊是否有 DevOps 文化等等,綜合考量是否需要微服務化。

微服務的好處是什么?

  • 相比于單體應用,每個服務的復雜度會下降,特別是數據層面(數據表關系)更清晰,不會一個應用上百張表,新員工上手快。
  • 對于穩(wěn)定的核心業(yè)務可以單獨成為一個服務,降低該服務的發(fā)布頻率,也減少測試人員壓力。
  • 可以將不同密集型的服務搭配著放到物理機上,或者單獨對某個服務進行擴容,實現硬件資源的充分利用。
  • 部署靈活,在私有化項目中,如果客戶有不需要的業(yè)務,那么對應的微服務就不需要部署,節(jié)省硬件成本,就像上文提到的樂高積木理念。

微服務有什么挑戰(zhàn)?

  • 一旦設計不合理,交叉調用,相互依賴頻繁,就會出現牽一發(fā)動全身的局面。想象單個應用內 Service 層依賴復雜的場面就明白了。
  • 項目多了,輪子需求也會變多,需要有人專注公共代碼的開發(fā)。
  • 開發(fā)過程的質量需要通過持續(xù)集成(CI)嚴格把控,提高自動化測試的比例,因為往往一個接口改動會涉及多個項目,光靠人工測試很難覆蓋所有情況。
  • 發(fā)布過程會變得復雜,因為微服務要發(fā)揮全部能力需要容器化的加持,容器編排就是***的挑戰(zhàn)。
  • 線上運維,當系統(tǒng)出現問題需要快速定位到某個機器節(jié)點或具體服務,監(jiān)控和鏈路日志分析都必不可少。

下面詳細說說我們是怎么應對這些挑戰(zhàn)的。

開發(fā)過程的挑戰(zhàn)

持續(xù)集成

通過 CI 將開發(fā)過程規(guī)范化,串聯自動化測試和人工 Review。

 

我們使用 Gerrit 作為代碼&分支管理工具,在流程管理上遵循 GitLab 的工作流模型:

  • 開發(fā)人員提交代碼至 Gerrit 的 Magic 分支。
  • 代碼 Review 人員 Review 代碼并給出評分。
  • 對應 Repo 的 Jenkins job 監(jiān)聽分支上的變動,觸發(fā) Build job。經過 IT 和 Sonar 的靜態(tài)代碼檢查給出評分。
  • Review 和 Verify 皆通過之后,相應 Repo 的負責人將代碼 Merge 到真實分支上。
  • 若有一項不通過,代碼修改后重復過程。
  • Gerrit 將代碼實時同步備份至兩個遠程倉庫中。

集成測試

一般來說代碼自動執(zhí)行的都是單元測試(Unit Test),即不依賴任何資源(數據庫,消息隊列)和其他服務,只測試本系統(tǒng)的代碼邏輯。

但這種測試需要 Mock 的部分非常多,一是寫起來復雜,二是代碼重構起來跟著改的測試用例也非常多,顯得不夠敏捷。而且一旦要求開發(fā)團隊要達到某個覆蓋率,就會出現很多造假的情況。

所以我們選擇主要針對 API 進行測試,即針對 Controller 層的測試。另外對于一些公共組件如分布式鎖,Json 序列化模塊也會有對應的測試代碼覆蓋。

測試代碼在運行時會采用一個隨機端口拉起項目,并通過 HTTP Client 對本地 API 發(fā)起請求,測試只會對外部服務做 Mock,數據庫的讀寫,消息隊列的消費等都是真實操作,相當于把 Jmeter 的事情在 Java 層面完成一部分。

Spring Boot 項目可以很容易的啟動這樣一個測試環(huán)境,代碼如下:

 

測試過程的 HTTP Client 推薦使用 io.rest-assured:rest-assured 支持 JsonPath,十分好用。

測試時需要注意的一個點是測試數據的構造和清理。構造又分為 Schema 的創(chuàng)建和測試數據的創(chuàng)建:

  • Schema 由 Flyway 處理,在啟用測試環(huán)境前先刪除所有表,再進行表的創(chuàng)建。
  • 測試數據可以通過 @Sql 讀取一個 SQL 文件進行創(chuàng)建,在一個用例結束后再清除這些數據。

順帶說一下,基于 Flyway 的 Schema Upgrade 功能我們封成了獨立的項目,每個微服務都有自己的 Upgrade 項目。

好處:一是支持 command-line 模式,可以細粒度的控制升級版本;二是也可以支持分庫分表以后的 Schema 操作。Upgrade項目也會被制作成 Docker image 提交到 Docker hub。

測試在每次提交代碼后都會執(zhí)行,Jenkins 監(jiān)聽 Gerrit 的提交,通過 docker run -rm {upgrade 項目的 image}先執(zhí)行一次 Schema Upgrade,然后 Gradle test 執(zhí)行測試。

最終會生成測試報告和覆蓋率報告,覆蓋率報告采用 JaCoCo 的 Gradle 插件生成,如下圖:

這里多提一點,除了集成測試,服務之間的接口要保證兼容,實際上還需要一種 consumer-driven testing tool。

就是說接口消費端先寫接口測試用例,然后發(fā)布到一個公共區(qū)域,接口提供方發(fā)布接口時也會執(zhí)行這個公共區(qū)域的用例,一旦測試失敗,表示接口出現了不兼容的情況。

比較推薦大家使用 Pact 或是 Spring Cloud Contact。我們目前的契約基于“人的信任”,畢竟服務端開發(fā)者還不多,所以沒有必要使用這樣一套工具。

集成測試的同時還會進行靜態(tài)代碼檢查,我們用的是 Sonar,當所有檢查通過后 Jenkins 會 +1 分,再由 Reviewer 進行代碼 Review。

自動化測試

單獨拿自動化測試出來說,就是因為它是質量保證的非常重要的一環(huán),上文能在 CI 中執(zhí)行的測試都是針對單個微服務的。

那么當所有服務(包括前端頁面)都在一起工作的時候是否會出現問題,就需要一個更接近線上的環(huán)境來進行測試了。

在自動化測試環(huán)節(jié),我們結合 Docker 提高一定的工作效率并提高測試運行時環(huán)境的一致性以及可移植性。

 

在準備好基礎的 Pyhton 鏡像以及 Webdriver(Selenium)之后,我們的自動化測試工作主要由以下主要步驟組成:

  • 測試人員在本地調試測試代碼并提交至 Gerrit。
  • Jenkins 進行測試運行時環(huán)境的鏡像制作,主要將引用的各種組件和庫打包進一個 Python 的基礎鏡像。
  • 通過 Jenkins 定時或手動觸發(fā),調用環(huán)境部署的 Job 將專用的自動化測試環(huán)境更新,然后拉取自動化測試代碼啟動一次性的自動化測試運行時環(huán)境的 Docker 容器,將代碼和測試報告的路徑鏡像至容器內。
  • 自動化測試過程將在容器內進行。
  • 測試完成之后,不必手動清理產生的各種多余內容,直接在 Jenkins 上查看發(fā)布出來的測試結果與趨勢。

 

關于部分性能測試的執(zhí)行,我們同樣也將其集成到 Jenkins 中,在可以直觀的通過一些結果數值來觀察版本性能變化情況的回歸測試和基礎場景,將會很大程度的提高效率,便捷的觀察趨勢:

  • 測試人員在本地調試測試代碼并提交至 Gerrit。
  • 通過 Jenkins 定時或手動觸發(fā),調用環(huán)境部署的 Job 將專用的性能測試環(huán)境更新以及可能的 Mock Server 更新。
  • 拉取***的性能測試代碼,通過 Jenkins 的性能測試插件來調用測試腳本。
  • 測試完成之后,直接在 Jenkins 上查看通過插件發(fā)布出來的測試結果與趨勢。

發(fā)布過程的挑戰(zhàn)

上面提到微服務一定需要結合容器化才能發(fā)揮全部優(yōu)勢,容器化就意味著線上有一套容器編排平臺。我們目前采用是 Redhat 的 OpenShift。

所以發(fā)布過程較原來只是啟動 Jar 包相比要復雜的多,需要結合容器編排平臺的特點找到合適的方法。

鏡像準備

公司開發(fā)基于 GitLab 的工作流程,Git 分支為 Master,Pre-production和 Prodution 三個分支,同時生產版本發(fā)布都打上對應的 Tag。

每個項目代碼里面都包含 Dockerfile 與 Jenkinsfile,通過 Jenkins 的多分支 Pipeline 來打包 Docker 鏡像并推送到 Harbor 私庫上。

 

Docker 鏡像的命令方式為:項目名/分支名:git_commit_id,如 funnel/production:4ee0b052fd8bd3c4f253b5c2777657424fccfbc9。

Tag 版本的 Docker 鏡像命名為:項目名 /release:tag 名,如 funnel/release:18.10.R1。

 

在 Jenkins 中執(zhí)行 build docker image job 時會在每次 Pull 代碼之后調用 Harbor 的 API 來判斷此版本的 Docker image 是否已經存在,如果存在就不執(zhí)行后續(xù)編譯打包的 Stage。

在 Jenkins 的發(fā)布任務中會調用打包 Job,避免了重復打包鏡像,這樣就大大的加快了發(fā)布速度。

數據庫 Schema 升級

數據庫的升級用的是 Flyway,打包成 Docker 鏡像后,在 OpenShift 中創(chuàng)建 Job 去執(zhí)行數據庫升級。

Job 可以用最簡單的命令行的方式去創(chuàng)建:

 

腳本升級任務也集成在 Jenkins 中。

容器發(fā)布

OpenShift 有個特別概念叫 DeploymentConfig,原生 Kubernetes Deployment 與之相似,但 OpenShift 的 DeploymentConfig 功能更多。

DeploymentConfig 關聯了一個叫做 ImageStreamTag 的東西,而這個 ImagesStreamTag 和實際的鏡像地址做關聯,當 ImageStreamTag 關聯的鏡像地址發(fā)生了變更,就會觸發(fā)相應的 DeploymentConfig 重新部署。

我們發(fā)布是使用了 Jenkins+OpenShift 插件,只需要將項目對應的 ImageStreamTag 指向到新生成的鏡像上,就觸發(fā)了部署。

 

如果是服務升級,已經有容器在運行怎么實現平滑替換而不影響業(yè)務呢?

配置 Pod 的健康檢查,Health Check 只配置了 ReadinessProbe,沒有用 LivenessProbe。

因為 LivenessProbe 在健康檢查失敗之后,會將故障的 Pod 直接干掉,故障現場沒有保留,不利于問題的排查定位。而 ReadinessProbe 只會將故障的 Pod 從 Service 中踢除,不接受流量。

使用了 ReadinessProbe 后,可以實現滾動升級不中斷業(yè)務,只有當 Pod 健康檢查成功之后,關聯的 Service 才會轉發(fā)流量請求給新升級的 Pod,并銷毀舊的 Pod。

[[261419]]

 

線上運維的挑戰(zhàn)

服務間調用

Spring Cloud 使用 Eruka 接受服務注冊請求,并在內存中維護服務列表。

當一個服務作為客戶端發(fā)起跨服務調用時,會先獲取服務提供者列表,再通過某種負載均衡算法取得具體的服務提供者地址(IP + Port),即所謂的客戶端服務發(fā)現。在本地開發(fā)環(huán)境中我們使用這種方式。

由于 OpenShift 天然就提供服務端服務發(fā)現,即 Service 模塊,客戶端無需關注服務發(fā)現具體細節(jié),只需知道服務的域名就可以發(fā)起調用。

由于我們有 Node.js 應用,在實現 Eureka 的注冊和去注冊的過程中都遇到過一些問題,不能達到生產級別。

所以決定直接使用 Service 方式替換掉 Eureka,也為以后采用 Service Mesh 做好鋪墊。

具體的做法是,配置環(huán)境變量:

  1. EUREKA_CLIENT_ENABLED=false,RIBBON_EUREKA_ENABLED=false 

并將服務列表如:

  1. FOO_RIBBON_LISTOFSERVERS: '[http://foo:8080](http://foo:8080/)' 

寫進 ConfigMap 中,以 envFrom: configMapRef 方式獲取環(huán)境變量列表。

如果一個服務需要暴露到外部怎么辦,比如暴露前端的 HTML 文件或者服務端的 Gateway。

OpenShift 內置的 HAProxy Router,相當于 Kubernetes 的 Ingress,直接在 OpenShift 的 Web 界面里面就可以很方便的配置。

我們將前端的資源也作為一個 Pod 并有對應的 Service,當請求進入 HAProxy 符合規(guī)則就會轉發(fā)到 UI 所在的 Service。

Router 支持 A/B test 等功能,唯一的遺憾是還不支持 URL Rewrite。

 

對于需要 URL Rewrite 的場景怎么辦?那么就直接將 Nginx 也作為一個服務,再做一層轉發(fā)。流程變成 Router → Nginx Pod → 具體提供服務的 Pod。

鏈路跟蹤

開源的全鏈路跟蹤很多,比如 Spring Cloud Sleuth + Zipkin,國內有美團的 CAT 等等。

其目的就是當一個請求經過多個服務時,可以通過一個固定值獲取整條請求鏈路的行為日志,基于此可以再進行耗時分析等,衍生出一些性能診斷的功能。

不過對于我們而言,首要目的就是 Trouble Shooting,出了問題需要快速定位異常出現在什么服務,整個請求的鏈路是怎樣的。

為了讓解決方案輕量,我們在日志中打印 RequestId 以及 TraceId 來標記鏈路。

RequestId 在 Gateway 生成表示唯一一次請求,TraceId 相當于二級路徑,一開始與 RequestId 一樣,但進入線程池或者消息隊列后,TraceId 會增加標記來標識唯一條路徑。

舉個例子,當一次請求向 MQ 發(fā)送一個消息,那么這個消息可能會被多個消費者消費,此時每個消費線程都會自己生成一個 TraceId 來標記消費鏈路。加入 TraceId 的目的就是為了避免只用 RequestId 過濾出太多日志。

實現上,通過 ThreadLocal 存放 APIRequestContext 串聯單服務內的所有調用。

當跨服務調用時,將 APIRequestContext 信息轉化為 HTTP Header,被調用方獲取到 HTTP Header 后再次構建 APIRequestContext 放入 ThreadLocal,重復循環(huán)保證 RequestId 和 TraceId 不丟失即可。

如果進入 MQ,那么 APIRequestContext 信息轉化為 Message Header 即可(基于 RabbitMQ 實現)。

當日志匯總到日志系統(tǒng)后,如果出現問題,只需要捕獲發(fā)生異常的 RequestId 或是 TraceId 即可進行問題定位。

 

經過一年來的使用,基本可以滿足絕大多數 Trouble Shooting 的場景,一般半小時內即可定位到具體業(yè)務。

容器監(jiān)控

容器化前監(jiān)控用的是 Telegraf 探針,容器化后用的是 Prometheus,直接安裝了 OpenShift 自帶的 cluster-monitoring-operator。

自帶的監(jiān)控項目已經比較全面,包括 Node,Pod 資源的監(jiān)控,在新增 Node 后也會自動添加進來。

Java 項目也添加了 Prometheus 的監(jiān)控端點,只是可惜 cluster-monitoring-operator 提供的配置是只讀的,后期將研究怎么將 Java 的 JVM 監(jiān)控這些整合進來。

 

總結

開源軟件是對中小團隊的一種福音,無論是 Spring Cloud 還是 Kubernetes 都大大降低了團隊在基礎設施建設上的時間成本。

當然其中有更多的話題,比如服務升降級,限流熔斷,分布式任務調度,灰度發(fā)布,功能開關等等都需要更多時間來探討。

對于小團隊,要根據自身情況選擇微服務的技術方案,不可一味追新,適合自己的才是***的。

 

 

責任編輯:武曉燕 來源: Docker
相關推薦

2015-01-08 10:08:03

前后端分離

2024-08-20 09:59:22

2019-01-11 09:41:56

網易考拉服務架構微服務

2022-04-28 09:36:51

微服務性能云原生

2021-04-26 18:13:37

微服務模式數據庫

2019-02-25 09:30:00

微服務代碼小團隊

2020-06-09 22:05:44

NGINX微服務架構

2023-11-06 08:55:31

2023-09-02 20:55:04

微服務架構

2021-05-20 13:22:31

架構運維技術

2018-06-01 23:08:01

Spring Clou微服務服務器

2020-04-27 10:20:07

微服務架構數據庫

2022-11-08 08:35:53

架構微服務移動

2021-01-22 17:46:37

微服務開源Web

2022-01-04 07:00:21

模型微服務架構

2024-06-05 12:03:43

微服務架構場景

2020-08-06 08:17:52

FaaS平臺Serverless

2019-08-06 13:37:55

微服務架構數據

2019-10-16 08:41:46

微服務架構Nginx

2021-04-13 17:40:55

微服務架構模式
點贊
收藏

51CTO技術棧公眾號