Spring Cloud 是一個基於 Spring Boot 實現的雲應用開發工具,它為基於 JVM 的雲應用開發中涉及的配置管理、服務發現、斷路器、智能路由、微代理、控制匯流排、全局鎖、決策競選、分散式會話和集群狀態管理等操作提供了一種簡單的開發方式。通過 Spring Boot 風格進行再封裝屏蔽 ...
Spring Cloud 是一個基於 Spring Boot 實現的雲應用開發工具,它為基於 JVM 的雲應用開發中涉及的配置管理、服務發現、斷路器、智能路由、微代理、控制匯流排、全局鎖、決策競選、分散式會話和集群狀態管理等操作提供了一種簡單的開發方式。通過 Spring Boot 風格進行再封裝屏蔽掉了複雜的配置和實現原理,最終給開發者留出了一套簡單易懂、易部署和易維護的分散式系統開發工具包。
Spring Cloud 包含了多個子項目(針對分散式系統中涉及的多個不同開源產品),比如:Spring Cloud Config、Spring Cloud Netflix、Spring Cloud CloudFoundry、Spring Cloud AWS、Spring Cloud Security、Spring Cloud Commons、Spring Cloud Zookeeper、Spring Cloud CLI 等項目。
項目地址:https://github.com/yuezhongxin/spring-cloud-consul-sample
ASP.NET Core 2.0 & Docker & Consul 的實現:https://github.com/yuezhongxin/HelloDocker.Sample
目前的測試站點,使用 ASP.NET Core 結合 Conusl 和 Fabio 搭建的微服務集群,因為各服務之間的通信基於 HTTP REST 協議,所以服務的實現可以跨語言,下麵我們就開發一個 Spring Boot 服務,然後使用 Spring Cloud Consul 將服務註冊到已有的集群中。
Java 開發工具我選用的 IntelliJ IDEA(MacOS 安裝教程),目前使用很好(Color Scheme 使用系統的 Darcula,字體大小 14),Java SDK 需要額外下載安裝(我安裝的版本 10)。
因為第一次使用 IntelliJ IDEA,下麵我把創建項目的過程,貼詳細一點。
首先,創建項目(選擇“Spring Initializr”,Spring Boot 項目),預設選擇 Java SDK 10:
然後填寫項目的基本信息(Artifact 為"spring-cloud-consul-sample",其他為預設):
註:Maven 是一個項目管理和構建工具,包含三個關鍵組件:項目對象模型(POM)、依賴項管理模型、構建生命周期和階段。
Group ID 和 Artifact ID 的區別,如果把 Group ID 看作是公司,那 Artifact ID 就可以看作是公司部門,有點類似於 .NET 中的解決方案和類庫的關係,比如 Spring Cloud 項目的 Group ID 為org.springframework.cloud
,Spring Cloud Consul 的 Artifact ID 為spring-cloud-starter-consul-discovery
。
下麵選擇創建 Spring Boot 項目類型(選擇 Web 依賴項):
然後填寫項目名稱和項目目錄:
然後點擊“Finish”,就完成啦。
像開發 ASP.NET Core 應用程式一樣,我們需要先引用各種程式包,Spring Boot 項目也是一樣,因為使用 Maven 進行依賴管理,我們需要在pom.xml
中配置依賴關係,配置如下:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<scope>compile</scope>
</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-consul-dependencies</artifactId>
<version>2.0.0.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
引用spring-cloud-starter-consul-discovery
對應 Spring Cloud Consul,引用spring-boot-starter-actuator
用作健康檢查(地址/actuator/health
),另外 Actuator 還支持項目的監控和管理。
這裡再說下節點的作用:
parent
:父引用配置,會繼承父引用的配置。dependencies
:當前引用配置,如果父引用配置了,子項目會自動引用。dependencyManagement
:當然引用配置,如果父引用配置了,子項目不會自動引用,子項目只要用到的時候引用,不需要配置版本號。
然後再貼一下SpringCloudConsulSampleApplication.java
的代碼:
package com.example.springcloudconsulsample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.discovery.DiscoveryClient;
@EnableDiscoveryClient
@RestController
@SpringBootApplication
public class SpringCloudConsulSampleApplication {
@Autowired
private DiscoveryClient discoveryClient;
/**
* 獲取所有服務
*/
@RequestMapping("/services")
public Object services() {
return discoveryClient.getServices();
}
@RequestMapping("/home")
public String home() {
return "Hello World";
}
public static void main(String[] args) {
SpringApplication.run(SpringCloudConsulSampleApplication.class, args);
}
}
增加@EnableDiscoveryClient
註解,項目啟動的時候,會註冊當前 Spring Boot 服務。
在使用 ASP.NET Core 註冊服務的時候,配置信息會填寫在代碼中(如服務名稱和埠等,當然也可以在配置文件),然後使用 Consul 組件註冊服務(調用 Consul HTTP REST)。
Spring Cloud Consul 註冊服務的話,需要添加配置文件(Spring Boot 項目資源文件在 resources 目錄下)。
application.properties
中添加配置:
spring.application.name=spring-boot-service
然後添加application.yml
配置文件:
debug: true
server:
port: 24543
spring:
cloud:
consul:
host: 127.0.0.1
port: 8500
discovery:
register: true
hostname: 10.9.10.215
serviceName: ${spring.application.name}
healthCheckPath: /actuator/health
healthCheckInterval: 15s
tags: urlprefix-/${spring.application.name}
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
上面配置需要再詳細說明說明下:
debug
配置是否調試模式,如果打包發佈的話,需要設置為false
。server.port
配置的是 Spring Boot 服務的埠。spring.cloud.consul.host/port
配置的是本地 Consul 的地址和埠(Server 節點和 Client 節點都可以),Spring Cloud Consul 會調用 Consul HTTP REST 介面,進行服務註冊。spring.cloud.consul.discovery.true
配置啟動是否註冊服務,spring.cloud.consul.discovery.hostname
配置 Spring Boot 服務的主機地址,也可以不進行配置,預設本機地址。spring.cloud.consul.discovery.serviceName
配置 Consul 註冊的服務名稱,${spring.application.name}
變數是我們上面application.properties
配置文件中添加的配置。spring.cloud.consul.discovery.healthCheckPath
配置 Consul 健康檢查地址,Actuator 組件幫我們進行了實現,所以我們不需要額外的實現,地址在服務啟動的時候,列印信息裡面可以看到。spring.cloud.consul.discovery.healthCheckInterval
配置 Consul 健康檢查頻率,也就是心跳頻率。spring.cloud.consul.discovery.tags
配置 Consul 註冊服務的 Tags,設置為urlprefix-/serviceName
的格式,是自動註冊到 Fabio 集群中。spring.cloud.consul.discovery.instanceId
配置 Consul 註冊服務 ID。
上面的工作做完之後,我們還需要在本地啟動 Consul 和 Fabio,參考:Mac OS、Ubuntu 安裝及使用 Consul
然後我們就可以直接使用 IntelliJ IDEA 調試項目了,按Shift + F9
進行調試。
上面說到 Actuator 的列印信息:
2018-03-28 10:09:54.645 INFO 63482 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2018-03-28 10:09:54.646 INFO 63482 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2018-03-28 10:09:54.647 INFO 63482 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto protected java.util.Map<java.lang.String, java.util.Map<java.lang.String, org.springframework.boot.actuate.endpoint.web.Link>> org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping.links(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
或者我們也可以使用 Maven 打包發佈,然後使用命令啟動服務。使用 IntelliJ IDEA 中的 Maven 進行打包,或者使用 Maven 命令打包都可以,這邊我們使用Maven 命令進行打包。
在我們安裝 IntelliJ IDEA 的時候,Maven 自動安裝了,但直接敲mvn -v
會發現命令找不到,需要我們配置一下環境變數。
我自己的 Maven 文件目錄是/Applications/IntelliJ IDEA.app/Contents/plugins/maven/lib/maven3
,可以在 IntelliJ IDEA 的配置設置中找到,然後我們執行下麵的命令:
$ export M2_HOME="/Applications/IntelliJ IDEA.app/Contents/plugins/maven/lib/maven3" &&
export PATH=$PATH:$M2_HOME/bin &&
chmod a+x "/Applications/IntelliJ IDEA.app/Contents/plugins/maven/lib/maven3/bin/mvn"
然後檢查下 Maven 命令是否生效:
$ mvn -v
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T00:41:47+08:00)
Maven home: /Applications/IntelliJ IDEA.app/Contents/plugins/maven/lib/maven3
Java version: 10, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk-10.jdk/Contents/Home
Default locale: zh_CN_#Hans, platform encoding: UTF-8
OS name: "mac os x", version: "10.13.2", arch: "x86_64", family: "mac"
然後我們修改application.yml
中的debug:false
,使用 Maven 進行打包(目錄切換到pom.xml
平級):
$ mvn clean package -Dmaven.test.skip=true
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building spring-cloud-consul-sample 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.0.0:clean (default-clean) @ spring-cloud-consul-sample ---
[INFO] Deleting /Users/xishuai/Documents/項目文件/測試項目/spring-cloud-consul-sample/target
[INFO]
[INFO] --- maven-resources-plugin:3.0.1:resources (default-resources) @ spring-cloud-consul-sample ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ spring-cloud-consul-sample ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/xishuai/Documents/項目文件/測試項目/spring-cloud-consul-sample/target/classes
[INFO]
[INFO] --- maven-resources-plugin:3.0.1:testResources (default-testResources) @ spring-cloud-consul-sample ---
[INFO] Not copying test resources
[INFO]
[INFO] --- maven-compiler-plugin:3.7.0:testCompile (default-testCompile) @ spring-cloud-consul-sample ---
[INFO] Not compiling test sources
[INFO]
[INFO] --- maven-surefire-plugin:2.20.1:test (default-test) @ spring-cloud-consul-sample ---
[INFO] Tests are skipped.
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ spring-cloud-consul-sample ---
[INFO] Building jar: /Users/xishuai/Documents/項目文件/測試項目/spring-cloud-consul-sample/target/spring-cloud-consul-sample-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.0.0.RELEASE:repackage (default) @ spring-cloud-consul-sample ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.815 s
[INFO] Finished at: 2018-03-28T10:26:46+08:00
[INFO] Final Memory: 30M/114M
[INFO] ------------------------------------------------------------------------
生成的 jar 程式包,會在 target 目錄下,文件為spring-cloud-consul-sample-0.0.1-SNAPSHOT.jar
(格式為項目名 + 版本號
),然後我們可以直接啟動服務了:
$ java -jar target/spring-cloud-consul-sample-0.0.1-SNAPSHOT.jar
2018-03-28 10:33:31.750 INFO 63875 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2b662a77: startup date [Wed Mar 28 10:33:31 CST 2018]; root of context hierarchy
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$1 (jar:file:/Users/xishuai/Documents/項目文件/測試項目/spring-cloud-consul-sample/target/spring-cloud-consul-sample-0.0.1-SNAPSHOT.jar!/BOOT-INF/lib/spring-core-5.0.4.RELEASE.jar!/) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2018-03-28 10:33:31.971 INFO 63875 --- [ main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2018-03-28 10:33:32.015 INFO 63875 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$4d45e598] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.0.RELEASE)
查看健康檢查是否成功:
查看 Consul 是否服務註冊成功:
查看 Fabio 集群是否包含服務:
服務註冊成功之後,我們可以手動進行發現服務,或者通過 Spring Cloud Ribbon/Feign 組件進行發現,並提供負載均衡功能(類似於 Fabio 功能),後面再研究下。
參考資料:
- ameizi/spring-cloud-consul-example
- Spring Cloud構建微服務架構:服務註冊與發現(Eureka、Consul)
- Spring Cloud Consul
- Spring Cloud Consul
- 使用 Spring Cloud Consul 實現服務的註冊和發現
- Service Discovery with Consul
- spring-cloud-consul/spring-cloud-consul-sample
- Spring Boot Actuator 監控端點小結
- Spring Cloud(二)Consul 服務治理實現(推薦)
- 構建微服務(二)服務註冊與發現
- springboot(十二):springboot 如何測試打包部署(推薦)
- springcloud(一):大話 Spring Cloud(推薦)