alibaba之Nacos

本文爲轉載文章
原文連接:https://windmt.com/2018/11/09/intro-to-spring-cloud-alibaba-nacos/html

上個月最後一天的凌晨,Spring Cloud Alibaba 正式入駐了 Spring Cloud 官方孵化器,並在 maven 中央庫發佈了第一個版本。java

目前 Spring Cloud Alibaba 還只能算是預覽版吧,裏邊的坑確定很多,不過我仍是決定試試,看看 Alibaba 到底靠譜不靠譜。mysql

image

Spring Cloud Alibaba

目前 Spring Cloud Alibaba 項目還處於 Spring Cloud 官方孵化器中,打開它 Github 的就能看到 「親切」 的中文文檔。git

它目前只有三個組件:github

  • Sentinel:把流量做爲切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。web

  • Nacos:一個更易於構建雲原生應用的動態服務發現、配置管理和服務管理平臺。spring

  • AliCloud OSS: 阿里雲對象存儲服務(Object Storage Service,簡稱 OSS),是阿里雲提供的海量、安全、低成本、高可靠的雲存儲服務。您能夠在任何應用、任什麼時候間、任何地點存儲和訪問任意類型的數據。sql

看官方路線圖上講後邊還會增長數據庫

  • Dubbo:Apache Dubbo™ (incubating) 是一款高性能 Java RPC 框架。bootstrap

  • RocketMQ:Apache RocketMQ™ 基於 Java 的高性能、高吞吐量的分佈式消息和流計算平臺。

  • Schedulerx:阿里中間件團隊開發的一款分佈式任務調度產品,支持週期性的任務與固定時間點觸發任務。

  • AliCloud SLS:針對日誌類數據的一站式服務,在阿里巴巴集團經歷大量大數據場景錘鍊而成。您無需開發就能快捷完成日誌數據採集、消費、投遞以及查詢分析等功能,提高運維、運營效率,創建 DT 時代海量日誌處理能力。

從數量上來看,Alibaba 的組件數量和目前 Netflix 的相比少了一多半,可是仔細看看各組件的功能描述,也就明白了。在沒真正上手以前,我我的先大膽猜想一下:

  • Nacos = Eureka/Consule + Config + Admin
  • Sentinel = Hystrix + Dashboard + Turbine
  • Dubbo = Ribbon + Feign
  • RocketMQ = RabbitMQ
  • Schedulerx = Quartz
  • AliCloud OSS、AliCloud SLS 這三個應該是獨有的
    鏈路跟蹤(Sleuth、Zipkin)不知道會不會在 Sentinel 裏
    以上只是猜想,待我從坑裏爬出來以後再回來更新。也歡迎你們一塊兒交流探討~

這裏我就先試試 Nacos。

Nacos

image

這是 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 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 和測試,不用改任何配置,直接敲如下命令執行

sh bin/startup.sh -m standalone

Windows 的話就是

cmd bin/startup.cmd -m standalone

而後從 http://localhost:8848/nacos/index.html 進入控制檯就能看到以下界面了

image

cluster 模式

集羣模式須要依賴 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}-${spring.profile.active}.${file-extension}

  • prefix 默認爲 spring.application.name 的值,也能夠經過配置項 spring.cloud.nacos.config.prefix來配置。
  • spring.profile.active 即爲當前環境對應的 profile,詳情能夠參考 Spring >Boot 文檔。 注意:當 spring.profile.active 爲空時,對應的鏈接符 - >也將不存在,dataId 的拼接格式變成 ${prefix}.${file-extension}
  • file-exetension 爲配置內容的數據格式,能夠經過配置項 spring.cloud.nacos.config.file-extension 來配置。目前只支持 properties 和 yaml 類型。

而後啓動 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 的可視化界面來操做

image

另外咱們能夠查詢配置的歷史記錄並能快速回滾

image

還能查詢到某個配置當前的被監聽狀態(這裏的分頁有些 bug)

image

數據源

通過了上邊的一些簡單操做,咱們已經能夠正常使用 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 中添加配置

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 開啓服務發現

@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 ,調用 http://localhost:18080/echo/windmt 和 http://localhost:18081/echo/windmt ,返回內容均爲 Hello Nacos Discovery windmt,說明服務發現成功了。

這時候查看 Nacos Console 也能看到已註冊的服務列表及其詳情

image

image

如今來說一下爲何前邊要將 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 生態總歸是好的~

本文示例代碼: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/


掃一掃,支持下做者吧

(轉載本站文章請註明做者和出處 方誌朋的博客

相關文章
相關標籤/搜索