over 2 years ago

既然 Microservices 未來只會多不會少,還是可以多利用 Spring 的項目來做管理,這邊用簡單的方式來做不同AP的設定同步,使用 SpringCloud 跟 RabbitMQ

Spring Cloud Config Server


簡單說,你Server端可以從GitHub上或是本地檔案載入設定檔,當Client端啟動時會去Server上拉需要的設定參數下來

Server端

build.gradle
buildscript {
    ext {
        springBootVersion = '1.2.5.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 
        classpath("io.spring.gradle:dependency-management-plugin:0.5.2.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot' 
apply plugin: 'io.spring.dependency-management' 

jar {
    baseName = 'Demo-Server'
    version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile("org.springframework.cloud:spring-cloud-config-server:1.0.2.RELEASE")
    testCompile("org.springframework.boot:spring-boot-starter-test") 
}

eclipse {
    classpath {
         containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
         containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
    }
}
application.yml
server:

  port: 8888


spring:

  cloud:

    config:

      server:

        git :

          uri: https://github.com/samzhu/microservices-lab-configuration
bootstrap.yml
spring:

  application:

    name: config-service
ConfigServerApplication.java
package demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {

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

Client端

build.gradle
buildscript {
    ext {
        springBootVersion = '1.2.5.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 
        classpath("io.spring.gradle:dependency-management-plugin:0.5.2.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot' 
apply plugin: 'io.spring.dependency-management' 

jar {
    baseName = 'Demo-Client'
    version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile('org.springframework.cloud:spring-cloud-config-client:1.0.2.RELEASE')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.springframework.boot:spring-boot-starter-actuator')
  testCompile("org.springframework.boot:spring-boot-starter-test") 
}

eclipse {
    classpath {
         containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
         containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
    }
}
application.yml
server:

  port: 8080
bootstrap.yml
spring:

  application:

    name: config-client

  cloud:

    config:

      uri: http://localhost:8888
Application.java
package demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;

@SpringBootApplication
public class Application {

    @Autowired
    void setEnvironment(Environment e) {
        System.out.println(e.getProperty("configuration.projectName"));
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
ProjectNameRestController.java
package demo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RefreshScope
public class ProjectNameRestController {

    @Value("${configuration.projectName}")
    private String projectName;

    @RequestMapping("/project-name")
    public String projectName() {
        return this.projectName;
    }
}

啟動後Client可以從Server取得GitHub上的設定值

config-client.properties
configuration.projectName=Spring Cloud

向Server端確認參數

curl -X GET 'http://localhost:8888/config-client/master'
{
  "name": "config-client",
  "profiles": [
    "master"
  ],
  "label": "master",
  "propertySources": [
    {
      "name": "https://github.com/samzhu/microservices-lab-configuration/config-client.properties",
      "source": {
        "configuration.projectName": "Spring Cloud"
      }
    }
  ]
}

向Client取得project-name

curl -X GET 'http://localhost:8080/project-name'
Spring Cloud

更新GitHub上的檔案

config-client.properties
configuration.projectName=Spring Cloud Sam Test

觸發Client更新

curl -X POST 'http://localhost:8080/refresh'
[
    "configuration.projectName"
]

再檢查可以發現已經更新了

curl -X GET 'http://localhost:8080/project-name'
Spring Cloud Sam Test

但是這樣子還是必須每一台 Client 去觸發 Refresh,所以 Spring Cloud 提供一個做法透過 RabbitMQ 來觸發

修改 Client 部分

build.gradle 增加 dependencies

compile('org.springframework.cloud:spring-cloud-starter-bus-amqp:1.0.3.RELEASE')

application.yml 增加 rabbitmq 部分

spring:
  rabbitmq:
    addresses: ${vcap.services.${PREFIX:}rabbitmq.credentials.uri:amqp://${RABBITMQ_HOST:192.168.56.102}:${RABBITMQ_PORT:5672}}

安裝 RabbitMQ Server

練習安裝在Ububtu上

echo "deb http://www.rabbitmq.com/debian/ testing main" | sudo tee -a /etc/apt/sources.list.d/rabbitmq.list

# 加入 APT repository
wget https://www.rabbitmq.com/rabbitmq-signing-key-public.asc
sudo apt-key add rabbitmq-signing-key-public.asc

sudo apt-get update

# 安裝 RabbitMQ server 套件
sudo apt-get install rabbitmq-server

# 啟用 RabbitMQ Management Web Console
sudo rabbitmq-plugins enable rabbitmq_management

# 開啟遠端使用者可登入 web console
sudo sh -c "echo '[{rabbit, [{loopback_users, []}]}].' > /etc/rabbitmq/rabbitmq.config"
sudo service rabbitmq-server restart

# 開啟瀏覽器使用 guest guest 登入觀察
http://192.168.56.102:15672/

之後啟動兩個 Client

java -jar Demo-Client-0.0.1-SNAPSHOT.jar
java -jar Demo-Client-0.0.1-SNAPSHOT.jar --server.port=9000

重複上面動作 更新 GitHub檔案後
對 Client 8080 送出更新指令

curl -X POST 'http://localhost:8080/bus/refresh'

可以發現 Client 9000 也更新了

curl -X GET 'http://localhost:9000/project-name'

很簡單的練習,還沒有考慮到安全性跟Docker後的處理

參考連結
http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html
http://www.javaworld.com/article/2927920/cloud-computing/build-self-healing-distributed-systems-with-spring-cloud.html
http://stackoverflow.com/questions/27230924/spring-cloud-configuration-recommended-architecture-in-data-center
https://blog.ik.am/#/entries/290
http://godleon.github.io/blog/2015/06/02/Build-RabbitMQ-Cluster-in-Ubuntu/
http://rabbitmq-into-chinese.readthedocs.org/zh_CN/latest/installation/Installing_on_Debian_Ubuntu/
http://www.rabbitmq.com/access-control.html
https://www.rabbitmq.com/install-debian.html
http://my.oschina.net/OpenSourceBO/blog/379732

← Ubuntu 安裝 FTP use Quartz in Spring Boot →
 
comments powered by Disqus