Home | 簡體中文 | 繁體中文 | 雜文 | 打賞(Donations) | 雲棲社區 | OSChina 博客 | Facebook | Linkedin | 知乎專欄 | Github | Search | About

第 8 章 Spring Cloud

目錄

8.1. Spring Cloud Config
8.1.1. Git 倉庫
8.1.1.1. 分支
8.1.1.2. HTTP Auth
8.1.1.3. basedir
8.1.1.4. 本地git倉庫
8.1.2. Server
8.1.2.1. Maven
8.1.2.2. Application
8.1.2.3. application.properties
8.1.2.4. 測試伺服器
8.1.3. Client
8.1.3.1. Maven pom.xml
8.1.3.2. Application
8.1.3.3. bootstrap.properties
8.1.3.4. 測試 client
8.1.4. Config server 用戶認證
8.1.4.1. Server 配置
8.1.4.1.1. application.properties
8.1.4.1.2. Maven
8.1.4.1.3. 測試是否生效
8.1.4.2. Client 配置
8.1.5. 加密敏感數據
8.1.6. Spring Cloud Config JDBC Backend
8.1.6.1.
8.1.6.2.
8.1.6.3.
8.1.6.4. application.properties
8.1.7. Old
8.1.7.1. Server (Camden.SR5)
8.1.7.2. Client (Camden.SR5)
8.2. Spring Cloud Netflix
8.2.1. Eureka Server
8.2.1.1. Maven
8.2.1.2. Application
8.2.1.3. application.properties
8.2.1.4. 檢查註冊伺服器
8.2.1.5. 為 Eureka Server 增加用戶認證
8.2.1.5.1. Maven
8.2.1.5.2. application.properties
8.2.1.5.3. Eureka Client
8.2.1.5.4. Feign Client
8.2.2. Eureka Client
8.2.2.1. Maven
8.2.2.2. Application
8.2.2.3. RestController
8.2.2.4. application.properties
8.2.2.5. 測試
8.2.3. Feign client
8.2.3.1. Maven
8.2.3.2. Application
8.2.3.3. interface
8.2.3.4. application.properties
8.2.3.5. 測試
8.2.3.6. fallback
8.2.4. Zuul
8.2.4.1. Maven
8.2.4.2. EnableZuulProxy
8.2.4.3. application.yml
8.2.4.4. 負載均衡配置
8.3. Spring Cloud Finchley
8.4. Spring Cloud 相關的 application.properties 配置
8.4.1. 啟用或禁用 bootstrap
8.5. FAQ
8.5.1. Feign請求超時
8.5.2. 已停止的微服務節點註銷慢或不註銷
8.5.3. Eureka Client (Dalston.SR1)
8.5.3.1. Maven
8.5.3.2. Application
8.5.3.3. RestController
8.5.3.4. application.properties
8.5.3.5. 測試
8.5.4. Feign 啟動出錯 PathVariable annotation was empty on param 0.
8.5.5. Feign 提示 Consider defining a bean of type 'common.feign.Cms' in your configuration.

8.1. Spring Cloud Config

8.1.1. Git 倉庫

克隆倉庫

			git clone https://github.com/netkiller/config.git
		

創建配置檔案 server-development.properties

			vim server-development.properties

			test.a=KKOOKK
			message=Hello world
		

提交配置檔案

			git commit -a
			git push
		

配置檔案格式

		
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties		
		
		

label 是指 git 的分支

8.1.1.1. 分支
				spring.cloud.config.label=mybranch
			
8.1.1.2. HTTP Auth
				spring.application.name=config-server
				spring.cloud.config.server.git.uri=https://netkiller:xxxxxx@github.com/xyz/microservices-configs.git
			

				spring.application.name=config-server
				spring.cloud.config.server.git.uri=https://github.com/xyz/microservices-configs.git
				spring.cloud.config.server.git.username=netkiller
				spring.cloud.config.server.git.password=password
			
8.1.1.3. basedir
				spring.cloud.config.server.git.basedir=api/configs
			
8.1.1.4. 本地git倉庫

創建本地倉庫

			
mkdir ~/config
cd config
git init
git config --global user.email "neo.chen@live.com"
git config --global user.name "Neo Chen"
			
			

創建測試配置檔案

			
# cat app-test.properties 
name=neo
age=10
			
			

提交配置檔案

			
git add app-test.properties 
git commit -a
			
			

檢查檔案是否提交成功

			
[root@netkiller config]# git log
commit aee6c35bacf1740004e02f8ecdcf2fd322422405
Author: Neo Chen <neo.chen@live.com>
Date:   Thu Nov 2 14:18:48 2017 +0800

        new file:   app-test.properties
			
			

配置 Spring cloud config 伺服器,修改 application.properties 檔案

			
server.port=8888
#spring.cloud.config.server.git.uri=/opt/config
spring.cloud.config.server.git.uri= file://${user.home}/config
security.user.name=cfg
security.user.password=s3cr3t

## Spring cloud GIT Repository file
${user.home}/config/root-server.properties		
			
			

檢驗配置中心

			
[root@netkiller config]# curl http://cfg:test@localhost:8888/app-test.properties
age: 10
name: neo
			
			

8.1.2. Server

8.1.2.1. Maven
			
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>cn.netkiller</groupId>
	<artifactId>config</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>config</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.6.RELEASE</version>
		<relativePath />
	</parent>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-config</artifactId>
				<version>1.3.1.RELEASE</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>


	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

			
			
8.1.2.2. Application

Application

			
package cn.netkiller.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration
@EnableDiscoveryClient
@EnableConfigServer
@SpringBootApplication
public class Application {

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

}
			
			
8.1.2.3. application.properties
				server.port=8888
				spring.cloud.config.server.git.uri=https://github.com/netkiller/config.git
			
8.1.2.4. 測試伺服器
				neo@netkiller $ curl http://localhost:8888/server-development.json
				{"message":"Hello world","test":{"a":"KKOOKK"}}
			

8.1.3. Client

8.1.3.1. Maven pom.xml
			
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>netkiller.cn</groupId>
	<artifactId>cloud</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.2.RELEASE</version>
		<relativePath />
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencyManagement>
	    <dependencies>
	        <dependency>
	            <groupId>org.springframework.cloud</groupId>
	            <artifactId>spring-cloud-config</artifactId>
	            <version>1.3.1.RELEASE</version>
	            <type>pom</type>
	            <scope>import</scope>
	        </dependency>
	    </dependencies>
	</dependencyManagement>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>			
			
			
8.1.3.2. Application
			
package cn.netkiller.cloud.client;

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

@SpringBootApplication
public class Application {

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

@RefreshScope
@RestController
class MessageRestController {

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

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

注意 @RefreshScope 註解

8.1.3.3. bootstrap.properties
			
spring.application.name=server-development
spring.cloud.config.uri=http://localhost:8888
management.security.enabled=false			
			
			
8.1.3.4. 測試 client
				neo@netkiller $ curl http://localhost:8080/message.json
				Hello world
			

8.1.4. Config server 用戶認證

8.1.4.1. Server 配置
8.1.4.1.1. application.properties
					server.port=8888
					spring.cloud.config.server.git.uri=ssh://localhost/config-repo
					spring.cloud.config.server.git.clone-on-start=true
					security.user.name=cfg
					security.user.password=s3cr3t
				
8.1.4.1.2. Maven
				
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>cn.netkiller</groupId>
	<artifactId>config</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>config</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.7.RELEASE</version>
		<relativePath />
	</parent>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-config</artifactId>
				<version>1.3.1.RELEASE</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>
				
				
				
8.1.4.1.3. 測試是否生效
				
neo@MacBook-Pro ~/deployment % curl http://cfg:s3cr3t@localhost:8888/neo-development.json
{"message":"Hello world","test":{"name":"neo"}}		
				
				
8.1.4.2. Client 配置

bootstrap.properties:

				spring.application.name=project
				spring.profiles.active=development
				spring.cloud.config.uri=http://localhost:8888
				spring.cloud.config.username=cfg
				spring.cloud.config.password=s3cr3t
			

8.1.5. 加密敏感數據

Config server 創建證書

		
keytool -genkeypair -alias config-server-key \
       -keyalg RSA -keysize 4096 -sigalg SHA512withRSA \
       -dname 'CN=Config Server,OU=Spring Cloud,O=Netkiller' \
       -keypass s3cr3t -keystore config-server.jks \
       -storepass passw0rd		
		
		

application.properties 中配置證書

		
# spring.cloud.config.server.encrypt.enabled=true
encrypt.key-store.location=classpath:/config-server.jks
encrypt.key-store.alias=config-server-key
encrypt.key-store.secret=s3cr3t
encrypt.key-store.password=passw0rd
		
		

測試加密

		
curl -X POST --data-urlencode mypassword http://localhost:8888/encrypt
		
		
		
$ PASSWORD=$(curl -X POST --data-urlencode passw0rd http://cfg:s3cr3t@localhost:8888/encrypt)
$ echo "user.password=$PASSWORD" >> api-interface-development.properties
$ git commit -am 'Added encrypted password'

# 刷新配置
$ curl -X POST http://cfg:s3cr3t@localhost:8888/refresh		
		
		

8.1.6. Spring Cloud Config JDBC Backend

8.1.6.1. 
			
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.11.RELEASE</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.flywaydb</groupId>
        <artifactId>flyway-core</artifactId>
        <version>5.0.3</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.21</version>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Edgware.SR3</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>			
			
			
8.1.6.2. 
			
CREATE TABLE `properties` (
  `key` varchar(50) NOT NULL,
  `value` varchar(500) NOT NULL,
  `application` varchar(50) NOT NULL,
  `profile` varchar(50) NOT NULL,
  `label` varchar(50) NOT NULL,
  PRIMARY KEY (`KEY`, `APPLICATION`, `PROFILE`, `LABEL`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;			
			
			
8.1.6.3. 
			
@EnableConfigServer
@SpringBootApplication
public class Application {

	//@Autowired
	//JdbcTemplate jdbcTemplate;

    public static void main(String[] args) {
    	SpringApplication.run(Application.class, args);
        // 測試用數據,僅用於本文測試使用
        JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
        jdbcTemplate.execute("delete from properties");
        jdbcTemplate.execute("INSERT INTO properties VALUES('neo.message', 'helloworld', 'api', 'stage', 'master')");
        jdbcTemplate.execute("INSERT INTO properties VALUES('neo.message', 'helloworld', 'new', 'online', 'master')");
        jdbcTemplate.execute("INSERT INTO properties VALUES('neo.message', 'helloworld', 'test', 'online', 'develop')");
        jdbcTemplate.execute("INSERT INTO properties VALUES('neo.message', 'helloworld', 'cms', 'online', 'master')");
    }

}			
			
			
8.1.6.4. application.properties

spring.profiles.active=jdbc 將配置中心的存儲實現切換到jdbc的方式, 必須設置。

			
server.port=8888
spring.profiles.active=jdbc

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/config-server-db
spring.datasource.username=root
spring.datasource.password=xxxx

# or

spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url= jdbc:postgresql://localhost:5432/configdb
spring.datasource.username=xxxxxx
spring.datasource.password=xxxxxx			
			
			

8.1.7. Old

8.1.7.1. Server (Camden.SR5)

Maven pom.xml 請使用最新版本 1.3.1, 下面的 maven 是早期 Camden.SR5 版本的配置

			
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>netkiller.cn</groupId>
	<artifactId>cloud</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>Neo</name>
	<description>http://www.netkiller.cn</description>
	<packaging>jar</packaging>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.3.RELEASE</version>
		<relativePath />
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Camden.SR5</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>
			
			
8.1.7.2. Client (Camden.SR5)

Maven pom.xml Camden.SR5 為早期版本,盡可以使用新版

			
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>netkiller.cn</groupId>
	<artifactId>cloud</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.2.RELEASE</version>
		<relativePath />
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Camden.SR5</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>