Nacos使用和注冊部分源碼介紹


Nacos簡單介紹

Nacos致力於幫助您發現、配置和管理微服務。Nacos提供了一組簡單易用的特性集,幫助您快速實現動態服務發現、服務配置、服務元數據及流量管理。Nacos幫助您更敏捷和容易地構建、交付和管理微服務平台。Nacos是構建以“服務”為中心的現代應用架構 (例如微服務范式、雲原生范式) 的服務基礎設施。
接下來主要介紹Nacos作為注冊中心的使用和注冊部分的源碼解析。

Nacos安裝

Nacos預裝環境

Nacos 依賴 Java 環境來運行。如果您是從代碼開始構建並運行Nacos,還需要為此配置 Maven環境這里就不介紹Maven和Java安裝,大家自行安裝一下。

安裝的方式主要有兩種:
  1. 從GitHub上下載源碼安裝:
//下載源碼的地址
git clone https://github.com/alibaba/nacos.git
cd nacos/
//編譯源碼
mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U  
ls -al distribution/target/
//進入編譯包
cd distribution/target/nacos-server-$version/nacos/bin
View Code

2.下載安裝包的形式:

tar -xvf nacos-server-$version.tar.gz
cd nacos/bin
View Code
啟動服務器

啟動命令(standalone代表着單機模式運行,非集群模式):

sh startup.sh -m standalone
View Code
關閉服務器
sh shutdown.sh
View Code
單機環境下使用Mysql:

在0.7版本之前,在單機模式時nacos使用嵌入式數據庫實現數據的存儲,不方便觀察數據存儲的基本情況。0.7版本增加了支持mysql數據源能力,具體的操作步驟:

  1. 安裝數據庫,版本要求:5.6.5+
  2. 初始化mysql數據庫,數據庫初始化文件:nacos-mysql.sql
  3. 修改conf/application.properties文件,增加支持mysql數據源配置(目前只支持mysql),添加mysql數據源的url、用戶名和密碼。
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456
View Code

對於單機來說我們就是玩個demo是夠的,但是對於生產來說我們就要考慮高可用的方案了:
對於集群部署的方式如果在虛擬機環境就采用Nagix負載3台虛擬機,對於K8S的環境通過Service負載3台Pod的形式搭建高可用環境,對於數據庫選擇來說最好采用主從結構,保證數據庫的高可用。
整體的部署可能如下;


下圖就是搭建好以后的整體界面:

Nacos使用

1.創建一個Spring Boot空應用

2.編輯pom.xml文件

    <properties>
        <springboot.vetsion>2.2.11.RELEASE</springboot.vetsion>
        <spring-cloud-version>Hoxton.SR9</spring-cloud-version>
        <spring-cloud-alibaba-version>2.2.3.RELEASE</spring-cloud-alibaba-version>
    </properties>
<dependencyManagement>
    <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${springboot.vetsion}</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>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba-version}</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>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>
View Code

3.創建應用的啟動項目

@SpringBootApplication(scanBasePackages = {"com.springcloud.study"})
@EnableDiscoveryClient
public class SystemApplication {

    public static void main(String[] args) {
        SpringApplication.run(SystemApplication.class, args);
    }
}
View Code

4.配置application.yaml文件

server:
  port: 8081
spring:
  application:
    name: system
  # 數據源配置項
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/study_user?useSSL=false&useUnicode=true&characterEncoding=UTF-8
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: 123456
  #nacos基礎配置
  cloud:
    nacos:
      discovery:
        server-addr: 10.226.73.115:8886
        #環境選擇
        #namespace: b7d341fc-df29-45ce-b3cd-4415f66b1ee0
View Code

5.啟動項目

Nacos注冊部分源碼分析

客戶端通過Rest接口式向Nacos Server注冊自己的服務,提供自身的元數據,比如ip地址、端口等信息。 Nacos Server接收到注冊請求后,就會把這些元數據信息存儲在一個雙層的內存Map中。對於注冊部分的源碼整體上分為兩部分:

客戶端注冊源碼

按照Spring Boot Starter的習慣,我們首先找到spring-cloud-starter-alibaba-nacos-discovery啟動項,如下圖所示:


標紅部分的NacosServiceRegistryAutoConfiguration是我們注冊部分關注的類,首先我們看下該類的整體的繼承結構:

重點關注AbstractAutoServiceRegistration接口,NacosAutoServiceRegistration該Bean的注入就是我們注入開始的:

整體看下該類,基本上是對AbstractAutoServiceRegistration繼承和實現,該類位於spring-cloud-common這個jar下面,Spring Cloud Commons模塊是為了對微服務中的服務注冊與發現、負載均衡、熔斷器等功能提供一個抽象層代碼,這個抽象層與具體的實現無關。這樣這些功能具體的實現上可以采用不同的技術去實現,並可以做到在使用時靈活的更換。
NacosAutoServiceRegistration內部存在一個@EventListener注解,@EventListener是一種事件驅動編程在spring4.2的時候開始有的,可以理解為ApplicationListener接口的擴展,方便我們使用,可以理解為Spring為我們提供的一個事件監聽、訂閱的實現,內部實現原理是觀察者設計模式;為的就是業務系統邏輯的解耦,提高可擴展性以及可維護性。事件發布者並不需要考慮誰去監聽,監聽具體的實現內容是什么,發布者的工作只是為了發布事件而已。

接下來我們重點看下AbstractAutoServiceRegistration內部start方法,

register的具體的實現類是NacosServiceRegistry,內部調用NacosNamingService的registerInstance方法,該方法內部通過調用NamingProxy的reqApi,通過NacosRestTemplate請求服務端的/instance方法注冊到服務端。


至此完成了客戶端注冊到服務端,下圖是整體的時序圖:
服務端注冊部分

服務端注冊相對比較復雜一點,這塊需要將Nacos源碼下載一下,找到naming模塊,InstanceController就是我們調用服務端的接口,如下圖所示:


接下來重點看下ServiceManager的registerInstance的方法,如下圖:

首先看下createEmptyService方法,該方法目的雙肩一個雙層的Map對象,用於存儲注冊應用的信息,整體的結構Map(namespace, Map(group::serviceName, Service)),這里正好對應注冊中心介紹時候的張圖,我們整體在看一下:


初始化的注冊表結構以后,接下來就是將應用的信息注冊添加到注冊表中,主要分為兩步如下圖:

addIpAddresses就是獲取當前注冊服務的所有ip,整體的流程如下圖:

這里的主要的重點是put方法,這里我們全部按照CP的場景去解釋,AP的場景在未來的章節補充,CP的實現類是DistroConsistencyServiceImpl,如下圖:

通過把需要注冊到注冊表的服務添加到阻塞隊列當中,Notifier本質上一個線程,然后通過執行run內部的hander方法,如下圖:

通過調用Service的onChange方法來變更注冊表的信息,內部主要通過updateIPs完成注冊表信息的表更,主要也是采用CopyOnWrite的思想,如下圖:

到此服務端的注入就完成了,這個里面整體上有三處亮點:
1.CopyOnWrite的思想的廣泛應用;
2.通過阻塞隊列實現異步任務提升系統性能,並且解決並發寫入問題;
3.觀察者設計的廣泛應用;

結束

歡迎大家點點關注,點點贊,感謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM