TO BANK解決方案微服務架構的正確姿勢

語言: CN / TW / HK

theme: smartblue

概述

我們公司是一家TO B企業,主要客戶是中大型銀行,區別於to C的業務模式,我們主要是為不同的銀行客戶提供解決方案,他們有個特點,基本都是私有云、本地化部署。那麼在這個過程中我們公司要面臨和很多C端應用服務不一樣的挑戰。

  1. 不同銀行客戶微服務化程序不一樣,有的使用了某些微服務服務元件
  2. 不同銀行客戶技術選型不一樣,有的是用eureka作為註冊中心,有的用nacos等
  3. 不同銀行客戶的微服務規範不一樣,比如光大銀行的服務名必須要加特定的字首和字尾等
  4. 服務之間支援多種呼叫方式,可以通過服務名呼叫,也要通過url呼叫
  5. ..........

什麼是微服務化

微服務架構(Microservice Architecture)是一種架構概念,旨在通過將功能分解到各個離散的服務中以實現對解決方案的解耦。

微服務是一種架構風格,一個大型複雜軟體應用由一個或多個微服務組成。系統中的各個微服務可被獨立部署,各個微服務之間是松耦合的。每個微服務僅關注於完成一件任務並很好地完成該任務。在所有情況下,每個任務代表著一個小的業務能力。

單體架構

優點:

  • 開發簡單直接,集中式管理,基本不會重複開發
  • 功能都在本地,沒有分散式的管理開銷和呼叫開銷。

缺點:

  • 開發效率低:所有的開發在一個專案改程式碼,遞交程式碼相互等待,程式碼衝突不斷
  • 程式碼維護難:程式碼功能耦合在一起,新人不知道何從下手
  • 部署不靈活:構建時間長,任何小修改必須重新構建整個專案,這個過程往往很長
  • 穩定性不高:一個微不足道的小問題,可以導致整個應用掛掉
  • 擴充套件性不夠:無法滿足高併發情況下的業務需求

微服務架構

優點:

  • 每個服務為獨立的業務開發,單獨部署,跑在自己的程序中。
  • 自動化測試、部署、運維( DevOps )。
  • 快速演化、快速迭代。
  • 整個業務由一系列的獨立的服務共同組成系統。
  • 高度容錯性、高可用、高併發。
  • 天然支援雲原生

缺點:

  • 服務規模大,部署、運維、管理難度大。
  • 服務間呼叫關係複雜,呼叫鏈路長,排障難度大。
  • 服務間通訊成本變大,效能和容錯帶來的挑戰。
  • 服務間依賴較多,系統整合、測試難度變大。
  • 開發人員技術能力挑戰,各服務間重複程式碼,重複建設等。
  • 叢集規模大,功能效能監控、告警帶來的挑戰。
  • 大規模分散式,資料一致性帶來的挑戰。
  • 需求和版本協調複雜度大大增加,測試難度也增加。
  • 對基礎架構要求大大提高,規模大幅增加。

結合我們公司的業務特點,TO B 使用者流量小,儘量部署建議,其實採用單體架構更合適,那是什麼原因讓我們最終選擇走微服務這條道路呢?

  1. 隨著銀行IT架構的升級,越來越多的銀行客戶採用微服務化架構,微服務和雲原生已經成為客戶招投標的重要指標。
  2. 公司要持續保持架構的先進性。

公司微服務架構

公司架構發展歷程

第一階段(2010年~2014年):

  • 採用傳統的SpringMVC + Mybatis,XML的方式配置
  • 部署到獨立的tomcat容器中

第二階段(2015年~2020年):

  • 使用springboot框架,版本也從1.3.x —> 2.3.x
  • 使用內嵌的tomcat容器,jar包方式啟動
  • 規則平臺、後臺等元件之間通過http呼叫

第三階段(2021年~2022年):

  • 使用spring cloud微服務框架
  • 接入註冊中心、配置中心、閘道器等微服務治理元件
  • 拆分出portal服務、名單服務等,服務之間通過open feign呼叫

總體架構

介面請求流程

瀏覽器請求通過nginx代理,轉發到閘道器,閘道器根據服務名路由到不同的服務元件中,不用再像以前,啟動一個節點需要在nginx大量配置ip、埠。

nginx配置:

閘道器配置:

服務拆分

拆分原則:

  1. 單一職責原、高內聚低耦合
  2. 服務粒度適中,服務不能太細
  3. 以業務模型為切入點
  4. 演進式拆分:剛開始的時候後不要拆的太細,可以隨著迭代過程逐步優化
  5. 儘量避免環形依賴與雙向依賴

拆分結果:

  • portal作為獨立服務,提供使用者、角色、機構管理的能力
  • 決策平臺服務
  • 後臺服務
  • 決策引擎服務
  • ......

認證授權

公司在第二階段springboot應用時期,會話管理採用的是spring session的方式,但它不是微服務的主流解決方案, 而且第三方應用、手機端等接入難度大。市面主流都是採用token的方式,因此我們決定通過基於jwt token + 快取的認證方式。

服務治理

註冊中心

什麼是註冊中心? 註冊中心可以說是微服務架構中的”通訊錄“,它記錄了服務和服務地址的對映關係。在分散式架構中,服務會註冊到這裡,當服務需要呼叫其它服務時,就到這裡找到服務的地址,進行呼叫。這就是我們常常說的服務註冊和發現。

目標: 滿足不同的銀行客戶使用不同的註冊中心,比如光大銀行使用consul, 興業銀行使用eureka等。評估了各個銀行的微服務情況,我們的解決方案計劃相容主流的eureka、nacos、consul作為註冊中心。

實現方案:

  1. 公司微服務核心包中引入nacos, eureka, consul的依賴。

  1. 在bootstrap.yml整合nacos、eureka、consul的配置。

  1. 通過實現Spring提供的切入點EnvironmentPostProcessor,改寫原生配置中心的配置,以nacos工程為例。

``` public class NacosDiscoveryEnvironmentPostProcessor implements EnvironmentPostProcessor {

@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
    // 讀取bootstrap.yml配置項中的配置
    String discoveryType = environment.getProperty("fit.common.cloud.discovery");
    // 判斷是否配置了nacos
    boolean nacosEnabled = "nacos".equals(discoveryType);
    LinkedHashMap<String, Object> map = new LinkedHashMap<>();
    // 設定nacos作為註冊中心是否啟用
    map.put("spring.cloud.nacos.discovery.enabled", nacosEnabled);
    map.put("ribbon.nacos.enabled", nacosEnabled);
    MapPropertySource propertySource = new MapPropertySource("nacosEnableInfo", map);
    // 新增到environment中
    environment.getPropertySources().addLast(propertySource);

}

} ```

缺點:

  • 引入了多餘的依賴

配置中心

配置中心,顧名思義,將配置中心化,說白了就是將配置從應用中抽取出來,統一管理,優雅的解決了配置的動態變更、許可權管理、持久化、運維成本等問題。應用程式自身只是從配置中心拿到自己想要的配置,既不需要去新增管理配置的介面,也不需要自己去實現配置的持久化,更不需要去關心配置何時變化。配置與應用程式隔離開,單獨管理配置。

目標: 滿足不同的銀行客戶有不同的配置中心選型,比如光大銀行使用consul, vivo使用apollo等。評估了各個銀行的微服務情況,我們的解決方案計劃相容主流的nacos、consul、apollo作為配置中心。

實現方案: 實現思路和上面的註冊中心一樣。

服務呼叫

在springcloud微服務的實際專案開發中,多個微服務之間不僅是相對獨立的,而且也是相對關聯的;也就是說,微服務之間需要相互訪問,多個微服務之間的介面可能會被互相多次呼叫,我們稱之為微服務之間的呼叫。

目標:

  1. 服務訪問支援通過open feign的方式呼叫
  2. 服務訪問支援修改服務名,因為不通銀行的服務名可能發生變化
  3. 服務訪問需要支援通過指定ip埠訪問,比如浙商專案的大資料元件由於網路原因,無法通過服務名訪問,需要配置指定的url

實現方案:

  1. 微服務核心包中新增cloud-feign模組,引入openfeign相關的依賴

  1. 為了實現feign呼叫過程中,帶上許可權資訊,需要在攔截器中新增token。

``` @Slf4j @Component public class FeignRequestInterceptor implements RequestInterceptor {

private final String AUTHORIZATION_HEADER = "Authorization";

@Autowired
private RestUserAcctProperties restUserAcctProperties;

@Override
public void apply(RequestTemplate requestTemplate) {
    ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
    if (attributes != null) {
        HttpServletRequest request = attributes.getRequest();
        // 攜帶token
        String authorization = request.getHeader(AUTHORIZATION_HEADER);
        if (!StringUtils.isEmpty(authorization)) {
            requestTemplate.header("Authorization", authorization);
            log.debug("feign token filter, url:[{}], token: [{}]", request.getRequestURI(), authorization);
            return;
        }
    }

    String encoded = Base64Utils.encodeToString((restUserAcctProperties.getSubscription().getUsername() + ":"
        + restUserAcctProperties.getSubscription().getPassword()).getBytes());
    requestTemplate.header("Authorization", "Basic " + encoded);
}

} ```

  1. 服務提供方,以jar包的形式提供對外開放使用的介面, 比如名單平臺提供namelist-api.jar,暴露可以呼叫的介面。

  1. 服務呼叫方,依賴服務提供方的jar包,新增對應的Feign註解。

  • 1標記顯示使用Feign的註解
  • 2標記顯示繼承名單服務暴露的介面,被Feign管理

  • 通過@FeignClient註解的屬性配置實現服務名的動態調整以及使用url呼叫。

  • name表示呼叫的服務名,支援從配置檔案讀取

  • url表示呼叫的地址,如果url有值優先讀取該地址去訪問,支援從配置檔案讀取。

服務熔斷降級

一個服務常常會呼叫別的模組,可能是另外的一個遠端服務、資料庫,或者第三方 API 等。例如,支付的時候,可能需要遠端呼叫銀聯提供的 API;查詢某個商品的價格,可能需要進行資料庫查詢。然而,這個被依賴服務的穩定性是不能保證的。如果依賴的服務出現了不穩定的情況,請求的響應時間變長,那麼呼叫服務的方法的響應時間也會變長,執行緒會產生堆積,最終可能耗盡業務自身的執行緒池,服務本身也變得不可用。

實現方式

  1. Hystrix
  2. Sentinel

由於Hystrix已經停止維護,加上Sentinel社群比較活躍,最終選擇適用了Sentinel。

Sentinel 是面向分散式、多語言異構化服務架構的流量治理元件,主要以流量為切入點,從流量路由、流量控制、流量整形、熔斷降級、系統自適應過載保護、熱點流量防護等多個維度來幫助開發者保障微服務的穩定性。

Sentinel 可以簡單的分為 Sentinel 核心庫和 Dashboard。核心庫不依賴 Dashboard,但是結合 Dashboard 可以取得最好的效果,Dashboard可以介面配置規則並且實時生效。

解決方案中實踐:

  1. 解決方案中只使用了Sentinel 核心庫,沒有適用Dashboard,如果新增Dashboard需要增加額外的元件,增加解決方案的負擔。
  2. 通過open feign整合Sentinel實現熔斷降級
  3. 引入sentinel 依賴
  4. 啟用OpenFeign整合Sentinel的自動配置,解決方案中預設開啟

feign: sentinel: enabled: true

  1. 自定義Feign.Builder, 提供預設兜底的降級策略, 返回提示“遠端訪問失敗,介面熔斷”。

  1. 可以自定義降級策略, 優先使用自定義策略。

問題:

  1. 目前降級規則使用全域性預設的,比如服務掛掉,會執行降級策略,不支援配置,後續優化。

總結

目前公司的微服務架構的解決方案已經在光大銀行、浙商等銀行中落地,滿足他們的基本功能。但還需要不斷迭代完善,比如服務的限流、鏈路追蹤,分散式事務等需要在後續持續整合到我們的解決方案中。

我正在參與掘金技術社群創作者簽約計劃招募活動,點選連結報名投稿