基於Spring Cloud搭建分佈式配置中心

一.Spring Cloud簡介

先來看看官網對spring cloud的定義:

Spring Cloud offers a simple and accessible programming model to the most common distributed system patterns, helping developers build resilient, reliable, and coordinated applications.

再來看看整個spring cloud的architecture
這裏寫圖片描述
可以看出spring cloud的意義在於推出了一個基於spring的全鏈路方案,包括gateway,tracing,microservices,configCenter,service registry等等,中小型公司在基於spring cloud和springBoot的基礎上進行搭建系統的話,只要稍作定製化便能很快的搭建起一個能支撐一定量qps和數據的系統

二.基於Spring Cloud搭建分佈式配置中心

(1)首先簡單瀏覽一下我們要搭建的config center的architecture:
這裏寫圖片描述
1.git repository作爲配置的存儲地
2.Config Server設置兩臺作爲高可用
3.eureka server設置兩臺註冊中心作爲高可用
4.config client作爲客戶端獲取配置

(2)下面看看關鍵代碼:

1.配置eureka註冊中心

EurekaServiceApplication:

package com.andrew.eureka.server;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class EurekaServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServiceApplication.class, args);
    }
}

application-peer1.properties配置:

server.port=8761

eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://peer2:8762/eureka
eureka.instance.appname=eureka-server
eureka.instance.hostname=peer1

logging.level.com.netflix.eureka=OFF
logging.level.com.netflix.discovery=OFF

application-peer2.properties配置:

server.port=8762

eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://peer1:8761/eureka
eureka.instance.appname=eureka-server
eureka.instance.hostname=peer2

logging.level.com.netflix.eureka=OFF
logging.level.com.netflix.discovery=OFF

通過mvn clean install命令打包成jar之後,跑命令

java -jar eureka-service-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1 
java -jar eureka-service-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2

輸入http://localhost:8761/之後,可以看到
這裏寫圖片描述

裏面的available-replicas可以看到擁有peer2這個備份service

2.配置config server

ConfigServerApplication:

package com.andrew.config.server;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@EnableConfigServer
@SpringBootApplication
@EnableEurekaClient
public class ConfigServerApplication {
    public static void main(String[] args) {
        new SpringApplicationBuilder(ConfigServerApplication.class).run(args);
    }
}

每個eureka client都必須有@EnableEurekaClient這個註解,每個config server必須有@EnableConfigServer這個註解

application.yml配置文件:

spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: F:\\public-projects\\spring-cloud\\spring-cloud-config\\gs-centralized-configuration-master\\config

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka

注意spring cloud使用git做配置的存儲倉庫,這裏我是用了本地的git倉庫,一般來說是通過遠程倉庫作爲配置的存儲
跑下面兩個命令起兩個config server:

java -jar config-server-0.0.1-SNAPSHOT.jar --server.port=8888
java -jar config-server-0.0.1-SNAPSHOT.jar --server.port=8889

這裏寫圖片描述

可以看到兩個config server已經註冊到eureka server上了

3.配置config client

package com.andrew.config.client;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@EnableEurekaClient
@SpringBootApplication
public class ConfigClientApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(ConfigClientApplication.class).run(args);
    }
}

@RefreshScope
@RestController
class MessageRestController {

    @Value("${message:Hello default}")
    private String message;

    @RequestMapping("/message")
    String getMessage() {
        return this.message;
    }
}

@RefreshScope是因爲config client只會在第一次初始化bean的時候獲取一次配置,後面如果需要更新的話,需要設置這個註解在controller上面,並且引入spring actuator的包,通過發送post請求來更新bean裏面的值
@Value註解表示要獲取的是key爲message的值,默認值是Hello default

配置application.properties:

management.endpoints.web.exposure.include=*

spring.application.name=config-client
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
eureka.client.service-url.defaultZone=http://localhost:8761/eureka,http://localhost:8762/eureka

spring.cloud.config.discovery.enabled=true能夠讓config client自動去發現config server
spring.cloud.config.discovery.serviceId=config-server是根據configServer在配置文件裏面的applicationName設置,configClient根據serviceId去探測configServer

PS:每個configClient會在第一次初始化之後從eureka service獲取到註冊在上面的服務器信息,後面即使eureka service down掉,仍然能夠根據本地緩存去訪問到config server

運行下面命令啓動config-client:

java -jar config-client-0.0.1-SNAPSHOT.jar --server.port=8081

這裏寫圖片描述
可以看到config-client已經註冊上去

4.Test Application

applicationContext.properties文件:

hello=helloWorld
message = congratulation success

在瀏覽器輸入:http://localhost:8081/message 可以看到結果是:

這裏寫圖片描述

當我們修改文件內容爲

hello=helloWorld
message = haha we change the value

git commit之後,通過postman發送post請求到http://localhost:8081/actuator/refresh,再去調用http://localhost:8081/message ,可以看到新的配置值:
這裏寫圖片描述
通過這我們就可以成功獲取到更新後的配置

5.優點和缺點

優點:
1.eureka作爲註冊中心,不像zk需要選舉master,eureka是peer形式的,那麼即使出現網絡變化導致註冊中心實例少於一定數量,eureka也可以保證一直的提供服務
2.當網絡變化的時候,eureka會有一個Self Preservation Mode的機制,如果15%的註冊實例在短時間內出現down的情況(通過heartbeat確認),那麼eureka不會移除實例的註冊信息,而是等到網絡恢復之後仍然以這個實例信息去提供給調用方

具體可以通過:https://github.com/Netflix/eureka/wiki/Server-Self-Preservation-Mode這裏瞭解

缺點:
1.需要自己定製化一個流程審批界面,沒有一個完整的權限控制流程
2.缺少一個界面去維護管理配置
3.不像zk是使用觀察者模式,每個client可以去監聽配置的變化,每次更新都需要主動去發送一次post請求更新或者必須通過git webhook加上消息隊列做熱更新,需要另外做一個封裝的api使得更新配置對上層無感知
4.全程都是用http去實現,不如zk通過tcp長連接來的更有效率
5.基於git倉庫保存配置,從文件系統在io上性能沒有從mysql讀快,並且可以在文件系統前加入redis之類的緩存機制提供更強的性能

6.附記

demo代碼:https://github.com/AndrewHuangMiao/spring-cloud-config-eureka
業界基於springboot和springcloud做了定製化之後的使用:https://github.com/ctripcorp/apollo/

7.參考:

https://spring.io/guides/gs/service-registration-and-discovery/
https://spring.io/guides/gs/centralized-configuration/
https://www.aliyun.com/jiaocheng/820688.html

written by:黃文嶽

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章