前提
最近由於業務發展,需要調研一套完善和主流的基礎架構,進行中台化(微服務)的實施,考慮到技術棧切換到SOFAStack
。既然整個體系都切換到螞蟻金服的技術棧,那么自然考慮一些基礎組件如服務注冊發現、配置管理等都切換為阿里的技術棧。考慮到目前比較熱的服務發現組件是Nacos
,需要調研SpringBoot
服務接入Nacos
的可行性,為以后強制要求新服務使用SOFAStack
+ Nacos
的技術棧進行服務開發打下基礎。
Nacos簡介
下面的簡介來源於Nacos
的官網:
Nacos
致力於幫助您發現、配置和管理微服務。Nacos
提供了一組簡單易用的特性集,幫助您快速實現動態服務發現、服務配置、服務元數據及流量管理。
Nacos
幫助您更敏捷和容易地構建、交付和管理微服務平台。Nacos
是構建以服務為中心的現代應用架構(例如微服務范式、雲原生范式)的服務基礎設施。
Nacos
地圖:
Nacos
生態圖:
從Nacos
提供的發展地圖來看,它基本提供了目前微服務實施中一些核心問題:監控、服務發現注冊、配置灰度發布、配置回滾等等。另外,它在生態上能夠融入目前主流的K8S
、Docker
、SpringCloud
、Consul
、Zookeeper
等等(有點像屏蔽底層細節,只需少量配置就可以切換底層架構的實現),這一點十分重要。目前Nacos
在阿里雲上提供了商用版本(記得有前輩說過開源的終極目標就是商用,大概如此)。如果在項目中使用的是SpringCloud
全家桶,引入Nacos
以及它和SpringCloud
之間的膠水層,可以完全替代Eureka
組件的功能,替代和強化部分Spring Cloud Config
的功能。
Nacos服務部署
Nacos-Server
部署相對簡單,它的發布版本見Github的Releases頁面。下載完成后進行解壓,Windows
系下啟動Nacos-Server
只需進入解壓后的${解壓目錄}\nacos\bin
目錄,執行startup.cmd
即可,服務啟動成功的結果如下:
單機模式在不修改配置的前提下直接啟動,使用的是內存數據庫,重啟后數據會被清空。如果需要數據持久化,則需要建立數據庫,具體的步驟是:
- 建表的腳本在
${解壓目錄}\nacos\conf
目錄下,見schema.sql
和nacos-mysql.sql
兩個文件。 - 自行通過建表的腳本建立數據庫。
- 需要指定數據庫,則需要修改
${解壓目錄}\nacos\conf\application.properties
,在文件的尾部追加數據源的連接配置,下面是官方給出的多數據源的例子:
# 需要確保多個數據源的用戶名和密碼一致
db.num=2
db.url.0=jdbc:mysql://11.162.196.16:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.url.1=jdbc:mysql://11.163.152.9:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=nacos_devtest
db.password=nacos
測試獲取已經注冊的服務:
λ curl -X GET http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName
{"hosts":[],"name":"DEFAULT_GROUP@@nacos.naming.serviceName","clusters":""}
訪問http://127.0.0.1:8848/nacos
即可打開Nacos-Console
,初始的登錄賬號和密碼都是nacos
:
更多運維部署相關的內容見文檔運維指南中的一節。
SpirngBoot應用使用Nacos作為注冊中心
SpringBoot
應用使用Nacos
作為注冊中心需要引入依賴nacos-discovery-spring-boot-starter
,筆者編寫本文的時候(2020-01-01),該依賴的最新版本為0.2.4
,對應於SpringBoot
的版本為2.0.3.RELEASE
,引入如下依賴:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
<version>0.2.4</version>
</dependency>
</dependencies>
為了方便起見,筆者把控制器、服務注冊的代碼都寫在啟動類ProvideApplication
中:
@RestController
@SpringBootApplication(scanBasePackages = "club.throwable.provide")
public class ProvideApplication implements CommandLineRunner {
@NacosInjected
private NamingService namingService;
@Value("${spring.application.name}")
private String applicationName;
@Value("${server.port}")
private Integer serverPort;
public static void main(String[] args) {
SpringApplication.run(ProvideApplication.class, args);
}
@GetMapping(path = "/hello")
public String hello(@RequestParam(name = "name") String name) {
return String.format("%s say hello!", name);
}
@Override
public void run(String... args) throws Exception {
// 通過Naming服務注冊實例到注冊中心
namingService.registerInstance(applicationName, "127.0.0.1", serverPort);
}
}
配置文件application-provide.properties
內容如下:
spring.application.name=provide-service
server.port=9092
nacos.discovery.server-addr=127.0.0.1:8848
使用spring.profiles.active=provide
啟動ProvideApplication
,啟動成功后用瀏覽器打開Nacos-Console
:
暫時可知服務的提供方已經注冊成功。接着編寫服務的消費方代碼,引入的最小依賴和服務提供方完全一致,編寫啟動類ConsumeApplication
如下:
@SpringBootApplication(scanBasePackages = "club.throwable.consume")
public class ConsumeApplication implements CommandLineRunner {
@NacosInjected
private NamingService namingService;
public static void main(String[] args) {
SpringApplication.run(ConsumeApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
// 根據服務名從注冊中心獲取一個健康的服務實例
Instance instance = namingService.selectOneHealthyInstance("provide-service");
// 這里只是為了方便才新建RestTemplate實例
RestTemplate template = new RestTemplate();
String url = String.format("http://%s:%d/hello?name=throwable", instance.getIp(), instance.getPort());
String result = template.getForObject(url, String.class);
System.out.println(String.format("請求URL:%s,響應結果:%s", url, result));
}
}
消費服務的配置文件application-consume.properties
內容如下:
spring.application.name=consume-service
server.port=9091
nacos.discovery.server-addr=127.0.0.1:8848
使用spring.profiles.active=consume
啟動ConsumeApplication
,CommandLineRunner
執行完畢后控制台打印:
請求URL:http://127.0.0.1:9092/hello?name=throwable,響應結果:throwable say hello!
這種方式使用起來會感覺模板代碼比較多,不夠簡潔。如果在SpringCloud
體系中,結合Feign
客戶端則可以省略這些模板代碼。
SpirngBoot應用使用Nacos管理配置
如果使用Nacos
進行配置管理,則需要引入nacos-config-spring-boot-starter
依賴,筆者編寫本文的時候(2020-01-01),該依賴的最新版本為0.2.4
:
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.4</version>
</dependency>
新建一個啟動類ConfigApplication
如下:
@RestController
@NacosPropertySource(dataId = "example", autoRefreshed = true)
@SpringBootApplication(scanBasePackages = "club.throwable.config")
public class ConfigApplication {
@NacosValue(value = "${counter:0}", autoRefreshed = true)
public Long counter;
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
@GetMapping(path = "/get")
public String get() {
return String.format("Counter value:%d", counter);
}
}
筆者定義了一個長整型的計數器,設置了autoRefreshed
(自動刷新)為true
,新建一個配置文件application-config.properties
:
spring.application.name=config-service
server.port=9093
nacos.config.server-addr=127.0.0.1:8848
使用spring.profiles.active=config
啟動ConfigApplication
,啟動成功后通過CURL
調用下面的接口:
λ curl -X GET http://127.0.0.1:9093/get
Counter value:0
接着通過Nacos-Console
添加一個配置:
點擊發布按鈕后再次調用接口:
λ curl -X GET http://127.0.0.1:9093/get
Counter value:10086
可見計數器的值已經動態刷新。配置項里面還有很多高級配置如:指定配置生效的服務、Beta
發布等等,可以按照合適的場景進行設置。
另外,Nacos Server
提供Open API
從而可以使用HTTP
客戶端就可以輕松進行配置查詢、配置更新發布等操作(目前這些API沒有做鑒權,社區也有人曾提出這樣會引發安全性問題,Nacos官方已經立項在后續新版本中加入鑒權的功能,目前建議屏蔽或者僅允許內網訪問這些Open API):
- 獲取配置:
curl -X GET http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=${DATA_ID}&group=${GROUP}
- 發布配置:
curl -X POST http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=${DATA_ID}&group=${GROUP}&content=${CONFIG_CONTENT}
小結
本文只是簡單介紹了SpringBoot
中使用Nacos
作為注冊中心以及進行配置管理。Nacos
項目Github
倉庫當前(2020-01-01)的star
數已經接近10000,社區也十分活躍,Issues
和交流群的響應都十分迅速。加之Netflix
的部分開源產品如Eureka
、Hystrix
等已經停止迭代,但Nacos
還在飛速迭代,甚至已經在阿里雲衍生出商業版本,所以筆者認為Nacos
值得使用,在相對熟悉它的大部分特性之后會付之於生產環境中使用。
參考資料:
本文的Demo
項目:
下一篇博文會介紹一下SOFAStack
中基於SOFABoot
、SOFARpc
以及Nacos
等組件作為基礎架構搭建一套微服務的詳細過程。
原文鏈接
- 個人博客【Github Page】:http://throwable.club/2020/01/01/spring-boot-nacos-get-start
- 個人博客【Coding Page】:http://throwable.coding.me/2020/01/01/spring-boot-nacos-get-start
(本文完 c-2-d e-a-20200101 23:11)
技術公眾號(《Throwable文摘》),不定期推送筆者原創技術文章(絕不抄襲或者轉載):