從單體架構到微服務
單體架構
Web應用程序發展的早期,大部分web工程師將所有的功能模塊打包到一起並放在一個web容器中運行,所有功能
模塊使用同一個數據庫,同時,它還提供API或者UI訪問的web模塊等。
盡管也是模塊化邏輯,但是最終它還是會打包並部署為單體式應用,這種將所有功能都部署在一個web容器中運行
的系統就叫做單體架構(也叫:巨石型應用)。
單體架構有很多好處:
- 開發效率高:模塊之間交互采用本地方法調用,並節省微服務之間的交互討論時間與開發成本。
- 容易測試:IDE都是為開發單個應用設計的、容易測試——在本地就可以啟動完整的系統。
- 容易部署:運維成本小,直接打包為一個完整的包,拷貝到web容器的某個目錄下即可運行。
但是,上述的好處是有條件的,它適用於小型簡單應用,對於大規模的復雜應用,就會展現出來以下的不足:
- 復雜性逐漸變高,可維護性逐漸變差 :所有業務模塊部署在一起,復雜度越來越高,修改時牽一發動全身。
- 版本迭代速度逐漸變慢:修改一個地方就要將整個應用全部編譯、部署、啟動時間過長、回歸測試周期過長。
- 阻礙技術創新:若更新技術框架,除非你願意將系統全部重寫,無法實現部分技術更新。
- 無法按需伸縮:通過冗余部署完整應用的方式來實現水平擴展,無法針對某業務按需伸縮。
微服務
許多大型公司,通過采用微服務架構解決了上述問題。其思路不是開發一個巨大的單體式的應用,而是將應用分解為小的、互相連接的微服務。
一個微服務一般完成某個特定的功能,比如訂單服務、用戶服務等等。每一個微服務都是完整應用,都有自己的業務邏輯和數據庫。一些微服務還會發布API給其它微服務和應用客戶端使用。
比如,根據前面描述系統可能的分解如下:
每一個業務模塊都使用獨立的服務完成,這種微服務架構模式也影響了應用和數據庫之間的關系,不像傳統多個業務模塊共享一個數據庫,微服務架構每個服務都有自己的數據庫。
微服務架構的好處:
- 分而治之,職責單一;易於開發、理解和維護、方便團隊的拆分和管理
- 可伸縮;能夠單獨的對指定的服務進行伸縮
- 局部容易修改,容易替換,容易部署,有利於持續集成和快速迭代
- 不會受限於任何技術棧
分布式應用配置管理
下圖展示了如何通過Nacos集中管理多個服務的配置:
用戶通過 Nacos Server的控制台集中對多個服務的配置進行管理。各服務統一從 Nacos Server中獲取各自的配置,並監聽配置的變化。
發布配置
首先在nacos發布配置,我們規划了兩個服務service1、service2,並且想對這兩個服務的配置進行集中維護。打開nacos控制台,並點擊菜單配置管理->配置列表:
在Nacos添加如下的配置:
創建項目
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.1.3.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.1.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
啟動類:
@SpringBootApplication @RestController public class Service1Application { public static void main(String[] args) { SpringApplication.run(Service1Application.class, args); } @Autowired ConfigurableApplicationContext applicationContext; @GetMapping("/port") public String getPort() { //讀取配置信息 return applicationContext.getEnvironment().getProperty("server.port"); } @GetMapping("/configs") public String getConfigs() { //讀取配置信息 return applicationContext.getEnvironment().getProperty("common.name"); } @GetMapping(value = "/configs2") public String getConfigs2() { String name = applicationContext.getEnvironment().getProperty("common.name"); String age = applicationContext.getEnvironment().getProperty("common.age"); String address = applicationContext.getEnvironment().getProperty("common.address"); String birthday = applicationContext.getEnvironment().getProperty("common.birthday"); String fullname = applicationContext.getEnvironment().getProperty("common.fullname"); return name + "+" + age + "+" + address + "+" + birthday + "+" + fullname; } }
配置
spring: application: name: service1 cloud: nacos: config: server-addr: 47.156.271.569:8848 # 配置中心地址 file-extension: yaml #dataid 的名稱就是application的name加file-extension service1.yaml namespace: e4582490-173d-41df-9932-c65f01605814 # 開發環境 指定 具體的namespace group: TEST_GROUP # 測試組
開始測試,直接在線修改,支持動態刷新
支持擴展dataid
配置如下:
spring: application: name: service1 cloud: nacos: config: server-addr: 47.111.251.239:8848 # 配置中心地址 file-extension: yaml #dataid 的名稱就是application的name加file-extension service1.yaml namespace: e4582490-173d-41df-9932-c65f01605814 # 開發環境 指定 具體的namespace group: TEST_GROUP # 測試組 ext-config: - data-id: service2.yaml group: TEST_GROUP refresh: true # ext-config[0]: # data-id: service2.yaml # group: TEST_GROUP # refresh: true
上圖中的2種配置都可以,上面是即定義了group和支持刷新。
可以看到 :
- 通過 spring.cloud.nacos.config.ext -config[n].data-id 的配置方式來支持多個 Data Id 的配置。
- 通過 spring.cloud.nacos.config.ext -config[n].group 的配置方式自定義 Data Id 所在的組,不明確配置的話,默認是 DEFAULT_GROUP。
- 通過 spring.cloud.nacos.config.ext -config[n].refresh 的配置方式來控制該 Data Id 在配置變更時,是否支持應用中可動態刷新, 感知到最新的配置值。默認是不支持的
Note : spring.cloud.nacos.config.ext -config[n].data-id 的值必須帶文件擴展名,文件擴展名既可支持properties,又可以支持 yaml/yml。 此時 spring.cloud.nacos.config.file -extension 的配置對自定義擴
展配置的 Data Id 文件擴展名沒有影響。通過自定義擴展的 Data Id 配置,既可以解決多個應用間配置共享的問題,又可以支持一個應用有多個配置文件。
自定義共享 Data Id 配置
為了更加清晰的在多個應用間配置共享的 Data Id ,你可以通過以下的方式來配置:
注意:共享dataid的時候默認DEFAULT_GROUP,不是這個組的話,是讀取不到的
spring: application: name: service1 cloud: nacos: config: server-addr: 47.151.545.265:8848 # 配置中心地址 file-extension: yaml #dataid 的名稱就是application的name加file-extension service1.yaml namespace: e4582490-173d-41df-9932-c65f01605814 # 開發環境 指定 具體的namespace group: TEST_GROUP # 測試組 shared-dataids: ext-config-common01.properties,ext-config-common02.properties,ext-config-common03.properties refreshable-dataids: ext-config-common01.properties
可以看到:
- 通過 spring.cloud.nacos.config.shared -dataids 來支持多個共享 Data Id 的配置,多個之間用逗號隔開。
- 通過 spring.cloud.nacos.config.refreshable -dataids 來支持哪些共享配置的 Data Id 在配置變化時,應用中是否可動態刷新, 感知到最新的配置值,多個 Data Id 之間用逗號隔開。如果沒有明確配置,默認情況下所有共享配置的 Data Id 都不支持動態刷新。
Note:通過 spring.cloud.nacos.config.shared -dataids 來支持多個共享配置的 Data Id 時, 多個共享配置間的一個優先級的關系我們約定:按照配置出現的先后順序,即后面的優先級要高於前面。
Note:通過 spring.cloud.nacos.config.shared -dataids 來配置時,Data Id 必須帶文件擴展名,文件擴展名既可支持 properties,也可以支持 yaml/yml。 此時 spring.cloud.nacos.config.file -extension 的配置對自定義擴展配置的 Data Id 文件擴展名沒有影響。
Note: spring.cloud.nacos.config.refreshable -dataids 給出哪些需要支持動態刷新時,Data Id 的值也必須明確給出文件擴展名。
配置的優先級
Spring Cloud Alibaba Nacos Config 目前提供了三種配置能力從 Nacos 拉取相關的配置。
A: 通過 spring.cloud.nacos.config.shared -dataids 支持多個共享 Data Id 的配置
B: 通過 spring.cloud.nacos.config.ext -config[n].data-id 的方式支持多個擴展 Data Id 的配置,多個Data Id 同時配置時,他的優先級關系是 spring.cloud.nacos.config.ext -config[n].data-id 其中 n 的值越大,優先級越高。
C: 通過內部相關規則(應用名、擴展名 )自動生成相關的 Data Id 配置
當三種方式共同使用時,他們的一個優先級關系是:C > B >A
完全關閉配置
通過設置 spring.cloud.nacos.config.enabled = false 來完全關閉 Spring Cloud Nacos Config