springcloud是微服務架構的集大成者,基於springboot構建,將一系列優秀的組件進行了整合。
中文文檔:https://springcloud.cc/
官方文檔:http://projects.spring.io/spring-cloud/#quick-start
構建環境
請一定要注意spring boot版本和spring cloud版本的匹配關係:https://spring.io/projects/spring-cloud
軟件 | 版本 |
---|---|
SpringCloud | Hoxton.RELEASE |
Spring Boot | 2.2.4.RELEASE |
Jdk | 1.8 |
Maven | 3.6 |
一、創建註冊中心
編寫POM文件添加Spring-Cloud基本應用包
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- 模型版本。maven2.0必須是這樣寫,現在是maven2唯一支持的版本 -->
<modelVersion>4.0.0</modelVersion>
<!-- 項目的的唯一標識符,並且配置時生成的路徑也是由此生成,maven會將該項目打成的jar包放本地路徑:/com/springcloud -->
<groupId>com.springcloud</groupId>
<!-- 構件的標識符,它和group ID一起唯一標識一個構件,一個groupId下面可能多個項目,就是靠artifactId來區分的。
Maven爲項目產生的構件包括:JARs,源碼,二進制發佈和WARs等 -->
<artifactId>springcloud-root</artifactId>
<!-- 項目當前版本號,格式爲:主版本.次版本.增量版本-限定版本號 -->
<version>0.0.1-SNAPSHOT</version>
<!-- 項目產生的構件類型,如pom,jar, maven-plugin, ejb, war, ear, rar, par,默認爲jar -->
<packaging>pom</packaging>
<!-- 項目的名稱, Maven產生的文檔用 -->
<name>spring-cloud</name>
<!-- 項目主頁的URL, Maven產生的文檔用 -->
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 父項目的座標。如果項目中沒有規定某個元素的值,那麼父項目中的對應值即爲項目的默認值。座標包括group ID,artifact ID和 version。 -->
<parent>
<!-- 被繼承的父項目的唯一標識符 -->
<groupId>org.springframework.boot</groupId>
<!-- 被繼承的父項目的構件標識符 -->
<artifactId>spring-boot-starter-parent</artifactId>
<!-- 被繼承的父項目的版本 -->
<version>2.2.4.RELEASE</version>
</parent>
<modules>
<!--註冊中心項目-->
<module>spring-register</module>
<module>springcloud-eureka</module>
<module>springcloud-common</module>
<module>springcloud-zuul</module>
<module>springcloud-eureka-cluster</module>
</modules>
<!-- 該元素描述了項目相關的所有依賴。 這些依賴組成了項目構建過程中的一個個環節。自動從項目定義的倉庫中下載。-->
<dependencyManagement>
<dependencies>
<dependency>
<!-- 依賴的group ID -->
<groupId>org.springframework.cloud</groupId>
<!-- 依賴的artifact ID -->
<artifactId>spring-cloud-dependencies</artifactId>
<!-- 依賴的版本號。 在Maven 2裏, 可以配置成版本號的範圍。 -->
<version>Hoxton.RELEASE</version>
<!-- 依賴類型。 -->
<type>pom</type>
<!-- 依賴範圍。在項目發佈過程中,幫助決定哪些構件被包括進來
- compile :默認範圍,用於編譯
- provided:類似於編譯,但支持你期待jdk或者容器提供,類似於classpath
- runtime: 在執行時需要使用
- test: 用於test任務時使用
- system: 需要外在提供相應的元素。通過systemPath來取得
- systemPath: 僅用於範圍爲system。提供相應的路徑
- optional: 當項目自身被依賴時,標註依賴是否傳遞。用於連續依賴時使用 -->
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--使用aliyun鏡像-->
<repositories>
<repository>
<id>alimaven</id>
<name>Maven Aliyun Mirror</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
二、創建註冊中心項目springcloud-eureka
微服務架構中最核心的部分是服務治理,服務治理最基礎的組件是註冊中心。Spring Cloud支持了Zookeeper、Consul和Eureka,官方推薦Eureka。
創建一個maven-module,通過maven指定父類目錄
添加依賴包文件POM.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.springcloud</groupId>
<artifactId>springcloud-root</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>springcloud-eureka</artifactId>
<name>springcloud-eureka</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
spring-cloud-starter-eureka-server:jar is missing 錯誤
Project build error: 'dependencies.dependency.version' for org.springframework.cloud:spring-cloud-starter-eureka-server:jar is missing.
change: spring-cloud-starter-eureka-server to spring-cloud-starter-netflix-eureka-server
添加註冊中心啓動類
package org.springcloud.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication //spring-boot 啓動註解
@EnableEurekaServer // spring-cloud 服務註解
public class RegisterMain
{
public static void main( String[] args )
{
SpringApplication.run(RegisterMain.class, args);
}
}
配置application.yml文件
spring:
application:
# 當前服務名
name: springcloud-eureka
freemarker:
prefer-file-system-access: false
server:
# 端口號
port: 8899
---
eureka:
instance:
hostname: localhost
client:
# 檢索服務
fetch-registry: false
# 是否將自己註冊到eureka
register-with-eureka: false
# 客戶端默認去這個地址找註冊中心
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
# 當eureka啓動時,不能從集羣節點中獲取到instance註冊信息,應該等多久
wait-time-in-ms-when-sync-empty: 0
enable-self-preservation: true
# eureka多長時間更新一次數據
peer-eureka-nodes-update-interval-ms: 100000
ERROR org.springframework.boot.SpringApplication - Application run failed 錯誤
15:02:33.112 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.<init>([Ljava/lang/Object;)V
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.bootstrapServiceContext(BootstrapApplicationListener.java:157)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:98)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:64)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:76)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:53)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:345)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:140)
at org.springcloud.eureka.RegisterMain.main(RegisterMain.java:16)
spring boot版本兼容性導致的,在pom.xml中修改配置文件,將springcloud的版本與springboot的版本對應起來即可解決。
spring boot版本和spring cloud版本的匹配關係:
https://spring.io/projects/spring-cloud
Spring Cloud | Spring Boot |
---|---|
Hoxton | 2.2.x |
Greenwich | 2.1.x |
Finchley | 兼容Spring Boot 2.0.x,不兼容Spring Boot 1.5.x |
Dalston和Edgware | 兼容Spring Boot 1.5.x,不兼容Spring Boot 2.0.x |
Camden | 兼容Spring Boot 1.4.x,也兼容Spring Boot 1.5.x |
Brixton | 兼容Spring Boot 1.3.x,也兼容Spring Boot 1.4.x |
APPLICATION FAILED TO START 錯誤
***************************
APPLICATION FAILED TO START
***************************
Description:
An attempt was made to call a method that does not exist. The attempt was made from the following location:
org.springframework.cloud.client.discovery.health.DiscoveryCompositeHealthIndicator.<init>(DiscoveryCompositeHealthIndicator.java:41)
The following method did not exist:
org.springframework.boot.actuate.health.CompositeHealthIndicator.<init>(Lorg/springframework/boot/actuate/health/HealthAggregator;)V
The method's class, org.springframework.boot.actuate.health.CompositeHealthIndicator, is available from the following locations:
jar:file:/E:/SpringBoot/Maven-Repository/org/springframework/boot/spring-boot-actuator/2.2.4.RELEASE/spring-boot-actuator-2.2.4.RELEASE.jar!/org/springframework/boot/actuate/health/CompositeHealthIndicator.class
It was loaded from the following location:
file:/E:/SpringBoot/Maven-Repository/org/springframework/boot/spring-boot-actuator/2.2.4.RELEASE/spring-boot-actuator-2.2.4.RELEASE.jar
將springcloud的版本與springboot的版本對應起來即可解決。
Unable to start reactive web server 錯誤
org.springframework.context.ApplicationContextException: Unable to start reactive web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ReactiveWebApplicationContext due to missing ReactiveWebServerFactory bean.
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.onRefresh(ReactiveWebServerApplicationContext.java:81) ~[spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:544) ~[spring-context-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:66) ~[spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) ~[spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:140) [spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
at org.springcloud.eureka.RegisterMain.main(RegisterMain.java:15) [classes/:na]
Caused by: org.springframework.context.ApplicationContextException: Unable to start ReactiveWebApplicationContext due to missing ReactiveWebServerFactory bean.
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.getWebServerFactoryBeanName(ReactiveWebServerApplicationContext.java:100) ~[spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.createWebServer(ReactiveWebServerApplicationContext.java:88) ~[spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.onRefresh(ReactiveWebServerApplicationContext.java:78) ~[spring-boot-2.2.4.RELEASE.jar:2.2.4.RELEASE]
添加webflux的依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
運行啓動類,訪問http://localhost:8899即可,如下圖
註冊中心已經完成。
三、註冊中心密碼配置
在POM.xml中增加:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
版本可以在此網站查詢:
https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security
application.yml 文件中增加配置
spring:
application:
name: springcloud-eureka
freemarker:
prefer-file-system-access: false
security:
basic:
enable: true
user:
name: admin
password: 123456
server:
port: 8899
---
eureka:
instance:
hostname: localhost
client:
fetch-registry: false
register-with-eureka: false
service-url:
defaultZone: http://${security.user.name}:${security.user.password}@${eureka.instance.hostname}:${server.port}/eureka/
server:
wait-time-in-ms-when-sync-empty: 0
enable-self-preservation: true
peer-eureka-nodes-update-interval-ms: 100000
再次啓動後訪問http://localhost:8899,如下圖
輸入用戶名密碼後,進入頁面
四、創建服務註冊到註冊中心
創建一個maven module 項目
添加依賴包文件POM.xml
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.springcloud</groupId>
<artifactId>springcloud-root</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>springcloud-common</artifactId>
<name>springcloud-common</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
添加客戶端啓動類
package org.springcloud.common;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient //Eureka Client
public class CommonClient
{
public static void main( String[] args )
{
SpringApplication.run(CommonClient.class, args);
}
}
配置application.yml文件
spring:
application:
name: springcloud-common
freemarker:
prefer-file-system-access: false
security:
user:
name: admin
password: 123456
server:
port: 8001
eureka:
instance:
hostname: localhost
client:
service-url:
defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@${eureka.instance.hostname}:8899/eureka/
運行客戶端啓動類,可以看到該客戶端已經被註冊到服務端,如下圖
cannot execute any request on any know server 錯誤
在eurka服務中添加一個安全認證類
package org.springcloud.eureka;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// Configure HttpSecurity as needed (e.g. enable http basic).
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
http.csrf().disable();
//爲了可以使用 http://${user}:${password}@${host}:${port}/eureka/ 這種方式登錄,所以必須是httpBasic,
http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
}
重新運行即可。
五、Eureka高可用集羣
將 application.yml 文件複製三分:application-peer1.yml,application-peer2.yml,application-peer3.yml。
分別添加配置項如下:
- application-peer1.yml
spring:
application:
name: springcloud-eureka-cluster
freemarker:
prefer-file-system-access: false
security:
user:
name: admin
password: 123456
server:
port: 8897
---
eureka:
instance:
hostname: eureka-peer1.com
instance-id: eureka-peer1
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer2.com:8898/eureka/,http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer3.com:8899/eureka/
- application-peer2.yml
spring:
application:
name: springcloud-eureka-cluster
freemarker:
prefer-file-system-access: false
security:
user:
name: admin
password: 123456
server:
port: 8898
---
eureka:
instance:
hostname: eureka-peer2.com
instance-id: eureka-peer2
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer1.com:8897/eureka/,http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer3.com:8899/eureka/
- application-peer3.yml
spring:
application:
name: springcloud-eureka-cluster
freemarker:
prefer-file-system-access: false
security:
user:
name: admin
password: 123456
server:
port: 8899
---
eureka:
instance:
hostname: eureka-peer3.com
instance-id: eureka-peer3
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer1.com:8897/eureka/,http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer2.com:8898/eureka/
修改C:\Windows\System32\drivers\etc\hosts
127.0.0.1 eureka-peer1.com eureka-peer2.com eureka-peer3.com
maven install生成jar包,通過 spring.profiles.active 屬性來分別啓動三臺服務器:
cd E:\SpringBoot\SpringCloud\springcloud-root\springcloud-eureka-cluster\target
java -jar springcloud-eureka-cluster-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
java -jar springcloud-eureka-cluster-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
java -jar springcloud-eureka-cluster-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer3
也可通過Run Configurations配置啓動
-
訪問 http://eureka-peer1.com:8897/
-
訪問 http://eureka-peer2.com:8898/
-
訪問http://eureka-peer3.com:8899/
Eureka服務註冊集羣各節點均在unavailable-replicas下錯誤
- 各個節點application名字要保持一致
- 本地測試時各個節點都在同一臺機器,hostname需要在本地host中填寫,各個節點使用自己的host
- prefer-ip-address設置爲true或者默認不填寫。
- register-with-eureka和fetch-registry都爲true
- defaultZone不能使用localhost,需要使用自己在host中配置的域名,配置項爲除自己以外的集羣中所有節點。
No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?錯誤
https://blog.csdn.net/lslk9898/article/details/73836745
六、啓動多個服務提供者實例
啓動多個springcloud-eureka-provider實例,端口分別爲8001,8002和8003
- application-provider1.yml
spring:
application:
name: springcloud-eureka-provider
freemarker:
prefer-file-system-access: false
security:
user:
name: admin
password: 123456
server:
port: 8001
eureka:
instance:
hostname: eureka-provider1.com
instance-id: eureka-provider1
client:
service-url:
defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer1.com:8897/eureka/,http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer2.com:8898/eureka/,http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer3.com:8899/eureka/
- application-provider2.yml
spring:
application:
name: springcloud-eureka-provider
freemarker:
prefer-file-system-access: false
security:
user:
name: admin
password: 123456
server:
port: 8002
eureka:
instance:
hostname: eureka-provider2.com
instance-id: eureka-provider2
client:
service-url:
defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer1.com:8897/eureka/,http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer2.com:8898/eureka/,http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer3.com:8899/eureka/
- application-provider3.yml
spring:
application:
name: springcloud-eureka-provider
freemarker:
prefer-file-system-access: false
security:
user:
name: admin
password: 123456
server:
port: 8003
eureka:
instance:
hostname: eureka-provider3.com
instance-id: eureka-provider3
client:
service-url:
defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer1.com:8897/eureka/,http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer2.com:8898/eureka/,http://${spring.security.user.name}:${spring.security.user.password}@eureka-peer3.com:8899/eureka/
修改C:\Windows\System32\drivers\etc\hosts
127.0.0.1 eureka-provider1.com eureka-provider2.com eureka-provider3.com
通過Run Configurations配置啓動
查看Eureka註冊中心
http://eureka-peer1.com:8897/
http://eureka-peer2.com:8898/,http://eureka-peer3.com:8899/ 結果同上。
三個服務提供者實例已成功註冊。