您好,登錄后才能下訂單哦!
上個月最后一天的凌晨,Spring Cloud Alibaba 正式入駐了 Spring Cloud 官方孵化器,并在 maven 中央庫發布了第一個版本。
目前 Spring Cloud Alibaba 還只能算是預覽版吧,里邊的坑肯定不少,不過我還是決定試試,看看 Alibaba 到底靠譜不靠譜。
目前 Spring Cloud Alibaba 項目還處于 Spring Cloud 官方孵化器中,打開它 Github 的就能看到 “親切” 的中文文檔。
它目前只有三個組件:
Sentinel:把流量作為切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。
Nacos:一個更易于構建云原生應用的動態服務發現、配置管理和服務管理平臺。
看官方路線圖上講后邊還會增加:
Dubbo:Apache Dubbo? (incubating) 是一款高性能 Java RPC 框架。
RocketMQ:Apache RocketMQ? 基于 Java 的高性能、高吞吐量的分布式消息和流計算平臺。
Schedulerx:阿里中間件團隊開發的一款分布式任務調度產品,支持周期性的任務與固定時間點觸發任務。
從數量上來看,Alibaba 的組件數量和目前 Netflix 的相比少了一多半,但是仔細看看各組件的功能描述,也就明白了。在沒真正上手之前,我個人先大膽猜測一下:
這是 Nacos 的架構圖,可以看到它確實是融合了服務注冊發現中心、配置中心、服務管理等功能,和我之前猜想的它是 Eureka/Consule + Config + Admin 的合體差不多。
另外通過官方文檔發現,Nacos 除了可以和 Spring Cloud 集成,還可以和 Spring、SpringBoot 進行集成。
不過我們只關注于 Spring Cloud,別的就略過了,直接上手吧~
工程的目錄結構如下:
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 之前,需要先下載 Nacos 并啟動 Nacos Server。
Nacos Server 有兩種運行模式:
不論哪種方式吧,都需要先去?https://github.com/alibaba/nacos/releases?下載最新的 release 包,然后解壓,以 nacos-server-0.4.0.zip 為例
unzip nacos-server-0.4.0.zip
cd nacos
此模式一般用于 demo 和測試,不用改任何配置,直接敲以下命令執行
sh bin/startup.sh -m standalone
Windows 的話就是
cmd bin/startup.cmd -m standalone
然后從?http://localhost:8848/nacos/index.html?進入控制臺就能看到如下界面了
集群模式需要依賴 MySQL,然后改兩個配置文件:
conf/cluster.conf
conf/application.properties
具體怎么改,在這里就先不展開了。我們先用 standalone 模式擼起來,享受 coding 的快感,然后再慢慢轉到 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 的區別,之前講過這里就不贅述了。
添加一個 Endpoint 便于觀察
@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {
@Value("${useLocalCache:false}")
private boolean useLocalCache;
@RequestMapping("/get")
public boolean get() {
return useLocalCache;
}
}
注意一定要加@RefreshScope注解
小心!此處有坑!
這時候先別急著啟動 NacosConfigApplication 的,需要需要通過調用 Nacos Open API 往 Nacos Server 里發布一個配置。dataId 為 nacos.properties,內容為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 的完整格式如下:
prefix?prefix?{spring.profile.active}.${file-extension}
然后啟動 NacosConfigApplication,從啟動日志里能看到
Located property source: CompositePropertySource {name='NACOS', propertySources=[NacosPropertySource {name='nacos.properties'}]}
如果 propertySources 里邊是空的,那抱歉,你掉到坑里邊了。 如果你能看到之前發布的 dataId,那恭喜,請求?http://localhost:8080/config/get?就可以看到返回內容 true 了。
再次調用 Nacos Open API 修改內容為useLocalCache=false
再次訪問?http://localhost:8080/config/get?,此時返回內容為false,說明程序中的useLocalCache值已經被動態更新了。
當然,以上手動調用 Nacos Open API 的方式也可以通過 Nacos Console 的可視化界面來操作
另外我們可以查詢配置的歷史記錄并能快速回滾
還能查詢到某個配置當前的被監聽狀態(這里的分頁有些 bug)
經過了上邊的一些簡單操作,我們已經可以正常使用 Nacos 配置中心了。
但是不知道你有沒有想過:配置數據是存在哪里呢?
我們沒有對 Nacos Server 做任何配置,那么數據只有兩個位置可以存儲:
如果我們現在重啟剛剛在運行的 Nacos Server,會發現剛才加的 nacos.properties 配置還在,說明不是內存存儲的。
這時候我們打開NACOS_PATH/data,會發現里邊有個derby-data目錄,Derby 是 Java 編寫的數據庫,屬于 Apache 的一個開源項目。我們的配置數據現在就存儲在這個庫中。
Derby 我并不是很熟悉,那能不能將數據源改為我們熟悉的 MySQL 呢?當然可以了。
注意:不支持 MySQL 8.0 版本
這里我以本地運行的 MySQL 為例:
創建一個名為nacos_config的 database
將NACOS_PATH/conf/nacos-mysql.sql中的表結構導入剛才創建的庫中,這幾張表的用途就自己研究吧
修改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
創建cluster.conf,填入要運行 Nacos Server 機器的 ip
192.168.100.155
192.168.100.156
我就是運行個 demo,沒有多余機器來組建集群怎么辦呢?
其實不用虛擬機,直接只填一個本地地址也是可以的(僅限于配置管理,服務發現不行)。
這里有兩個坑:
Nacos Server 的數據源是用 Derby 還是 MySQL 完全是由其運行模式決定的:
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
從習慣來看,這個#號后邊的應該就是注釋的,但是抱歉哦,必須刪掉,否則下面的異常就撲面而來
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
以上配置結束后,運行 Nacos Server 就能看到效果了。
除了 MySQL 的數據表發生了變化,我們會發現NACOS_PATH/data下的目錄結構也發生了變化,多了config-data/DEFAULT_GROUP/nacos_config這么一個文件,里邊的內容就是我們的配置
useLocalCache=true
這是容錯呢?還是緩存呢?只有等看過源碼才知道了。
服務注冊中心和服務發現的服務端都是由 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 中添加配置
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 開啟服務發現
@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;
}
}
在 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 ,調用?http://localhost:18080/echo/windmt?和?http://localhost:18081/echo/windmt?,返回內容均為 Hello Nacos Discovery windmt,說明服務發現成功了。
這時候查看 Nacos Console 也能看到已注冊的服務列表及其詳情
現在來講一下為什么前邊要將 Nacos Server 由偽分布式再改為 standalone 模式。
單個節點的 Nacos Server 偽分布式在配置管理運行的好好的,但是到了服務發現,它就失效了。
通過 log 可以發現一些端倪,單節點的在選主的時候,無法正確選出 leader
==> logs/naming-raft.log <==
2018-11-13 16:38:56,424 INFO leader timeout, start voting,leader: null, term: 1
從而導致 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]
... ...
當今年年初 Dubbo 進入 Apache 孵化器的時候,就有預感阿里要與 Spring Cloud 結緣。只是沒想到這么快。
如今 Spring Cloud Alibaba 已經進入了 Spring Cloud 官方孵化器,相信等不了多久也就能正式發布了。雖然大家在生產環境必然還不會這么快速地接入,但是總歸是多了一種選擇。
而 Nacos 作為微服務核心的服務注冊與發現中心,讓大家在 Eureka 和 Consule 之外有了新的選擇,開箱即用,上手簡潔,暫時也沒發現有太大的坑。但將配置中心融合也融合進來是好是壞,這個我先按下不表。
總而言之,Spring Cloud Alibaba 的入駐對于 Spring Cloud 生態總歸是好的~
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。