分散式配置中心之思考

挑戰者V發表於2021-05-23

一、為什麼需要分散式配置中心?它能解決什麼問題?

從解決問題層面進行切入,它能解決配置混亂難管理的問題。

過去傳統式開發,一個SSM框架開發的單體應用通常會有如下配置:

  • spring-mybatis.xml;
  • spring-mvc.xml;
  • mybatis.xml;
  • web.xml;
  • jdbc.properties;
  • log4j.properties;
  • spring-redis.xml;
  • spring-mongodb.xml;
  • mapper目錄下有若干xml。

當這個單體應用因為某種原因(新來的架構師按照微服務的方式進行重構以及拆分(逐步開展)、專案經理為了新的需求-新建專案(一般老專案不能輕易動,保險起見)等),這個時候就涉及到一個問題,新的專案目錄結構與原來的可能一致,但配置檔案基本上相同,這時將老專案的配置檔案複製到新的專案,除非新的專案採取新的技術,否則仍然按照之前老專案的規範來,這個場景相信不少的朋友都遇到過。假如是兩三個專案還好,如果這時要拆分為七八個甚至二十個,那麼這樣的工作將非常繁瑣,同時維護上會很困難(稍不留神漏掉一個,最後一上線發現資料不對,原來連的還是開發環境的資料庫,這時只得重新部署)。由此看來,分散式配置中心的主要作用在於對配置檔案的統一管理,減少重複性工作,提高整體研發團隊的效率(開發、測試、運維等)
除此外統一管理體現的好處有安全性(可採用某種加密的方式進行關鍵配置資料加密,同時過去配置在程式碼裡,如果程式碼被人反編譯破解就可能導致密碼之類的東西被洩漏等)、時效性(從兩個方面來說,第一個方面是修改後重啟才能生效,第二個是當時修改即刻生效)。
歸納地概括,因為多個專案場景中面臨配置檔案過於分散、修改追根溯源困難、環境容易搞混、程式碼與配置檔案耦合等問題,我們需要分散式配置中心,而分散式配置中心恰好就能解決這樣的問題。

二、分散式配置中心在實際中會面臨哪些問題?

以Nacos為例,目前我使用Nacos作為分散式服務註冊中心,而Nacos恰好整合了分散式配置管理。Nacos中的配置管理,就是管理配置檔案的,而這些配置檔案內容儲存在MySQL。如果MySQL遭遇一些意外如磁碟空間滿了、黑客攻擊、連線過多、低效率的SQL導致記憶體消耗極大等,那麼Nacos也會處於掛掉或當機狀態(停止服務)等,這樣也會直接導致一些微服務處理故障,雖然不在一個伺服器上或者是連線的業務資料庫不一樣,但共同點都是讀取Nacos統一管理下的配置。針對這樣的問題一般從三個方面入手:

  • 第一個方面,運維從監控策略(提前預警,做好應對)、伺服器安全策略(防止攻擊)、服務可用性策略(包含叢集)等;
  • 第二個方面,開發從寫程式碼入手,遵守規範(程式碼規範),邏輯嚴謹(程式邏輯考慮較為全面),合理呼叫API(明白每個API的優缺點,進行合理組裝,避免效能瓶頸)等;
  • 第三個方面,測試從效能測試入手,模擬多人使用或非法攻擊的場景等。

上面列舉的僅僅是配置中心在實際落中面臨的重大問題之一,除此之外還有就是如何規範管理配置(因為並不是所有的配置都需要放到配置中心進行統一管理,如果所有的微服務配置均放到分散式配置中心來管理,那麼也會面臨一個大問題就是如何管理好這些配置,一旦管理不好,就可能變成了體力勞動,違背了分散式配置中心的初衷)。

在提到規範管理之前,回到一個問題上,這個問題是究竟什麼樣的配置檔案應該放在分散式配置中心?
我的回答是通用性配置,以我部落格為例,application-dev.yml配置內容(我將jwt和鑑權、ribbon、hystrix等通用性配置放入了Nacos的配置管理):

# JWT配置
jwt:
  # 密匙KEY
  secret: JWTSecret
  # HeaderKEY
  tokenHeader: Authorization
  # Token字首字元
  tokenPrefix: challenger-
  # 過期時間 單位秒 1天后過期=86400 7天后過期=604800
  expiration: 86400
  # 配置不需要認證的介面
  antMatchers: /login/**,/user/register,/api-doc/**,/login/**,/favicon.ico,/doc.html,/webjars/**,/swagger-resources,/v2/api-docs/**,/druid/**,/cnblogs/**,/user/**
  # 有效時間
  validTime: 7
ribbon:
  okhttp:
    enabled: true #
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 預設為;輪詢,這裡改為隨機
  ConnectTimeout: 5000 # 連線超時時間(ms)
  ReadTimeout: 5000 # 通訊超時時間(ms)
hystrix:
  enabled: true
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 6000 #

那麼在規範性方面該如何落地?這與公司的實際情況有關,每家公司的業務、研發團隊的綜合素質等均存在差異性,而在規範性上就需要找到適合該公司研發團隊的。但適合很難,都是從坑坑窪窪中摸索出來的。

以我個人經驗來看(結合近來的坑),從以下入手:

  • 通用性配置管理,公共通用性配置檔案和業務通用性配置檔案,放入分散式配置中心進行管理;
  • 分類配置管理,不同環境(dev、test、prod)放入不同的分散式配置中心進行管理;
  • 差異性配置管理,差異性配置檔案放入具體的微服務專案,衡量差異性的標準是該配置只在此處用到,其它微服務均不涉及。

三、分散式配置中心的技術選型

關於這一方面,我特別查閱了相關資料,有博友將分散式配置中心的技術選型歸納為如下:

  • Disconf;
  • Spring Cloud Config;
  • Apollo;
  • Nacos。

目前用的比較多的,一個是SpringCloud Config,相當於是SpringCloud原生自帶,不過該分散式配置中心的儲存主要為SVN和Git,也有部分人採用本地儲存的方式(儲存在某個伺服器上),另一個是Apollo,然後就是Nacos,至於Disconf早就不維護了,相當於落伍,GitHub如圖:

對於早就不維護的,一般技術選型不考慮,關於技術選型需要考慮哪些東西,感興趣的朋友可以閱讀我的這篇文章:
從單體架構到分散式微服務架構的思考

四、SpringCloud Alibaba之分散式配置中心整合(以Nacos作為分散式配置中心)

1.新增Maven依賴

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<!-- SpringCloud Ailibaba Nacos Config -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

2.bootstrap.yml配置

cloud:
   nacos:
     discovery:
       # 服務註冊地址
       server-addr: 127.0.0.1:8848
     config:
       # 配置中心地址
       server-addr: 127.0.0.1:8848
       # 配置檔案格式
       file-extension: yml
       # 共享配置
       shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

3.例子

(1)通過nacos新建一個配置檔案

(2)bootstrap.yml配置

cloud:
   nacos:
     discovery:
       # 服務註冊地址
       server-addr: 127.0.0.1:8848
     config:
       # 配置中心地址
       server-addr: 127.0.0.1:8848
       # 配置檔案格式
       file-extension: yml
       # 共享配置
       shared-dataids: blog.properties,application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

(3)程式碼讀取

a.Environment讀取
@Autowired
private Environment env

env.getProperty("api_url")
b.註解讀取
@Value("${api_url}")
private String apiUrl;

(4)如果想實時更新的話需要配置兩個地方(兩者缺一不可,nacos版本為1.3.1)

a.配置檔案
cloud:
  nacos:
    discovery:
      # 服務註冊地址
      server-addr: 127.0.0.1:8848
    config:
      # 配置中心地址
      server-addr: 127.0.0.1:8848
      # 配置檔案格式
      file-extension: yml
      # 共享配置
      shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension},blog.properties
      refresh-enabled: true
      refreshable-dataids: blog.properties
b.註解
@RefreshScope

 

相關文章