1.Eureka簡介
Eureka是Netflix開發的服務發現框架,本身是一個基於REST的服務,主要用於定位運行在AWS域中的中間層服務,以達到負載均衡和中間層服務故障轉移的目的。SpringCloud將它集成在其子項目spring-cloud-netflix中,以實現SpringCloud的服務發現功能。 Eureka包含兩個組件:Eureka Server和Eureka Client。
1.1 Eureka Server
Eureka Server提供服務註冊服務,各個節點啓動後,會在Eureka Server中進行註冊,這樣Eureka Server中的服務註冊表中將會存儲所有可用服務節點的信息,服務節點的信息可以在界面中直觀的看到。 Eureka Server本身也是一個服務,默認情況下會自動註冊到Eureka註冊中心。 如果搭建單機版的Eureka Server註冊中心,則需要配置取消Eureka Server的自動註冊邏輯。畢竟當前服務註冊到當前服務代表的註冊中心中是一個說不通的邏輯。 Eureka Server通過Register、Get、Renew等接口提供服務的註冊、發現和心跳檢測等服務。
1.2 Eureka Client
Eureka Client是一個java客戶端,用於簡化與Eureka Server的交互,客戶端同時也具備一個內置的、使用輪詢(round-robin)負載算法的負載均衡器。在應用啓動後,將會向Eureka Server發送心跳,默認週期爲30秒,如果Eureka Server在多個心跳週期內沒有接收到某個節點的心跳,Eureka Server將會從服務註冊表中把這個服務節點移除(默認90秒)。 Eureka Client分爲兩個角色,分別是:Application Service(Service Provider)和Application Client(Service Consumer)
- Application Service服務提供方,是註冊到Eureka Server中的服務;
- Application Client服務消費方,通過Eureka Server發現服務,並消費。
2.Eureka Server架構
- Register(服務註冊):把自己的IP和端口註冊給Eureka;
- Renew(服務續約):發送心跳包,每30秒發送一次。告訴Eureka自己還活着;
- Cancel(服務下線):當provider關閉時會向Eureka發送消息,把自己從服務列表中刪除。防止consumer調用到不存在的服務;
- Get Registry(獲取服務註冊列表):獲取其他服務列表;
- Replicate(集羣中數據同步):eureka集羣中的數據複製與同步;
- Make Remote Call(遠程調用):完成服務的遠程調用。
3.Eureka服務的註冊與發現功能搭建
3.1 創建父工程
使用IDEA新建一個maven項目spring-cloud-demo,刪除src目錄,在pom.xml中添加以下依賴
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>org.example</groupId>
<artifactId>spring-cloud-demo</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>spring-cloud-eureka-server</module>
<module>spring-cloud-eureka-client</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<!-- jdk版本 -->
<java.version>1.8</java.version>
<!-- SpringCloud版本號,官方最新穩定版本 -->
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>
<!-- 公共依賴 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
<!--依賴管理,用於管理spring-cloud的依賴 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<resources>
<!-- 先指定 src/main/resources下所有文件及文件夾爲資源文件 -->
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${maven.compiler.encoding}</encoding>
</configuration>
</plugin>
<plugin>
<!--打包跳過測試-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<!-- resources資源插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven-resources-plugin.version}</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>${docker-maven-plugin.version}</version>
</plugin>
<!-- java文檔插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
複製代碼
3.2 基於Eureka Server搭建服務註冊發現中心
新建maven項目spring-cloud-eureka-server,添加如下依賴pom.xml中
<?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">
<parent>
<artifactId>spring-cloud-demo</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-eureka-server</artifactId>
<dependencies>
<!-- eureka服務端依賴jar包 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- eureka安全組件jar包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
複製代碼
增加Security相關配置,關閉crsf
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
}
複製代碼
創建一個啓動類EurekaServerApplication,添加@EnableEurekaServer註解
@Slf4j
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
log.info("=======啓動服務註冊中心 eureka-server 服務項目中=======");
SpringApplication.run(EurekaServerApplication.class, args);
log.info("=======啓動服務註冊中心 eureka-server 服務項目成功=======");
}
}
複製代碼
新建application.yml屬性文件,增加下面的配置
server:
#項目端口號
port: 8888
tomcat:
max-connections: 200
max-threads: 300
min-spare-threads: 0
uri-encoding: UTF-8
logging:
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{15} - %msg%n'
spring:
application:
name: eureka-server
eureka:
#eureka實例定義
instance:
#eureka實例主機名稱
hostname: master
#表示eureka client發送心跳給server端的頻率。如果在leaseExpirationDurationInSeconds後,server端沒有收到client的心跳,
#則將摘除該instance。
#除此之外,如果該instance實現了HealthCheckCallback,並決定讓自己unavailable的話,則該instance也不會接收到流量。
lease-renewal-interval-in-seconds: 5
#客戶端進行Eureka註冊的配置
client:
#關閉eureka的客戶端行爲:註冊服務
registerWithEureka: false
#關閉eureka的客戶端行爲:訂閱服務
fetchRegistry: false
serviceUrl:
#eureka註冊中心地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
# 關閉自我保護機制,防止失效的服務也被一直訪問 (Spring Cloud默認該配置是 true)
enable-self-preservation: false
# 每隔10s掃描服務列表,該配置可以修改檢查失效服務的時間,每隔10s檢查失效服務,並移除列表 (Spring Cloud默認該配置是 60s)
eviction-interval-timer-in-ms: 5000
複製代碼
運行啓動類啓動我們的註冊中心服務,瀏覽器輸入http://localhost:8888/訪問
3.3 編寫服務提供者
新建maven項目spring-cloud-eureka-client-provider,添加如下依賴pom.xml中
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-demo</artifactId>
<groupId>com.hxmec</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-eureka-client-provider</artifactId>
<name>spring-cloud-eureka-client-provider</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
複製代碼
新建application.yml,增加下面的配置
server:
port: 9001
spring:
application:
name: eureka-client-provider
logging:
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{15} - %msg%n'
eureka:
client:
service-url:
defaultZone: http://localhost:8888/eureka/
複製代碼
創建一個啓動類EurekaClientProviderApplication,添加@EnableDiscoveryClient註解
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaClientProviderApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientProviderApplication.class, args);
}
}
複製代碼
創建一個DemoController,提供一個接口給消費者服務查詢
@RestController
@RequestMapping("/demo")
public class DemoController {
@Value("${server.port:#{null}}")
private String serverPort;
@GetMapping("/hello")
public String hello() {
return "Hello " + serverPort;
}
}
複製代碼
啓動項目,打開http://localhost:8888/ 可以看到應用已經註冊到Eureka註冊中心
3.4 編寫服務消費者
創建maven項目spring-cloud-eureka-client-consumer,pom依賴和服務提供者一樣,創建啓動類EurekaClientConsumerApplication
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaClientConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientConsumerApplication.class, args);
}
}
複製代碼
新建application.yml 屬性文件,增加下面的配置
server:
port: 9002
spring:
application:
name: eureka-client-consumer
logging:
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{15} - %msg%n'
eureka:
client:
service-url:
defaultZone: http://localhost:8888/eureka/
複製代碼
使用RestTemplate來訪問http服務,創建RestTemplate配置類RestTemplateConfiguration
@Configuration
public class RestTemplateConfiguration {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
複製代碼
創建DemoController
@RestController
@RequestMapping("/test")
@AllArgsConstructor
@Slf4j
public class DemoController {
private final RestTemplate restTemplate;
@GetMapping("/callHello")
public String callHello() {
//LoadBalanced註解可以實現通過註冊的服務名稱來調用
//String result = restTemplate.getForObject("http://localhost:9001/demo/hello", String.class);
String result = restTemplate.getForObject("http://eureka-client-provider/demo/hello", String.class);
log.info("調用結果:{}" , result);
return result;
}
}
複製代碼
啓動項目,打開http://localhost:8888/ 可以看到應用已經註冊到Eureka註冊中心
請求測試接口,驗證是否成功調用生產者的接口
4.項目git地址
https://github.com/ty1972873004/spring-cloud-demo