spring cloud

This commit is contained in:
luoxiang 2019-08-26 07:51:14 +08:00
parent ead9678338
commit da5b55e19f
6 changed files with 255 additions and 339 deletions

View File

@ -1,39 +1,19 @@
# eureka 高可用注册中心的搭建 # Eureka 高可用注册中心的搭建
## 目录<br/>
<a href="#一项目结构">一、项目结构</a><br/>
<a href="#二三步搭建eureka-高可用注册中心">二、三步搭建eureka 高可用注册中心</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#21-引入eureka服务端依赖">2.1 引入eureka服务端依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#22--创建三份配置文件分别代表不同注册中心的配置">2.2 创建三份配置文件,分别代表不同注册中心的配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#23-启动类上增加注解EnableEurekaServer激活eureka服务端自动配置">2.3 启动类上增加注解@EnableEurekaServer激活eureka服务端自动配置</a><br/>
<a href="#三三步搭建eureka-客户端">三、三步搭建eureka 客户端</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#31-引入eureka客户端依赖">3.1 引入eureka客户端依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#32-eureka-客户端配置指定注册中心地址">3.2 eureka 客户端配置,指定注册中心地址</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#33-启动类上增加注解EnableDiscoveryClient激活eureka客户端自动配置">3.3 启动类上增加注解@EnableDiscoveryClient激活eureka客户端自动配置</a><br/>
<a href="#4启动项目">4.启动项目 </a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#41-这里我们可以采用命令行方式指定配置分别启动三个注册中心">4.1 这里我们可以采用命令行方式指定配置,分别启动三个注册中心</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#42--高可用集群搭建成功的判定">4.2 高可用集群搭建成功的判定</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#43--prefer-ip-address-参数说明">4.3 prefer-ip-address 参数说明</a><br/>
## 正文<br/>
## 一、项目结构 ## 一、项目结构
eureka-server 为服务注册中心,负责服务的管理; - **eureka-server** 为服务注册中心,负责服务的管理;
- **eureka-client** 为 Eureka 客户端。
eureka-client 为 eureka 客户端;
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-eureka-cluster.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-eureka-cluster.png"/> </div>
## 二、三步搭建 Eureka 高可用注册中心
## 二、三步搭建eureka 高可用注册中心
这里我们以单机伪集群的方式搭建,让三个单机注册中心互相注册,实现注册中心的高可用。配置示意图如下: 这里我们以单机伪集群的方式搭建,让三个单机注册中心互相注册,实现注册中心的高可用。配置示意图如下:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka-server-client.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka-server-client.png"/> </div>
### 2.1 服务端依赖
#### 2.1 引入eureka服务端依赖
```xml ```xml
<dependency> <dependency>
@ -42,10 +22,11 @@ eureka-client 为 eureka 客户端;
</dependency> </dependency>
``` ```
#### 2.2 创建三份配置文件,分别代表不同注册中心的配置 ### 2.2 服务端配置
创建三份配置文件,分别代表不同注册中心的配置:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka-application.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka-application.png"/> </div>
application-01.yml: application-01.yml:
```yaml ```yaml
@ -105,7 +86,9 @@ eureka:
需要注意的是 Eureka 互相注册要求各个 Eureka 实例的 eureka.instance.hostname 不同,如果相同,则会被 Eureka 标记为 unavailable-replicas不可用副本 需要注意的是 Eureka 互相注册要求各个 Eureka 实例的 eureka.instance.hostname 不同,如果相同,则会被 Eureka 标记为 unavailable-replicas不可用副本
#### 2.3 启动类上增加注解@EnableEurekaServer激活eureka服务端自动配置 ### 2.3 @EnableEurekaServer
在启动类上增加 @EnableEurekaServer 注解来激活 Eureka 服务端自动配置:
```java ```java
@SpringBootApplication @SpringBootApplication
@ -121,9 +104,9 @@ public class EurekaServerApplication {
## 三、三步搭建eureka 客户端 ## 三、三步搭建 Eureka 客户端
#### 3.1 引入eureka客户端依赖 ### 3.1 客户端依赖
```xml ```xml
<dependency> <dependency>
@ -132,7 +115,7 @@ public class EurekaServerApplication {
</dependency> </dependency>
``` ```
#### 3.2 eureka 客户端配置,指定注册中心地址 ### 3.2 客户端配置
```yaml ```yaml
server: server:
@ -148,7 +131,9 @@ eureka:
defaultZone: http://127.0.0.1:8010/eureka/,http://localhost:8020/eureka/,http://192.168.200.228:8030/eureka/ defaultZone: http://127.0.0.1:8010/eureka/,http://localhost:8020/eureka/,http://192.168.200.228:8030/eureka/
``` ```
#### 3.3 启动类上增加注解@EnableDiscoveryClient激活eureka客户端自动配置 ### 3.3 @EnableDiscoveryClient
在启动类上增加 @EnableDiscoveryClient 注解来激活 Eureka 客户端自动配置:
```java ```java
@SpringBootApplication @SpringBootApplication
@ -164,49 +149,49 @@ public class EurekaClientApplication {
## 4.启动项目 ## 4.启动项目
### 4.1 这里我们可以采用命令行方式指定配置,分别启动三个注册中心 ### 4.1 启动注册中心
这里我们可以采用命令行方式指定配置,分别启动三个注册中心:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka-active.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka-active.png"/> </div>
### 4.2 集群搭建成功的判定
### 4.2 高可用集群搭建成功的判定 这里需要注意的是仅仅 Status 中出现其他注册中心时,并不一定是搭建成功的,**一定是当注册中心的 DS Replicas 和 available replicas 中显示其余的注册中心时候,才代表搭建成功**。
这里需要主要的是仅仅 status 中出现其他注册中心时,并不一定是搭建成功的,**一定是当注册中心的 DS Replicas 和 available replicas 中显示其余的注册中心时候**,才代表搭建成功。 8010 注册中心:
#### 4.2.1 点击下面注册中心的可用实例列表中的地址,访问链接分以下几个情况: <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka-8010.png"/> </div>
8020 注册中心:
1. hostname 和 prefer-ip-address 都没有配置,则访问 主机名:服务名:端口号, <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka-8020.png"/> </div>
8030 注册中心:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka-8030.png"/> </div>
Status 下的每个注册中心都可以点击跳转到其监控页面,但其监控页面地址链接可能是动态变化的,主要情况如下:
+ 当 hostname 和 prefer-ip-address 都没有配置,则访问 `主机名:服务名:端口号`
``` ```
http://desktop-8jgsflj:8761/info http://desktop-8jgsflj:8761/info
``` ```
2. 配置了 hostname 而没有配置 prefer-ip-address则访问 hostname:服务名:端口号, + 当配置了 hostname 而没有配置 prefer-ip-address则访问 `hostname:服务名:端口号`
``` ```
http://server:8761/info http://server:8761/info
``` ```
3. 如果配置了 prefer-ip-address则访问 ipAddress:服务名:端口号, + 如果配置了 prefer-ip-address则访问 `ipAddress:服务名:端口号`
``` ```
http://192.168.200.228:8761/info http://192.168.200.228:8761/info
``` ```
8010 注册中心:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka-8010.png"/> </div> ### 4.3 prefer-ip-address 参数
8020 注册中心: 在有的配置示例中,配置了 prefer-ip-address 为 true
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka-8020.png"/> </div>
8030 注册中心:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka-8030.png"/> </div>
### 4.3 prefer-ip-address 参数说明
在有的配置示例中,配置了 prefer-ip-address 为 true。
```properties ```properties
eureka.instance.prefer-ip-address=true eureka.instance.prefer-ip-address=true
``` ```
在多机器独立部署的情况下是没有问题的,配置 prefer-ip-address 为 ture代表发现服务时候优先按照 ip 去搜寻,对于多集群而言,可以保证尽快准确搜索到服务。而对于单机部署来说,ip 地址都是相同的,这会导致其余注册中心出现在 unavailable-replicas(不可用副本) 中。所以单机部署时候不建议开启这个参数(默认值为 false多机部署时候可以开启。 在多机器独立部署的情况下是没有问题的,配置 prefer-ip-address 为 ture代表发现服务时候优先按照 IP 去搜寻对于多集群而言可以保证尽快准确搜索到服务。而对于单机部署来说IP 地址都是相同的,这会导致其余注册中心出现在 unavailable-replicas (不可用副本) 中。所以单机部署时候不建议开启这个参数(默认值为 false多机部署时候可以开启。

View File

@ -1,44 +1,26 @@
# eureka 服务的注册与发现 # Eureka 服务的注册与发现
## 目录<br/>
<a href="#一eureka-简介">一、eureka 简介</a><br/>
<a href="#二项目结构">二、项目结构</a><br/>
<a href="#三三步搭建eureka-服务注册中心">三、三步搭建eureka 服务注册中心</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#31-引入eureka服务端依赖">3.1 引入eureka服务端依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#32-eureka-服务端配置">3.2 eureka 服务端配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#33-启动类上增加注解EnableEurekaServer激活eureka服务端自动配置">3.3 启动类上增加注解@EnableEurekaServer激活eureka服务端自动配置</a><br/>
<a href="#四三步搭建eureka-客户端">四、三步搭建eureka 客户端</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#41-引入eureka客户端依赖">4.1 引入eureka客户端依赖</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#42-eureka-客户端配置">4.2 eureka 客户端配置</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#43-启动类上增加注解EnableDiscoveryClient激活eureka客户端自动配置">4.3 启动类上增加注解@EnableDiscoveryClient激活eureka客户端自动配置</a><br/>
<a href="#五启动项目">五、启动项目 </a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#51-进入注册中心控制台查看服务注册情况">5.1 进入注册中心控制台,查看服务注册情况</a><br/>
## 正文<br/>
## 一、eureka 简介 ## 一、Eureka 简介
Spring Cloud Eureka 使用 Netflix Eureka 来实现服务注册与发现,它既包含了服务端组件,也包含了客户端组件 Spring Cloud Eureka 使用 Netflix Eureka 来实现服务注册与发现,它既包含了服务端组件,也包含了客户端组件:
**Eureka 服务端**:服务的注册中心,负责维护注册的服务列表。 - **Eureka 服务端**:服务的注册中心,负责维护注册的服务列表。
- **Eureka 客户端** 在应用程序运行时Eureka 客户端向注册中心注册自身提供的服务,并周期性地发送心跳来更新它的服务租约。同时它也能把从服务端查询到服务信息缓存到本地,并周期性地刷新服务状态。
**Eureka 客户端** 在应用程序运行时Eureka 客户端向注册中心注册自身提供的服务,并周期性地发送心跳来更新它的服务租约。同时它也能把从服务端查询到服务信息缓存到本地,并周期性地刷新服务状态。
## 二、项目结构 ## 二、项目结构
eureka-server 为服务注册中心,负责服务的管理; - **eureka-server** 为服务注册中心,负责服务的管理;
- **eureka-client** 为 Eureka 客户端。
eureka-client 为 eureka 客户端;
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-eureka.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-eureka.png"/> </div>
## 三、三步搭建 Eureka 服务注册中心
### 3.1 服务端依赖
## 三、三步搭建eureka 服务注册中心
#### 3.1 引入eureka服务端依赖
```xml ```xml
<dependency> <dependency>
@ -47,7 +29,7 @@ eureka-client 为 eureka 客户端;
</dependency> </dependency>
``` ```
#### 3.2 eureka 服务端配置 ### 3.2 服务端配置
```yaml ```yaml
server: server:
@ -64,7 +46,9 @@ eureka:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
``` ```
#### 3.3 启动类上增加注解@EnableEurekaServer激活eureka服务端自动配置 ### 3.3 @EnableEurekaServer
在启动类上增加 @EnableEurekaServer 注解来激活 Eureka 服务端自动配置:
```java ```java
@SpringBootApplication @SpringBootApplication
@ -80,9 +64,9 @@ public class EurekaServerApplication {
## 四、三步搭建eureka 客户端 ## 四、三步搭建 Eureka 客户端
#### 4.1 引入eureka客户端依赖 ### 4.1 客户端依赖
```xml ```xml
<dependency> <dependency>
@ -91,7 +75,7 @@ public class EurekaServerApplication {
</dependency> </dependency>
``` ```
#### 4.2 eureka 客户端配置 ### 4.2 客户端配置
```yaml ```yaml
server: server:
@ -107,7 +91,9 @@ eureka:
defaultZone: http://localhost:8010/eureka/ defaultZone: http://localhost:8010/eureka/
``` ```
#### 4.3 启动类上增加注解@EnableDiscoveryClient激活eureka客户端自动配置 ### 4.3 @EnableDiscoveryClient
在启动类上增加 @EnableDiscoveryClient 注解来激活 Eureka 客户端自动配置:
```java ```java
@SpringBootApplication @SpringBootApplication
@ -123,6 +109,6 @@ public class EurekaClientApplication {
## 五、启动项目 ## 五、启动项目
#### 5.1 进入注册中心控制台,查看服务注册情况 进入注册中心控制台,查看服务注册情况
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/eureka.png"/> </div>

View File

@ -1,39 +1,30 @@
# spring-cloud-feign # Spring-Cloud-Feign
## 目录<br/>
<a href="#一feign-简介">一、feign 简介</a><br/>
<a href="#二项目结构">二、项目结构</a><br/>
<a href="#三服务提供者的实现">三、服务提供者的实现</a><br/>
<a href="#四服务消费者的实现">四、服务消费者的实现</a><br/>
<a href="#五启动测试">五、启动测试</a><br/>
<a href="#六-feign-的服务容错">六、 feign 的服务容错</a><br/>
## 正文<br/>
## 一、feign 简介 ## 一、Feign 简介
在上一个用例中,我们使用 ribbon+restTemplate 实现服务之间的远程调用,实际上每一个调用都是模板化的内容,所以 spring cloud Feign 在此基础上进行了进一步的封装。我们只需要定义一个接口并使用 feign 注解的方式来进行配置,同时采用 springMvc 注解进行参数绑定就可以完成服务的调用。feign 同时还内置实现了负载均衡、服务容错等功能。 在上一个用例中,我们使用 Ribbon + RestTemplate 实现服务之间的远程调用,实际上每一个调用都是模板化的内容,所以 Spring Cloud Feign 在此基础上进行了进一步的封装。我们只需要定义一个接口并使用 Feign 注解的方式来进行配置,同时采用 springMvc 注解进行参数绑定就可以完成服务的调用。Feign 同时还内置实现了负载均衡、服务容错等功能。
## 二、项目结构 ## 二、项目结构
+ common: 公共的接口和实体类; + **common**公共的接口和实体类;
+ consumer: 服务的消费者,采用 feign 调用产品服务; + **consumer**:服务的消费者,采用 Feign 调用产品服务;
+ producer服务的提供者 + **producer**:服务的提供者;
+ eureka: 注册中心。 + **eureka**注册中心。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-feign.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-feign.png"/> </div>
## 三、服务提供者的实现 ## 三、服务提供者的实现
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/feign-producer.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/feign-producer.png"/> </div>
### 3.1 定义服务
#### 3.1 产品服务由`ProductService`提供,并通过`ProducerController`将服务暴露给外部调用。 产品服务由 `ProductService` 提供,并通过 `ProducerController` 将服务暴露给外部调用:
ProductService.java ProductService.java
@ -97,7 +88,9 @@ public class ProducerController implements ProductFeign {
} }
``` ```
#### 3.2 指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient ### 3.2 服务注册
指定注册中心地址,并在启动类上开启自动注册 @EnableDiscoveryClient
```java ```java
server: server:
@ -131,8 +124,7 @@ public class ProducerApplication {
## 四、服务消费者的实现 ## 四、服务消费者的实现
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/feign-consumer.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/feign-consumer.png"/> </div>
### 4.1 基本依赖
#### 4.1 导入openfeign依赖
```xml ```xml
<!-- feign 依赖--> <!-- feign 依赖-->
@ -142,9 +134,9 @@ public class ProducerApplication {
</dependency> </dependency>
``` ```
#### 4.2 指定注册中心地址,并在启动类上添加注解@EnableDiscoveryClient和@EnableFeignClients ### 4.2 @EnableFeignClients
@EnableFeignClients 会去扫描工程中所有用 @FeignClient 声明的 feign 客户端。 指定注册中心地址,并在启动类上添加注解 @EnableDiscoveryClient@EnableFeignClients@EnableFeignClients 会去扫描工程中所有用 @FeignClient 声明的 Feign 客户端:
```java ```java
server: server:
@ -173,7 +165,7 @@ public class ConsumerApplication {
} }
``` ```
#### 4.3 创建服务调用公共接口 ### 4.3 创建服务调用接口
```java ```java
/** /**
@ -203,9 +195,9 @@ public interface ProductFeign {
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/common-feign.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/common-feign.png"/> </div>
### 4.4 Feign 客户端
继承公共接口,创建 CProductFeign@FeignClient 声明为 Feign 客户端:
#### 4.4 继承公共接口创建CProductFeign@FeignClient声明为feign客户端
```java ```java
/** /**
@ -218,7 +210,9 @@ public interface CProductFeign extends ProductFeign {
} }
``` ```
#### 4.5 注入使用 feign 服务调用接口 ### 4.5 调用远程服务
注入并使用 Feign 接口调用远程服务:
```java ```java
@Controller @Controller
@ -257,37 +251,34 @@ public class SellController {
## 五、启动测试 ## 五、启动测试
#### 5.1 启动一个Eureka服务、三个producer服务注意区分端口、和一个消费者服务 ### 5.1 启动服务
feign 的依赖中导入了 spring-cloud-starter-netflix-ribbon 依赖,并且在内部实现了基于 ribbon 的客户端负载均衡,所以我们这里启动三个 producer 实例来观察负载均衡的情况。 启动一个Eureka服务、三个生产者服务注意区分端口、和一个消费者服务。Feign 的依赖中导入了 spring-cloud-starter-netflix-ribbon 依赖,并且在内部实现了基于 Ribbon 的客户端负载均衡,所以我们这里启动三个生产者服务来观察负载均衡的情况:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-app.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-app.png"/> </div>
**服务注册中心:** **服务注册中心:**
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-eureka.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-eureka.png"/> </div>
### 5.2 验证负载均衡
#### 5.2 访问http://localhost:8080/sell/products 查看负载均衡的调用结果 访问 http://localhost:8080/sell/products 查看负载均衡的调用结果
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-products-8020.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-products-8020.png"/> </div>
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-products-8030.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-products-8030.png"/> </div>
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/feign-8040.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/feign-8040.png"/> </div>
## 六、Feign 的服务容错
## 六、 feign 的服务容错 ### 6.1 开启容错配置
#### 6.1 feign 的依赖中默认导入了hystrix 的相关依赖,我们不需要额外导入,只需要开启相关配置即可 Feign 的依赖中默认导入了 Hystrix (熔断器)的相关依赖,我们不需要额外导入,只需要开启相关配置即可
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/feign-hystrix-maven.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/feign-hystrix-maven.png"/> </div>
在 application.yml 中开启 Hystrix
#### 6.2 在application.yml 中开启hystrix
```yml ```yml
feign: feign:
@ -296,12 +287,14 @@ feign:
enabled: true enabled: true
``` ```
#### 6.3 创建`CProductFeignImpl`,继承feign接口CProductFeign定义熔断时候的回退处理 ### 6.2 定义降级处理
创建 `CProductFeignImpl`,继承 Feign接口CProductFeign定义熔断时候的降级处理机制
```java ```java
/** /**
* @author : heibaiying * @author : heibaiying
* @description : 定义发生熔断时候的回退处理。除了继承自 CProductFeign,还需要用@Component 声明为 spring 的组件 * @description : 定义发生熔断时候的降级处理。除了继承自 CProductFeign,还需要用 @Component 声明为 spring 的组件
*/ */
@Component @Component
public class CProductFeignImpl implements CProductFeign { public class CProductFeignImpl implements CProductFeign {
@ -353,7 +346,9 @@ public class CProductFeignImpl implements CProductFeign {
</html> </html>
``` ```
#### 6.4 在 @FeignClient 注解中用fallback参数指定熔断时候的回退处理 ### 6.3 配置降级处理
@FeignClient 注解中,用 fallback 参数指定熔断时候的降级处理:
```java ```java
/** /**
@ -366,9 +361,9 @@ public interface CProductFeign extends ProductFeign {
} }
``` ```
#### 6.5 测试熔断处理 ### 6.4 测试熔断
hystrix 默认调用超时时间为 2s ,这里我们使用线程休眠的方式来模拟超时熔断。 Hystrix 默认调用超时时间为 2s 这里我们使用线程休眠的方式来模拟超时熔断。
```java ```java
public List<Product> queryAllProducts() { public List<Product> queryAllProducts() {

View File

@ -1,55 +1,42 @@
# spring-cloud-hystrix-turbine # Spring-Cloud-Hystrix-Turbine
## 目录<br/>
<a href="#一hystrix-简介">一、hystrix 简介</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-熔断器">1.1 熔断器</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-hystrix-工作机制">1.2 hystrix 工作机制</a><br/>
<a href="#二项目结构">二、项目结构</a><br/>
<a href="#三整合-hystrix-以consumer模块为例">三、整合 hystrix 以consumer模块为例</a><br/>
<a href="#四使用turbine-实现聚合监控">四、使用turbine 实现聚合监控</a><br/>
<a href="#五整合过程中可能出现的问题">五、整合过程中可能出现的问题</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#51-无法访问监控页面">5.1 无法访问监控页面</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#52-页面一直loading-或者访问端点页面一直出现ping">5.2 页面一直loading 或者访问端点页面一直出现ping</a><br/>
## 正文<br/>
## 一、hystrix 简介 ## 一、简介
#### 1.1 熔断器 ### 1.1 Spring Cloud Hystrix
在分布式系统中,由于服务之间相互的依赖调用,如果一个服务单元发生了故障就有可能导致故障蔓延至整个系统,从而衍生出一系列的保护机制,断路器就是其中之一。 在分布式系统中,由于服务之间相互的依赖调用,如果一个服务单元发生了故障就有可能导致故障蔓延至整个系统,从而衍生出一系列的保护机制,断路器就是其中之一。
断路器可以在服务单元发生故障的时候,及时切断与服务单元的连接,避免资源被长时间占用。spring cloud hystrix 组件实现了断路器、线程隔离等一系列基本功能,并具有服务降级、服务熔断、请求缓存、请求合并以及服务监控等配套功能。 断路器可以在服务单元发生故障的时候及时切断与服务单元的连接避免资源被长时间占用。Spring Cloud Hystrix 组件实现了断路器、线程隔离等一系列基本功能,并具有服务降级、服务熔断、请求缓存、请求合并以及服务监控等配套功能。
#### 1.2 hystrix 工作机制 ### 1.2 熔断器工作机制
- 当一个服务处理请求失败次数低于阈值时,熔断器处于关闭状态,服务正常; - 当一个服务处理请求失败次数低于阈值时,熔断器处于关闭状态,服务正常;
- 当一个服务的处理请求的失败次数大于阈值时候,熔断器开启,这时候所有的请求都会执行快速失败,是不会去调用实际的服务的 - 当一个服务处理请求失败的次数大于阈值时,熔断器开启,这时所有的请求都会执行快速失败,而不会去调用实际的服务
- 当熔断器处于打开状态的一段时间后,熔断器处于半打开状态,这时候一定数量的请求回去调用实际的服务,如果调用成功,则代表服务可用了,熔断器关闭;如果还是失败,则代表服务还是不可用,熔断器继续关闭 - 当熔断器处于打开状态的一段时间后,熔断器处于半打开状态,这时候一定数量的请求回去调用实际的服务,如果调用成功,则代表服务可用了,熔断器关闭;如果还是失败,则代表服务还是不可用,熔断器继续打开
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/circuitbreaker.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/circuitbreaker.png"/> </div>
## 二、项目结构 ## 二、项目结构
[spring-cloud-ribbon](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-ribbon) 用例已经实现通过 ribbon+restTemplate 实现服务间的调用,本用例在其基础上进行 hystrix 的整合。 [spring-cloud-ribbon](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-ribbon) 用例已经实现通过 Ribbon + RestTemplate 实现服务间的调用,本用例在其基础上进行 Hystrix 的整合:
+ common: 公共的接口和实体类; + **common**公共的接口和实体类;
+ consumer: 服务的消费者,采用 RestTemplate 调用产品服务; + **consumer**服务的消费者,采用 RestTemplate 调用产品服务;
+ producer服务的提供者 + **producer**:服务的提供者;
+ eureka: 注册中心; + **eureka** 注册中心;
+ turbine:多个熔断器的聚合监控。 + **turbine**多个熔断器的聚合监控。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-hystrix.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-hystrix.png"/> </div>
## 三、整合 Hystrix
这里以 consumer 模块为例,说明其整合步骤:
## 三、整合 hystrix 以consumer模块为例 ### 3.1 引入依赖
#### 3.1 引入依赖 Hystrix 的仪表盘功能实际上是从 [端点](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-actuator) 获取数据,所以需要引入 actuator starter 开启端点的相关功能:
hystrix 的仪表盘功能实际上是从[端点](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-actuator) 获取数据,所以需要 actuator starter 开启端点的相关功能。
```xml ```xml
<!--hystrix 依赖--> <!--hystrix 依赖-->
@ -69,7 +56,7 @@ hystrix 的仪表盘功能实际上是从[端点](https://github.com/heibaiying/
</dependency> </dependency>
``` ```
#### 3.2 暴露端点 ### 3.2 暴露端点
```java ```java
management: management:
@ -80,7 +67,9 @@ management:
include: "*" include: "*"
``` ```
#### 3.3 在启动类上添加注解@EnableHystrix和@EnableHystrixDashboard ### 3.3 添加注解
在启动类上添加注解 @EnableHystrix@EnableHystrixDashboard
```java ```java
@SpringBootApplication @SpringBootApplication
@ -95,7 +84,9 @@ public class ConsumerApplication {
} }
``` ```
#### 3.4 使用 @HystrixCommand 定义失败回退的方法 ### 3.4 服务降级
使用 @HystrixCommand 定义失败回退的方法:
```java ```java
@HystrixCommand(fallbackMethod = "queryProductsFail") @HystrixCommand(fallbackMethod = "queryProductsFail")
@ -138,9 +129,9 @@ public List<Product> queryProductsFail() {
</html> </html>
``` ```
#### 3.5 模拟熔断 ### 3.5 模拟熔断
这里被调用方采用线程休眠的方式模拟服务超时Hystrix 默认超时时间为 2s,调用远程服务时候超过这个时间,会触发熔断。 这里被调用方采用线程休眠的方式模拟服务超时Hystrix 默认超时时间为 2s,调用远程服务时候超过这个时间,会触发熔断:
```java ```java
public List<Product> queryAllProducts() { public List<Product> queryAllProducts() {
@ -155,41 +146,38 @@ public List<Product> queryAllProducts() {
} }
``` ```
3.5 启动服务,访问 http://localhost:8030/sell/products ,多次刷新查看熔断情况 ### 3.5 测试熔断
启动服务,访问 http://localhost:8030/sell/products ,多次刷新查看熔断情况:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/hystrix-8030.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/hystrix-8030.png"/> </div>
### 3.7 控制台
#### 3.5 启动服务,访问 localhost:8030/hystrix 启动服务可以访问 localhost:8030/hystrix ,依次输出 http://localhost:8030/actuator/hystrix.stream监控地址 2000延迟时间title 可以任意填写进入Hystrix 监控台。
依次输出 http://localhost:8030/actuator/hystrix.stream监控地址 2000延迟时间title 可以任意填写,进入监控台。 在 Spring Cloud Finchley.SR2 中,监控地址需要以 `/actuator` 开头的,因为在 Spring Boot 2.x 中所有端点(包括自定义端点)都是暴露在这个路径下,可以通过控制台的启动日志来验证这一点。
需要注意的是在 spring cloud Finchley.SR2监控地址中都是有/actuator 的,因为在 spring boot 2.x 的所有端点(包括自定义端点)都是暴露在这个路径下,在启动时候的控制台输出的日志可以查看到所有暴露端点的映射。
**登录页面** **登录页面**
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/hystrix-single-login.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/hystrix-single-login.png"/> </div>
**监控页面** **监控页面**
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/hystrix-8030-login.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/hystrix-8030-login.png"/> </div>
**关于各个参数的说明参见[官方 wiki](https://github.com/Netflix-Skunkworks/hystrix-dashboard/wiki) 提供的图** **关于各个参数的说明参见[官方 wiki](https://github.com/Netflix-Skunkworks/hystrix-dashboard/wiki) 提供的图**
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/dashboard.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/dashboard.png"/> </div>
## 四、聚合监控
如果你想要聚合监控不同服务单元下的多个断路器,可以使用 Turbine 来实现。单体监控和聚合监控的区别如下:
## 四、使用turbine 实现聚合监控
单体监控和聚合监控:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/dashboard-direct-vs-turbine-640.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/dashboard-direct-vs-turbine-640.png"/> </div>
### 4.1 导入依赖
创建 Turbine 模块,导入以下依赖:
#### 4.1 创建turbine模块导入依赖
```xml ```xml
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
@ -244,7 +232,9 @@ public List<Product> queryAllProducts() {
#### 4.2 指定注册中心地址和聚合的项目,这里我们监控 consumer,producer 两个项目 ### 4.2 项目配置
指定注册中心地址和聚合的项目,这里我们监控 consumerproducer 两个项目:
```java ```java
server: server:
@ -269,7 +259,9 @@ turbine:
#### 4.3 在启动类上添加注解 ### 4.3 添加注解
在启动类上添加注解:
```java ```java
@SpringBootApplication @SpringBootApplication
@ -288,51 +280,49 @@ public class TurbineApplication {
#### 4.4 依次启动eureka、producer、consumer、turbine四个项目 ### 4.4 启动项目
在 localhost:8030/hystrix 或者 localhost:8030/hystrixconsumer 和 producer 都集成了 hystrix 页面输入 http://localhost:8040/turbine.stream查看断路器聚合信息 依次启动 eureka、producer、consumer、turbine 四个项目,因为 consumer 和 producer 都集成了 Hystrix ,所以可以在 localhost:8020/hystrix 或者 8030/hystrix 页面输入 http://localhost:8040/turbine.stream 来查看断路器聚合信息:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/hystrix-cluster-login.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/hystrix-cluster-login.png"/> </div>
**显示了不同服务单元consumer,producer的多个断路器信息** **显示了不同服务单元consumer,producer的多个断路器信息**
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/hystrix-cluster.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/hystrix-cluster.png"/> </div>
## 五、常见问题
## 五、整合过程中可能出现的问题 在整合过程中可能出现的一些问题如下:
#### 5.1 无法访问监控页面 ### 5.1 无法访问监控页面
1. 一般是端点链接输入不对,在 F 版本的 spring cloud 中,输入监控的端点链接是 http://localhost:8030/actuator/hystrix.stream ,中间是有/actuator/(之前版本的没有/actuator/ 一般是端点链接输入不对,在 F 版本的 Spring Cloud 中,输入监控的端点链接是 http://localhost:8030/actuator/hystrix.stream ,中间是有 `/actuator/`(之前版本的没有)。其次是可能没有暴露端点,暴露端点有两种方式,一种是我们在上文中提到的基于配置的方式:
2. 没有暴露端点链接,暴露端点链接有两种方式,一种是我们在上文中提到的基于配置的方式 ```yaml
management:
endpoints:
web:
exposure:
# 需要开启 hystrix.stream 端点的暴露 这样才能获取到监控信息 * 代表开启所有可监控端点
include: "*"
```
```yaml 另一种基于代码的方式,示例如下:
management:
endpoints:
web:
exposure:
# 需要开启 hystrix.stream 端点的暴露 这样才能获取到监控信息 * 代表开启所有可监控端点
include: "*"
```
第二种方式是基于代码的方式,如下: ```java
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/actuator/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
```
```java 这两种方式二选一即可,就算是采用代码的方式,还是建议将地址设置为 /actuator/hystrix.stream而不是原来的 hystrix.stream因为 Turbine 默认也是从 /actuator/hystrix.stream 去获取信息。
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/actuator/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
```
这两种方式二选一即可,就算是采用代码的方式,还是建议将地址设置为/actuator/hystrix.stream而不是原来的 hystrix.stream因为 turbine 默认也是从/actuator/hystrix.stream 去获取信息。 ### 5.2 页面一直 Loading 或者访问端点页面一直出现 Ping
#### 5.2 页面一直loading 或者访问端点页面一直出现ping 这种情况是熔断器所在的方法没有被调用,所以没有产生监控数据,不是整合问题,这时候调用一下熔断器所在方法即可:
这种情况是熔断器所在的方法没有被调用,所以没有产生监控数据,不是整合问题,这时候调用一下熔断器所在方法即可。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/hystrix-loading.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/hystrix-loading.png"/> </div>

View File

@ -1,44 +1,27 @@
# spring-cloud-ribbon # Spring-Cloud-Ribbon
## 目录<br/>
<a href="#一ribbon-简介">一、ribbon 简介</a><br/>
<a href="#二项目结构">二、项目结构</a><br/>
<a href="#三服务提供者的实现">三、服务提供者的实现</a><br/>
<a href="#四服务消费者的实现">四、服务消费者的实现</a><br/>
<a href="#五启动测试">五、启动测试</a><br/>
<a href="#六-附1-关于RestTemplate的说明">六、 附1 关于RestTemplate的说明</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#61--restTemplate-规范">6.1 restTemplate 规范</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#62-ForEntity和ForObject的区别">6.2 ForEntity()和ForObject()的区别</a><br/>
<a href="#七-附2-关于ribbon更多负载均衡的策略">七、 附2 关于ribbon更多负载均衡的策略</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#71-内置的负载均衡的策略如下图">7.1 内置的负载均衡的策略如下图</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#72-配置文件指定负载均衡的方式">7.2 配置文件指定负载均衡的方式</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#73-代码指定负载均衡的方式">7.3 代码指定负载均衡的方式</a><br/>
## 正文<br/>
## 一、ribbon 简介 ## 一、Ribbon 简介
ribbon 是 Netfix 公司开源的负载均衡组件,采用服务端负载均衡的方式,即消费者客户端维护可用的服务列表,并通过负载均衡的方式将请求按照指定的策略分摊给消费者,从而达到负载均衡的方式。 Ribbon 是 Netfix 公司开源的负载均衡组件,采用服务端负载均衡的方式,即消费者客户端维护可用的服务列表,并通过负载均衡的方式将请求按照指定的策略分摊给消费者,从而达到负载均衡的方式。
## 二、项目结构 ## 二、项目结构
+ common: 公共的接口和实体类; + **common**:公共的接口和实体类;
+ consumer: 服务的消费者,采用 RestTemplate 调用产品服务; + **consumer**:服务的消费者,采用 RestTemplate 调用产品服务;
+ producer服务的提供者 + **producer**:服务的提供者;
+ eureka: 注册中心ribbon 从注册中心获取可用的服务列表,是实现负载均衡的基础。这里使用我们在[服务的注册与发现](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-eureka) 这个用例中搭建的简单注册中心作为测试即可。 + **eureka**注册中心Ribbon 从注册中心获取可用的服务列表,是实现负载均衡的基础。这里使用我们在 [服务的注册与发现](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-eureka) 这个用例中搭建的注册中心即可。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon.png"/> </div>
## 三、服务提供者的实现 ## 三、服务提供者的实现
#### 3.1 产品服务由`ProductService`提供,并通过`ProducerController`将服务暴露给外部调用。 ### 3.1 定义服务
产品服务由 `ProductService` 提供,并通过 `ProducerController` 将服务暴露给外部调用:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/ribbon-producer.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/ribbon-producer.png"/> </div>
ProductService.java ProductService.java
```java ```java
@ -106,7 +89,9 @@ public class ProducerController {
} }
``` ```
#### 3.2 指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient ### 3.2 注册服务
指定注册中心地址,并在启动类上开启自动注册 @EnableDiscoveryClient
```java ```java
server: server:
@ -140,8 +125,7 @@ public class ProducerApplication {
## 四、服务消费者的实现 ## 四、服务消费者的实现
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/ribbon-consumer.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/ribbon-consumer.png"/> </div>
### 4.1 基本依赖
#### 4.1 导入负载均衡需要的依赖
```xml ```xml
<!--ribbon 依赖--> <!--ribbon 依赖-->
@ -151,7 +135,9 @@ public class ProducerApplication {
</dependency> </dependency>
``` ```
#### 4.2 指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient ### 4.2 注册服务
指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient
```java ```java
server: server:
@ -179,7 +165,9 @@ public class ConsumerApplication {
} }
``` ```
#### 4.3 使用@LoadBalanced配置RestTemplate即可实现客户端负载均衡 ### 4.3 @LoadBalanced
使用 @LoadBalanced 配置 RestTemplate 即可实现客户端负载均衡:
```java ```java
import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.client.loadbalancer.LoadBalanced;
@ -198,9 +186,9 @@ public class RibbonConfig {
} }
``` ```
#### 4.4 使用RestTemplate调用远程服务 ### 4.4 调用远程服务
这里我们在调用远程服务的时候url 填写的是服务名 + 具体接口地址 ,由于我们的同一个服务会存在多个实例,在使用@LoadBalanced 配置 RestTemplate 调用服务时,客户端就会从按照指定的负载均衡的方式将请求分摊到多个实例上。(默认的负载均衡采用的是 RoundRobinRule轮询的策略有特殊需求时候可以采用其他内置的策略规则或者实现 IRule 来定义自己的负载均衡策略)。 使用 RestTemplate 调用远程服务,这里我们在调用远程服务的时候url 填写的是 服务名 + 具体接口地址 ,由于我们的同一个服务会存在多个实例,在使用@LoadBalanced 配置 RestTemplate 调用服务时,客户端就会从按照指定的负载均衡的方式将请求分摊到多个实例上。(默认的负载均衡采用的是 RoundRobinRule轮询的策略有特殊需求时候可以采用其他内置的策略规则或者实现 IRule 来定义自己的负载均衡策略)。
```java ```java
@Service @Service
@ -232,38 +220,36 @@ public class ProductService implements IProductService {
## 五、启动测试 ## 五、启动测试
#### 5.1 启动一个Eureka服务、三个producer服务注意区分端口、和一个消费者服务 ### 5.1 启动服务
启动一个Eureka服务、三个生产者服务注意区分端口、和一个消费者服务
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-app.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-app.png"/> </div>
**服务注册中心:** **服务注册中心:**
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-eureka.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-eureka.png"/> </div>
### 5.2 验证负载均衡
#### 5.2 访问http://localhost:8080/sell/products 查看负载均衡的调用结果 访问 http://localhost:8080/sell/products 查看负载均衡的调用结果
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-products-8020.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-products-8020.png"/> </div>
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-products-8030.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-ribbon-products-8030.png"/> </div>
## 六、RestTemplate
## 六、 附1 关于RestTemplate的说明 ### 6.1 RestTemplate 规范
#### 6.1 restTemplate 规范 在使用 RestTemplate 调用对应 RESTful 接口时候,使用的方法应该与接口声明方式(@GetMapping@PostMapping@PutMapping@DeleteMapping)保持一致。其对应关系如下:
restTemplate 调用对应 resultful 接口时候,使用的方法应该与接口声明方式(@GetMapping@PostMapping@PutMapping@DeleteMapping)保持一致。请求类型与对应的调用方法如下。 - GET 请求 ( getForObject 、getForEntity )
- POST 请求( postForObject 、postForEntity
- PUT 请求( put
- DELETE 请求 delete
- GET 请求 (getForObject 、getForEntity) ### 6.2 ForEntity 和 ForObject 的区别
- POST 请求postForObject 、postForEntity
- PUT 请求put
- DELETE 请求 delete
#### 6.2 ForEntity()和ForObject()的区别 - `ForEntity()` 发送一个请求,返回的 ResponseEntity 包含了响应体所映射成的对象,
- `ForEntity()` 发送一个请求,返回的 ResponseEntity 包含了响应体所映射成的对象 - `ForObject()` 发送一个请求,返回的请求体将映射为一个对象。示例如下:
- `ForObject()` 发送一个请求,返回的请求体将映射为一个对象
例如:
```java ```java
ResponseEntity<Product> responseEntity = restTemplate.getForEntity("http://producer/product/{1}", Product.class, id); ResponseEntity<Product> responseEntity = restTemplate.getForEntity("http://producer/product/{1}", Product.class, id);
@ -272,11 +258,11 @@ Product product = restTemplate.getForObject("http://producer/product/{1}", Produ
## 七、 附2 关于ribbon更多负载均衡策略 ## 七、负载均衡策略
Ribbon 内置了多种负载均衡策略,如果有更复杂的需求,可以自己实现 IRule。 Ribbon 内置了多种负载均衡策略,如果有更复杂的需求,可以自己实现 IRule。
#### 7.1 内置的负载均衡的策略如下图 ### 7.1 内置的负载均衡的策略
![Ribbon 负载均衡策略.png](http://upload-images.jianshu.io/upload_images/6944619-0355d316f5df9b3f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![Ribbon 负载均衡策略.png](http://upload-images.jianshu.io/upload_images/6944619-0355d316f5df9b3f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
@ -284,9 +270,13 @@ Ribbon 内置了多种负载均衡策略,如果有更复杂的需求,可以
#### 7.2 配置文件指定负载均衡的方式 ### 7.2 指定负载均衡的策略
要设置 `IRule` 名为的服务名称 `users`,您可以设置以下属性: 可以通过两种方式来为服务指定具体的负载均衡的策略,分别是基于配置的方式和基于代码的方式:
**1. 基于配置的方式**
如下将为名为 `user` 的服务设置其负载均衡的策略为 WeightedResponseTimeRule
```yaml ```yaml
users: users:
@ -294,9 +284,7 @@ users:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
``` ```
**2. 基于代码的方式**
#### 7.3 代码指定负载均衡的方式
```java ```java
@Configuration @Configuration
@ -316,10 +304,11 @@ public class CustomConfiguration {
} }
``` ```
在使用代码方式的时候需要注意 [官方文档](http://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-ribbon.html#_customizing_the_ribbon_client) 中关于注解方式有以下强调: 在使用代码方式时, [官方文档](http://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-ribbon.html#_customizing_the_ribbon_client) 中有以下强调说明:
```
The CustomConfiguration clas must be a @Configuration class, but take care that it is not in a @ComponentScan for the main application context. Otherwise, it is shared by all the @RibbonClients. If you use @ComponentScan (or @SpringBootApplication), you need to take steps to avoid it being included (for instance, you can put it in a separate, non-overlapping package or specify the packages to scan explicitly in the @ComponentScan). The CustomConfiguration clas must be a @Configuration class, but take care that it is not in a @ComponentScan for the main application context. Otherwise, it is shared by all the @RibbonClients. If you use @ComponentScan (or @SpringBootApplication), you need to take steps to avoid it being included (for instance, you can put it in a separate, non-overlapping package or specify the packages to scan explicitly in the @ComponentScan).
```
`CustomConfiguration` 类必须是 `@Configuration` 标注的,但需要注意的它不是在 `@ComponentScan` 主应用程序上下文。否则,它将由所有 `@RibbonClients` 共享。如果你使用 `@ComponentScan`(或 `@SpringBootApplication`),你需要采取一些措施来避免它被扫描到(例如,你可以把它放在一个独立的,非重叠的包,或用 `@ComponentScan` 时显示扫描指定的包)。 CustomConfiguration 类必须使用 @Configuration 进行注解,但需要注意的它不能在 @ComponentScan 主应用程序的上下文。否则,它将被所有 @RibbonClients 共享。如果你使用 @ComponentScan(或 @SpringBootApplication),你需要采取一些措施来避免它被扫描到(例如,你可以把它放在一个独立的,非重叠的包,或用 @ComponentScan 时显示扫描指定的包,从而避开扫描到 CustomConfiguration 所在的包)。

View File

@ -1,59 +1,41 @@
# spring-cloud-zuul # Spring-Cloud-Zuul
## 目录<br/>
<a href="#一zuul简介">一、zuul简介</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#11-API-网关">1.1 API 网关</a><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#12-zuul">1.2 zuul</a><br/>
<a href="#二项目结构">二、项目结构</a><br/>
<a href="#三构建api-网关-zuul">三、构建api 网关 zuul</a><br/>
<a href="#四错误熔断">四、错误熔断</a><br/>
<a href="#五zuul--过滤器">五、zuul 过滤器</a><br/>
<a href="#六负载均衡">六、负载均衡</a><br/>
<a href="#七附关于版本问题可能导致的-zuul-启动失败">七、附:关于版本问题可能导致的 zuul 启动失败</a><br/>
## 正文<br/>
## 一、zuul简介 ## 一、简介
### 1.1 API 网关 ### 1.1 API 网关
api 网关是整个微服务系统的门面,所有的外部访问需要通过网关进行调度和过滤。它实现了请求转发、负载均衡、校验过滤、错误熔断、服务聚合等功能。 API 网关是整个微服务系统的门面,所有的外部访问需要通过网关进行调度和过滤。它实现了请求转发、负载均衡、校验过滤、错误熔断、服务聚合等功能:
下图是直观的显示 api Gateway 在微服务网关中的作用(图片引用自 spring boot 官网)。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/apiGateway.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/apiGateway.png"/> </div>
### 1.2 Spring Cloud Zuul
### 1.2 zuul Spring Cloud 基于 Net Flix Zuul 实现了网关组件,这就是 Spring Cloud Zuul。它除了实现负载均衡、错误熔断、路由转发等功能还能与 Spring 的其他组件无缝配合使用。
spring cloud 中提供了基础 Net flix Zuul 实现的网关组件,这就是 Zuul,它除了实现负载均衡、错误熔断、路由转发等功能,还能与 spring 其他组件无缝配合使用。
## 二、项目结构 ## 二、项目结构
[spring-cloud-feign](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-feign) 用例已经实现通过 feign 实现服务间的调用,且提供了两个业务服务单元 (consumer、producer),可以方便直观的测试 zuul 的路由、负载均衡、和错误熔断等功能,所以本用例在其基础上进行 zuul 的整合。 [spring-cloud-feign](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-feign) 用例已经通过 Feign 实现服务间的调用,且提供了两个服务单元 (consumer、producer),可以方便直观地测试 Zuul 的路由、负载均衡、和错误熔断等功能,所以本用例在其基础上进行整合。
+ common: 公共的接口和实体类; + **common**公共的接口和实体类;
+ consumer: 服务的消费者,采用 feign 调用产品服务; + **consumer**:服务的消费者,采用 Feign 调用产品服务;
+ producer服务的提供者 + **producer**:服务的提供者;
+ eureka: 注册中心; + **eureka**注册中心;
+ zuul: api 网关。 + **zuul**API 网关。
聚合项目目录如下: 聚合项目目录如下:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-zuul.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/spring-cloud-zuul.png"/> </div>
Zuul 项目目录如下:
zuul 项目目录如下:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul.png"/> </div>
## 三、Zuul 网关
### 3.1 引入依赖
## 三、构建api 网关 zuul 主要的依赖是 spring-cloud-starter-netflix-zuul
#### 3.1 引入依赖
主要的依赖是 spring-cloud-starter-netflix-zuul
```xml ```xml
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
@ -127,11 +109,9 @@ zuul 项目目录如下:
</project> </project>
``` ```
### 3.2 添加注解
在启动类上添加 @EnableZuulProxy和 @EnableDiscoveryClient 注解,@EnableZuulProxy 会自动设置 Zuul 服务器端点并在其中开启一些反向代理过滤器,以便将请求转发到后端服务器:
#### 3.2 在启动类上添加注解@EnableZuulProxy和@EnableDiscoveryClient
@EnableZuulProxy 会自动设置 Zuul 服务器端点并在其中开启一些反向代理过滤器,以便将请求转发到后端服务器。
```java ```java
@SpringBootApplication @SpringBootApplication
@ -146,11 +126,9 @@ public class ZuulApplication {
} }
``` ```
### 3.3 项目配置
在配置文件中指定注册中心的地址并配置网关的路由规则。Zuul 需要指定注册中心的地址Zuul 会从 Eureka 获取其他微服务的实例信息,然后按照指定的路由规则进行请求转发:
#### 3.3 指定注册中心、配置网关的路由规则
zuul 需要指定注册中心的地址zuul 会从 eureka 获取其他微服务的实例信息,然后按照指定的路由规则进行请求转发。
```yaml ```yaml
server: server:
@ -175,21 +153,22 @@ zuul:
serviceId: consumer serviceId: consumer
``` ```
### 3.4 启动服务
启动 eureka、producer、consumer、zuul 四个服务,访问 localhost:8090/consumer/sell/product
#### 3.4 启动eureka、producer、consumer、zuul服务访问 localhost:8090/consumer/sell/product
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-consumer.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-consumer.png"/> </div>
## 四、错误熔断 ## 四、错误熔断
#### 4.1 zuul 默认整合了 hystrix ,不用导入其他额外依赖 ### 4.1 默认依赖
Zuul 默认整合了 Hystrix ,不用导入其他额外依赖:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-hystrix.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-hystrix.png"/> </div>
### 4.2 服务降级
#### 4.2 创建 CustomZuulFallbackProvider并实现FallbackProvider 接口,同时用@Component声明为spring 组件,即可实现熔断时候的回退服务 创建 CustomZuulFallbackProvider 并实现 FallbackProvider 接口,同时用 @Component 声明为 Spring 组件,即可实现熔断时候的回退服务:
```java ```java
/** /**
@ -262,15 +241,13 @@ public class CustomZuulFallbackProvider implements FallbackProvider {
} }
``` ```
正确返回了内容、同时返回的 http 状态码也和我们设置的一样。 正确返回了内容、同时返回的 Http 状态码也和我们设置的一样。
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-broker.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-broker.png"/> </div>
## 五、Zuul 过滤器
创建自定义过滤器继承自 CustomZuulFilter当我们访问网关的时候如果判断 Session 中没有对应的 code则跳转到我们自定义的登录页面
## 五、zuul 过滤器
创建自定义过滤器继承自 CustomZuulFilter当我们访问网关的时候如果判断 session 中没有对应的 code,则跳转到我们自定义的登录页面。
```java ```java
/** /**
@ -331,7 +308,7 @@ public class CustomZuulFilter extends ZuulFilter {
} }
``` ```
index.ftl: **index.ftl**
```html ```html
<!doctype html> <!doctype html>
@ -352,27 +329,21 @@ index.ftl:
## 六、负载均衡 ## 六、负载均衡
#### zuul 默认集成了ribbon 实现了负载均衡。只要启动多个实例即可查看到负载均衡的效果。 Zuul 默认集成了 Ribbon 并实现了负载均衡,只要启动多个实例即可查看到负载均衡的效果:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-ribbon.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-ribbon.png"/> </div>
**这里我们直接在idea 中启动多个实例来测试:**
#### 这里我们直接在idea 中启动多个实例来测试:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-config.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-config.png"/> </div>
**负载均衡测试结果:**
#### 负载均衡测试结果:
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-consumer.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-consumer.png"/> </div>
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-consumer-8040.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-consumer-8040.png"/> </div>
<div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-consumer-8030.png"/> </div> <div align="center"> <img src="https://github.com/heibaiying/spring-samples-for-all/blob/master/pictures/zuul-consumer-8030.png"/> </div>
## 七、常见异常
如果出现以下错误导致启动失败,是 Spring Boot 版本不兼容导致的错误Finchley SR2 版本的 Zuul 组件和 Spring Boot 2.1.x 存在不兼容的情况。如果出现这个问题,则将 Spring Boot 版本降至 2.0.x 即可,本用例中采用的是 2.0.8 。
## 七、附:关于版本问题可能导致的 zuul 启动失败
如果出现以下错误导致启动失败,是 spring boot 版本不兼容导致的错误Finchley SR2 版本 spring cloud 中的 zuul 和 spring boot 2.1.x 版本存在不兼容。如果出现这个问题,则将 spring boot 将至 2.0.x 的版本即可,用例中采用的是 2.0.8 版本。在实际的开发中应该严格遵循 spring 官方的版本依赖说明。
```java ```java
APPLICATION FAILED TO START APPLICATION FAILED TO START
@ -389,7 +360,7 @@ Consider renaming one of the beans or enabling overriding by setting spring.main
``` ```
**spring cloud 版本说明** 在实际的开发中应该严格遵循 Spring 官方的版本依赖说明
| Release Train | Boot Version | | Release Train | Boot Version |
| ------------- | ------------ | | ------------- | ------------ |
@ -398,4 +369,4 @@ Consider renaming one of the beans or enabling overriding by setting spring.main
| Edgware | 1.5.x | | Edgware | 1.5.x |
| Dalston | 1.5.x | | Dalston | 1.5.x |
更多组件的版本说明可以在[spring cloud overview](https://spring.io/projects/spring-cloud#overview) 页面查看。 更多组件的版本说明可以在 [spring cloud overview](https://spring.io/projects/spring-cloud#overview) 页面查看。