Eureka
按照官方介紹:
Eureka is a REST (Representational State Transfer) based service that is primarily used in the AWS cloud for locating services for the purpose of load balancing and failover of middle-tier servers.
Eureka 是一個基于 REST 的服務,主要在 AWS 雲中使用, 定位服務來進行中間層伺服器的負載均衡和故障轉移。
Spring Cloud 封裝了 Netflix 公司開發的 Eureka 子產品來實作服務注冊和發現。Eureka 采用了 C-S 的設計架構。Eureka Server 作為服務注冊功能的伺服器,它是服務注冊中心。而系統中的其他微服務,使用 Eureka 的用戶端連接配接到 Eureka Server,并維持心跳連接配接。這樣系統的維護人員就可以通過 Eureka Server 來監控系統中各個微服務是否正常運作。Spring Cloud 的一些其他子產品(比如Zuul)就可以通過 Eureka Server 來發現系統中的其他微服務,并執行相關的邏輯。
Eureka由兩個元件組成:Eureka伺服器和Eureka用戶端。Eureka伺服器用作服務注冊伺服器。Eureka用戶端是一個java用戶端,用來簡化與伺服器的互動、作為輪詢負載均衡器,并提供服務的故障切換支援。Netflix在其生産環境中使用的是另外的用戶端,它提供基于流量、資源使用率以及出錯狀态的權重負載均衡。
用一張圖來認識以下:
上圖簡要描述了Eureka的基本架構,由3個角色組成:
1、Eureka Server
- 提供服務注冊和發現
2、Service Provider
- 服務提供方
- 将自身服務注冊到Eureka,進而使服務消費方能夠找到
3、Service Consumer
- 服務消費方
- 從Eureka擷取注冊服務清單,進而能夠消費服務
案例實踐
Eureka Server
1. 服務注冊中心
在IDEA中建立一個Spring Cloud工程,引入Eureka-Server包,pom檔案整體如下:
<?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>
<groupId>org.example.springcloud</groupId>
<artifactId>service-register</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<!-- eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-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>
</project> 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>
<groupId>org.example.springcloud</groupId>
<artifactId>service-register</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<!-- eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-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>
</project>
在src/main/java包下建立一個名為hello的包,然後建立
EurekaServiceRegisterApplication
類 @SpringBootApplication @EnableEurekaServer觸發Spring Boot的自動配置機制,spring boot會在容器中建立對應的bean。EurekaServiceRegisterApplication的代碼如下:
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaServiceRegisterApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServiceRegisterApplication.class, args);
}
} hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaServiceRegisterApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServiceRegisterApplication.class, args);
}
}
application.properties配置。
#是否需要注冊到注冊中心
eureka.client.register-with-eureka=false
#是否需要從注冊中心擷取服務清單
eureka.client.fetch-registry=false
#注冊伺服器的位址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
logging.level.com.netflix.eureka=OFF
logging.level.com.netflix.discovery=OFF
eureka.client.register-with-eureka=false
#是否需要從注冊中心擷取服務清單
eureka.client.fetch-registry=false
#注冊伺服器的位址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
logging.level.com.netflix.eureka=OFF
logging.level.com.netflix.discovery=OFF
啟動注冊服務,通路:
http://localhost:8761
,就可以看到如下界面。
服務注冊中心背景
2. 服務提供者
建立一個Spring Boot工程,代表服務提供者。
工程的pom檔案内容如下:
<?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>
<groupId>org.example.springcloud</groupId>
<artifactId>service-client</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</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>
</project> 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>
<groupId>org.example.springcloud</groupId>
<artifactId>service-client</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</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>
</project>
添加spring-cloud-starter-eureka這個Jar包,其中包含了eureka的用戶端實作。
在src/main/java/hello下建立工程的主類EurekaServerProducerApplication。 @EnableDiscoveryClient在服務啟動的時,觸發服務注冊的過程,向配置檔案中指定的服務注冊中心(Eureka-Server)的位址注冊自己提供的服務。EurekaServerProducerApplication:
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaServerProducerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerProducerApplication.class, args);
}
} hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaServerProducerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerProducerApplication.class, args);
}
}
配置檔案的内容如下:
#服務提供者的名字
spring.application.name=compute-service
#服務提供者的端口号
server.port=8888
#服務注冊中心的位址
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
spring.application.name=compute-service
#服務提供者的端口号
server.port=8888
#服務注冊中心的位址
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
服務提供者的基本架構搭好後,需要實作服務的具體内容,在ServiceInstanceRestController類中實作,它的具體代碼如下:
package hello;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ServiceInstanceRestController {
private static final Logger logger = LoggerFactory.getLogger(ServiceInstanceRestController.class);
@Autowired
private DiscoveryClient discoveryClient; //服務發現用戶端
@GetMapping(value = "/add")
public Integer add(@RequestParam Integer a, @RequestParam Integer b) {
ServiceInstance instance = discoveryClient.getLocalServiceInstance();
Integer r = a + b;
logger.info("/add, host:" + instance.getHost() + ", service_id:" + instance.getServiceId() + ", result:" + r);
return r;
}
} hello;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ServiceInstanceRestController {
private static final Logger logger = LoggerFactory.getLogger(ServiceInstanceRestController.class);
@Autowired
private DiscoveryClient discoveryClient; //服務發現用戶端
@GetMapping(value = "/add")
public Integer add(@RequestParam Integer a, @RequestParam Integer b) {
ServiceInstance instance = discoveryClient.getLocalServiceInstance();
Integer r = a + b;
logger.info("/add, host:" + instance.getHost() + ", service_id:" + instance.getServiceId() + ", result:" + r);
return r;
}
}
啟動服務注冊中心的工程,然後啟動服務提供者,
localhost:8761
,如下圖所示,服務提供者已經注冊到服務注冊中心啦。
服務提供者注冊到服務注冊中心
在Spring Cloud Netflix中,使用Ribbon實作用戶端負載均衡,使用Feign實作聲明式HTTP用戶端調用——即寫得像本地函數調用一樣。
3. 服務消費者-Ribbon
建立一個Spring boot工程,引入ribbon和eureka,pom檔案内容如下:
<?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>
<groupId>org.example.springcloud</groupId>
<artifactId>serviceconsumer</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<!-- 用戶端負載均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<!-- eureka用戶端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- spring boot實作Java Web服務-->
<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>
</project> 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>
<groupId>org.example.springcloud</groupId>
<artifactId>serviceconsumer</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<!-- 用戶端負載均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<!-- eureka用戶端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- spring boot實作Java Web服務-->
<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>
</project>
建立EurekaConsumerApplication類,定義REST用戶端執行個體,代碼如下:
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient //開啟服務發現的能力
@SpringBootApplication
public class EurekaConsumerApplication {
@Bean //定義REST用戶端,RestTemplate執行個體
@LoadBalanced //開啟負債均衡的能力
RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerApplication.class, args);
}
} hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient //開啟服務發現的能力
@SpringBootApplication
public class EurekaConsumerApplication {
@Bean //定義REST用戶端,RestTemplate執行個體
@LoadBalanced //開啟負債均衡的能力
RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerApplication.class, args);
}
}
application.properties中定義了服務注冊中心的位址、消費者服務的端口号、消費者服務的名稱這些内容:
#應用名稱
spring.application.name=ribbon-consumer
#端口号
server.port=9000
#注冊中心的位址
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
spring.application.name=ribbon-consumer
#端口号
server.port=9000
#注冊中心的位址
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
消費者服務的入口為:ConsumerController,我們通過這個執行個體進行測試。消費者服務啟動過程中,會從服務注冊中心中拉最新的服務清單,當浏覽器觸發對應的請求,就會根據COMPUTE-SERVICE查找服務提供者的IP和端口号,然後發起調用。
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping(value = "/add")
public String add() {
return restTemplate.getForEntity("http://COMPUTE-SERVICE/add?a=10&b=20", String.class).getBody();
}
} hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping(value = "/add")
public String add() {
return restTemplate.getForEntity("http://COMPUTE-SERVICE/add?a=10&b=20", String.class).getBody();
}
}
首先啟動服務注冊中心,第二分别啟動兩個服務提供者(IP相同、端口不同即可),然後啟動服務消費者。
兩個服務提供者
在浏覽器裡通路
localhost:9000/add
兩次,可以看到請求有時候會在8888端口的服務,有時候會到8889的服務。具體背後選擇的原理,還有待後續研究。
4. 服務消費者-Feign
上一節中,使用類似
restTemplate.getForEntity("http://COMPUTE-SERVICE/add?a=10&b=20", String.class).getBody()
這樣的語句進行服務間調用并非不可以,隻是我們在服務化的過程中,希望跨服務調用能夠看起來像本地調用,這也是我了解的Feign的使用場景。
建立一個spring boot工程,該工程的pom檔案與上一節的類似,隻是把ribbon的依賴換為feign的即可,代碼如下:
<?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>
<groupId>org.example.springcloud</groupId>
<artifactId>serviceconsumer</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Feign實作聲明式HTTP用戶端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!-- eureka用戶端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- spring boot實作Java Web服務-->
<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>
</project> 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>
<groupId>org.example.springcloud</groupId>
<artifactId>serviceconsumer</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Feign實作聲明式HTTP用戶端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!-- eureka用戶端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- spring boot實作Java Web服務-->
<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>
</project>
首先建立應用程式啟動類:EurekaConsumerApplication,代碼如下:
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
@EnableDiscoveryClient //用于啟動服務發現功能
@EnableFeignClients //用于啟動Fegin功能
@SpringBootApplication
public class EurekaConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerApplication.class);
}
} hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
@EnableDiscoveryClient //用于啟動服務發現功能
@EnableFeignClients //用于啟動Fegin功能
@SpringBootApplication
public class EurekaConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerApplication.class);
}
}
然後定義遠端調用的接口,在hello包下建立depend包,然後建立ComputeClient接口,使用@FeignClient("COMPUTE-SERVICE")注解修飾,COMPUTE-SERVICE就是服務提供者的名稱,然後定義要使用的服務,代碼如下:
package hello.depend;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient("COMPUTE-SERVICE")
public interface ComputeClient {
@RequestMapping(method = RequestMethod.GET, value = "/add")
Integer add(@RequestParam(value = "a") Integer a, @RequestParam(value = "b") Integer b);
} hello.depend;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient("COMPUTE-SERVICE")
public interface ComputeClient {
@RequestMapping(method = RequestMethod.GET, value = "/add")
Integer add(@RequestParam(value = "a") Integer a, @RequestParam(value = "b") Integer b);
}
在ConsumerController中,像引入普通的spring bean一樣引入ComputeClient對象,其他的和Ribbon的類似。
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import hello.depend.ComputeClient;
@RestController
public class ConsumerController {
@Autowired
private ComputeClient computeClient;
@RequestMapping(value = "/add", method = RequestMethod.GET)
public Integer add() {
return computeClient.add(10, 20);
}
} hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import hello.depend.ComputeClient;
@RestController
public class ConsumerController {
@Autowired
private ComputeClient computeClient;
@RequestMapping(value = "/add", method = RequestMethod.GET)
public Integer add() {
return computeClient.add(10, 20);
}
}
application.properties的内容如下:
#應用名稱
spring.application.name=fegin-consumer
#端口号
server.port=9000
#注冊中心的位址
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
spring.application.name=fegin-consumer
#端口号
server.port=9000
#注冊中心的位址
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
啟動fegin消費者,通路
localhost:9000/add
,也可以看到服務提供者已經收到了消費者發來的請求。
請求到達服務提供者1
請求到達服務提供者2