上個月最后一天的凌晨愁茁,Spring Cloud Alibaba 正式入駐了 Spring Cloud 官方孵化器,并在 maven 中央庫發(fā)布了第一個版本促煮。
目前 Spring Cloud Alibaba 還只能算是預(yù)覽版吧,里邊的坑肯定不少坐昙,不過我還是決定試試疾棵,看看 Alibaba 到底靠譜不靠譜。
Spring Cloud Alibaba
目前 Spring Cloud Alibaba 項目還處于 Spring Cloud 官方孵化器中拟枚,打開它 Github 的就能看到 “親切” 的中文文檔梨州。
它目前只有三個組件:
Sentinel:把流量作為切入點暴匠,從流量控制傻粘、熔斷降級弦悉、系統(tǒng)負載保護等多個維度保護服務(wù)的穩(wěn)定性稽莉。
Nacos:一個更易于構(gòu)建云原生應(yīng)用的動態(tài)服務(wù)發(fā)現(xiàn)、配置管理和服務(wù)管理平臺昧甘。
AliCloud OSS: 阿里云對象存儲服務(wù)(Object Storage Service战得,簡稱 OSS)常侦,是阿里云提供的海量聋亡、安全杀捻、低成本致讥、高可靠的云存儲服務(wù)器赞。您可以在任何應(yīng)用港柜、任何時間夏醉、任何地點存儲和訪問任意類型的數(shù)據(jù)畔柔。
看官方路線圖上講后邊還會增加
Dubbo:Apache Dubbo? (incubating) 是一款高性能 Java RPC 框架靶擦。
RocketMQ:Apache RocketMQ? 基于 Java 的高性能、高吞吐量的分布式消息和流計算平臺踩蔚。
Schedulerx:阿里中間件團隊開發(fā)的一款分布式任務(wù)調(diào)度產(chǎn)品馅闽,支持周期性的任務(wù)與固定時間點觸發(fā)任務(wù)福也。
AliCloud SLS:針對日志類數(shù)據(jù)的一站式服務(wù)拟杉,在阿里巴巴集團經(jīng)歷大量大數(shù)據(jù)場景錘煉而成搬设。您無需開發(fā)就能快捷完成日志數(shù)據(jù)采集、消費泣洞、投遞以及查詢分析等功能,提升運維呕诉、運營效率椿每,建立 DT 時代海量日志處理能力。
從數(shù)量上來看法精,Alibaba 的組件數(shù)量和目前 Netflix 的相比少了一多半洛勉,但是仔細看看各組件的功能描述收毫,也就明白了。在沒真正上手之前,我個人先大膽猜測一下:
- Nacos = Eureka/Consule + Config + Admin
- Sentinel = Hystrix + Dashboard + Turbine
- Dubbo = Ribbon + Feign
- RocketMQ = RabbitMQ
- Schedulerx = Quartz
- AliCloud OSS、AliCloud SLS 這三個應(yīng)該是獨有的
鏈路跟蹤(Sleuth、Zipkin)不知道會不會在 Sentinel 里
以上只是猜測蝙砌,待我從坑里爬出來之后再回來更新薪介。也歡迎大家一起交流探討~
這里我就先試試 Nacos缀旁。
Nacos
這是 Nacos 的架構(gòu)圖,可以看到它確實是融合了服務(wù)注冊發(fā)現(xiàn)中心、配置中心、服務(wù)管理等功能辫继,和我之前猜想的它是 Eureka/Consule + Config + Admin 的合體差不多。
另外通過官方文檔發(fā)現(xiàn),Nacos 除了可以和 Spring Cloud 集成,還可以和 Spring、SpringBoot 進行集成。
不過我們只關(guān)注于 Spring Cloud黔姜,別的就略過了纳寂,直接上手吧~
工程的目錄結(jié)構(gòu)如下:
alibaba
├── nacos-config
│ ├── pom.xml
│ └── src
├── nacos-consumer
│ ├── pom.xml
│ └── src
├── nacos-provider
│ ├── pom.xml
│ └── src
└── pom.xml
首先引入 Spring Cloud Alibaba 的 BOM
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/>
</parent>
<properties>
<spring-cloud.version>Finchley.SR2</spring-cloud.version>
<spring-cloud-alibaba.version>0.2.0.RELEASE</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
這里版本號有坑,文檔上說和 Spring Boot 2.0.x 版本兼容隘冲,但是實測 2.0.6.RELEASE 報錯
java.lang.NoClassDefFoundError: org/springframework/core/env/EnvironmentCapable
Nacos Server
在使用 Nacos 之前绳慎,需要先下載 Nacos 并啟動 Nacos Server已脓。
Nacos Server 有兩種運行模式:
- standalone
- cluster
不論哪種方式吧,都需要先去 https://github.com/alibaba/nacos/releases 下載最新的 release 包,然后解壓,以 nacos-server-0.4.0.zip 為例
unzip nacos-server-0.4.0.zip
cd nacos
standalone 模式
此模式一般用于 demo 和測試,不用改任何配置贞奋,直接敲以下命令執(zhí)行
sh bin/startup.sh -m standalone
Windows 的話就是
cmd bin/startup.cmd -m standalone
然后從 http://localhost:8848/nacos/index.html 進入控制臺就能看到如下界面了
cluster 模式
集群模式需要依賴 MySQL勾缭,然后改兩個配置文件:
conf/cluster.conf
conf/application.properties
具體怎么改混稽,在這里就先不展開了膳叨。我們先用 standalone 模式擼起來汰翠,享受 coding 的快感烛卧,然后再慢慢轉(zhuǎn)到 cluster 上邊。
配置管理
在 nacos/pom.xml 里添加依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
啟動類不用修改
@SpringBootApplication
public class NacosApplication {
public static void main(String[] args) {
SpringApplication.run(NacosApplication.class, args);
}
}
修改 bootstrap.yml
spring:
application:
name: nacos
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
注意:必須是寫在 bootstrap.yml 中炬搭,配置在 application.yml 中不行迎变,啟動報錯
java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.application.name' in value "${spring.application.name}"
至于 bootstrap.yml 和 application.yml 的區(qū)別,之前講過這里就不贅述了。
添加一個 Endpoint 便于觀察
@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {
@Value("${useLocalCache:false}")
private boolean useLocalCache;
@RequestMapping("/get")
public boolean get() {
return useLocalCache;
}
}
注意一定要加@RefreshScope注解
小心!此處有坑!
這時候先別急著啟動 NacosConfigApplication 的,需要需要通過調(diào)用 Nacos Open API 往 Nacos Server 里發(fā)布一個配置丘薛。dataId 為 nacos.properties,內(nèi)容為useLocalCache=true
curl -X "POST" "http://127.0.0.1:8848/nacos/v1/cs/configs" \
-H 'Content-Type: application/x-www-form-urlencoded; charset=utf-8' \
--data-urlencode "dataId=nacos.properties" \
--data-urlencode "group=DEFAULT_GROUP" \
--data-urlencode "content=useLocalCache=true
dataId 的完整格式如下:
{spring.profile.active}.${file-extension}
- prefix 默認為 spring.application.name 的值,也可以通過配置項 spring.cloud.nacos.config.prefix來配置。
- spring.profile.active 即為當(dāng)前環(huán)境對應(yīng)的 profile播急,詳情可以參考 Spring >Boot 文檔捶枢。 注意:當(dāng) spring.profile.active 為空時,對應(yīng)的連接符 - >也將不存在蒜鸡,dataId 的拼接格式變成
{file-extension}
- file-exetension 為配置內(nèi)容的數(shù)據(jù)格式忘朝,可以通過配置項 spring.cloud.nacos.config.file-extension 來配置。目前只支持 properties 和 yaml 類型导狡。
然后啟動 NacosConfigApplication枚赡,從啟動日志里能看到
Located property source: CompositePropertySource {name='NACOS', propertySources=[NacosPropertySource {name='nacos.properties'}]}
如果 propertySources 里邊是空的卢肃,那抱歉,你掉到坑里邊了。 如果你能看到之前發(fā)布的 dataId忙芒,那恭喜潮峦,請求 http://localhost:8080/config/get 就可以看到返回內(nèi)容 true 了。
再次調(diào)用 Nacos Open API 修改內(nèi)容為useLocalCache=false
再次訪問 http://localhost:8080/config/get ,此時返回內(nèi)容為false,說明程序中的useLocalCache值已經(jīng)被動態(tài)更新了。
當(dāng)然,以上手動調(diào)用 Nacos Open API 的方式也可以通過 Nacos Console 的可視化界面來操作
另外我們可以查詢配置的歷史記錄并能快速回滾
還能查詢到某個配置當(dāng)前的被監(jiān)聽狀態(tài)(這里的分頁有些 bug)
數(shù)據(jù)源
經(jīng)過了上邊的一些簡單操作准浴,我們已經(jīng)可以正常使用 Nacos 配置中心了乐横。
但是不知道你有沒有想過:配置數(shù)據(jù)是存在哪里呢罐农?
我們沒有對 Nacos Server 做任何配置匾南,那么數(shù)據(jù)只有兩個位置可以存儲:
- 內(nèi)存
- 本地數(shù)據(jù)庫
如果我們現(xiàn)在重啟剛剛在運行的 Nacos Server蛆楞,會發(fā)現(xiàn)剛才加的 nacos.properties 配置還在裆悄,說明不是內(nèi)存存儲的臂聋。
這時候我們打開NACOS_PATH/data孩等,會發(fā)現(xiàn)里邊有個derby-data目錄冰垄,Derby 是 Java 編寫的數(shù)據(jù)庫虹茶,屬于 Apache 的一個開源項目蝴罪。我們的配置數(shù)據(jù)現(xiàn)在就存儲在這個庫中步清。
Derby 我并不是很熟悉,那能不能將數(shù)據(jù)源改為我們熟悉的 MySQL 呢询微?當(dāng)然可以了狂巢。
注意:不支持 MySQL 8.0 版本
這里我以本地運行的 MySQL 為例:
創(chuàng)建一個名為nacos_config的 database
將NACOS_PATH/conf/nacos-mysql.sql中的表結(jié)構(gòu)導(dǎo)入剛才創(chuàng)建的庫中,這幾張表的用途就自己研究吧
修改NACOS_PATH/conf/application.properties斩个,加入 MySQL 配置
db.num=1
db.url.0=jdbc:mysql://localhost:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=root
創(chuàng)建cluster.conf受啥,填入要運行 Nacos Server 機器的 ip
192.168.100.155
192.168.100.156
我就是運行個 demo滚局,沒有多余機器來組建集群怎么辦呢顽频?
其實不用虛擬機嘁圈,直接只填一個本地地址也是可以的(僅限于配置管理最住,服務(wù)發(fā)現(xiàn)不行)涨缚。
這里有兩個坑:
Nacos Server 的數(shù)據(jù)源是用 Derby 還是 MySQL 完全是由其運行模式?jīng)Q定的:
- standalone 的話僅會使用 Derby仗岖,即使在 application.properties 里邊配置 MySQL 也照樣無視轧拄;
- cluster 模式會自動使用 MySQL檩电,這時候如果沒有 MySQL 的配置俐末,是會報錯的载矿。
官方提供的 cluster.conf 示例如下
#it is ip
#example
10.10.109.214
11.16.128.34
11.16.128.36
從習(xí)慣來看烹卒,這個#號后邊的應(yīng)該就是注釋的旅急,但是抱歉哦溺拱,必須刪掉迫摔,否則下面的異常就撲面而來
Caused by: java.lang.NumberFormatException: For input string: "it is ip:0"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:589)
at java.lang.Long.parseLong(Long.java:631)
at com.alibaba.nacos.naming.core.DistroMapper.onServerStatusUpdate(DistroMapper.java:125)
at com.alibaba.nacos.naming.core.DistroMapper.init(DistroMapper.java:100)
at com.alibaba.nacos.naming.core.DistroMapper.<clinit>(DistroMapper.java:65)
... 79 common frames omitted
以上配置結(jié)束后攒菠,運行 Nacos Server 就能看到效果了。
除了 MySQL 的數(shù)據(jù)表發(fā)生了變化和敬,我們會發(fā)現(xiàn)NACOS_PATH/data下的目錄結(jié)構(gòu)也發(fā)生了變化啤它,多了config-data/DEFAULT_GROUP/nacos_config這么一個文件舱痘,里邊的內(nèi)容就是我們的配置
useLocalCache=true
這是容錯呢塌碌?還是緩存呢台妆?只有等看過源碼才知道了接剩。
服務(wù)發(fā)現(xiàn)
服務(wù)注冊中心和服務(wù)發(fā)現(xiàn)的服務(wù)端都是由 Nacos Server 來提供的,我們只需要提供 Service 向其注冊就好了懊缺。
首先我們先將 Nacos Server 由偽分布式改為 standalone 模式疫稿,原因后邊再說吧。
這里模擬提供兩個 service:provider 和 consumer
alibaba
├── nacos-provider
│ ├── pom.xml
│ └── src
└── nacos-consumer
│ ├── pom.xml
│ └── src
└── pom.xml
首先在 provider 和 consumer 的 pom 添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
在兩者的 bootstrap.yml 中添加配置
provider
spring:
application:
name: nacos-provider
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
server:
port: 18080
consumer
spring:
application:
name: nacos-consumer
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
server:
port: 18081
使用 Spring Cloud 的原生注解 @EnableDiscoveryClient 開啟服務(wù)發(fā)現(xiàn)
@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderApplication {
public static void main(String[] args) {
SpringApplication.run(NacosProviderApplication.class, args);
}
}
提供 Endpoint 以供訪問
@RestController
@RequestMapping("/echo")
public class EchoController {
@RequestMapping(value = "/{string}", method = RequestMethod.GET)
public String echo(@PathVariable String string) {
return "Hello Nacos Discovery " + string;
}
}
Consumer
在 NacosConsumerApplication 中集成 RestTemplate 和 Ribbon
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
提供 Controller
@RestController
@RequestMapping("/echo")
public class TestController {
private final RestTemplate restTemplate;
@Autowired
public TestController(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@RequestMapping(value = "/{str}", method = RequestMethod.GET)
public String echo(@PathVariable String str) {
return restTemplate.getForObject("http://nacos-provider/echo/" + str, String.class);
}
}
分別啟動 NacosProviderApplication 和 NacosConsumerApplication 桐汤,調(diào)用 http://localhost:18080/echo/windmt 和 http://localhost:18081/echo/windmt 而克,返回內(nèi)容均為 Hello Nacos Discovery windmt,說明服務(wù)發(fā)現(xiàn)成功了怔毛。
這時候查看 Nacos Console 也能看到已注冊的服務(wù)列表及其詳情
現(xiàn)在來講一下為什么前邊要將 Nacos Server 由偽分布式再改為 standalone 模式。
單個節(jié)點的 Nacos Server 偽分布式在配置管理運行的好好的腾降,但是到了服務(wù)發(fā)現(xiàn)抗果,它就失效了寄啼。
通過 log 可以發(fā)現(xiàn)一些端倪,單節(jié)點的在選主的時候杜漠,無法正確選出 leader
==> logs/naming-raft.log <==
2018-11-13 16:38:56,424 INFO leader timeout, start voting,leader: null, term: 1
從而導(dǎo)致 Client 無法正常注冊
java.lang.IllegalStateException: failed to req API:/nacos/v1/ns/instance after all servers([127.0.0.1:8848]) tried
at com.alibaba.nacos.client.naming.net.NamingProxy.reqAPI(NamingProxy.java:339) ~[nacos-client-0.3.0.jar:na]
at com.alibaba.nacos.client.naming.net.NamingProxy.reqAPI(NamingProxy.java:272) ~[nacos-client-0.3.0.jar:na]
at com.alibaba.nacos.client.naming.net.NamingProxy.registerService(NamingProxy.java:171) ~[nacos-client-0.3.0.jar:na]
at com.alibaba.nacos.client.naming.NacosNamingService.registerInstance(NacosNamingService.java:161) ~[nacos-client-0.3.0.jar:na]
... ...
小結(jié)
當(dāng)今年年初 Dubbo 進入 Apache 孵化器的時候,就有預(yù)感阿里要與 Spring Cloud 結(jié)緣喜庞。只是沒想到這么快睛竣。
如今 Spring Cloud Alibaba 已經(jīng)進入了 Spring Cloud 官方孵化器,相信等不了多久也就能正式發(fā)布了。雖然大家在生產(chǎn)環(huán)境必然還不會這么快速地接入,但是總歸是多了一種選擇。
而 Nacos 作為微服務(wù)核心的服務(wù)注冊與發(fā)現(xiàn)中心,讓大家在 Eureka 和 Consule 之外有了新的選擇,開箱即用择镇,上手簡潔吝梅,暫時也沒發(fā)現(xiàn)有太大的坑。但將配置中心融合也融合進來是好是壞装蓬,這個我先按下不表暗赶。
總而言之因惭,Spring Cloud Alibaba 的入駐對于 Spring Cloud 生態(tài)總歸是好的~
本文示例代碼:https://github.com/zhaoyibo/spring-cloud-study/tree/master/alibaba
參考
https://github.com/spring-cloud-incubator/spring-cloud-alibaba
https://github.com/alibaba/Nacos
https://nacos.io/en-us/docs/quick-start-spring-cloud.html
原文鏈接:https://windmt.com/2018/11/09/intro-to-spring-cloud-alibaba-nacos/
關(guān)注我: