From 1bf52fa739c38d1fdc63ba2b1144f0c9e0194740 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=BD=97=E7=A5=A5?= <1366971433@qq.com>
Date: Fri, 1 Feb 2019 10:28:48 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0README.md=E6=96=87=E7=AB=A0?=
=?UTF-8?q?=E5=AF=BC=E8=88=AA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
spring-boot/spring-boot-actuator/README.md | 4 +-
spring-boot/spring-boot-base/README.md | 2 +
spring-boot/spring-boot-data-jpa/README.md | 2 +
.../spring-boot-druid-mybatis/README.md | 2 +
spring-boot/spring-boot-dubbo/README.md | 6 +-
spring-boot/spring-boot-jsp/README.md | 2 +
spring-boot/spring-boot-kafka/README.md | 4 +-
spring-boot/spring-boot-memcached/README.md | 2 +
spring-boot/spring-boot-mongodb/README.md | 2 +
spring-boot/spring-boot-mybatis/README.md | 2 +
spring-boot/spring-boot-rabbitmq/README.md | 4 +-
spring-boot/spring-boot-redis/README.md | 2 +
spring-boot/spring-boot-servlet/README.md | 4 +-
spring-boot/spring-boot-swagger2/README.md | 2 -
spring-boot/spring-boot-tomcat/README.md | 2 +
spring-boot/spring-boot-websocket/README.md | 6 +-
spring-cloud/spring-cloud-config/README.md | 884 +++++++++---------
.../spring-cloud-eureka-cluster/README.md | 6 +-
spring-cloud/spring-cloud-eureka/README.md | 5 +-
spring-cloud/spring-cloud-feign/README.md | 770 ++++++++-------
spring-cloud/spring-cloud-hystrix/README.md | 662 +++++++------
spring-cloud/spring-cloud-ribbon/README.md | 630 +++++++------
.../spring-cloud-sleuth-zipkin/README.md | 1 +
spring-cloud/spring-cloud-zuul/README.md | 787 ++++++++--------
24 files changed, 1889 insertions(+), 1904 deletions(-)
delete mode 100644 spring-boot/spring-boot-swagger2/README.md
diff --git a/spring-boot/spring-boot-actuator/README.md b/spring-boot/spring-boot-actuator/README.md
index 68e7c65..7c4acdd 100644
--- a/spring-boot/spring-boot-actuator/README.md
+++ b/spring-boot/spring-boot-actuator/README.md
@@ -12,12 +12,14 @@
1.4 查看监控状态
三、自定义健康检查指标
四、自定义健康状态聚合规则
-五、@Endpoint自定义端点
+五、@Endpoint自定义端点
5.1 自定义端点
5.2 访问自定义端点http://127.0.0.1:8080/actuator/customEndPoint
## 正文
+
+
## 一、用例涉及到的概念综述
### 1.1 端点
diff --git a/spring-boot/spring-boot-base/README.md b/spring-boot/spring-boot-base/README.md
index 1af3a1f..81c9320 100644
--- a/spring-boot/spring-boot-base/README.md
+++ b/spring-boot/spring-boot-base/README.md
@@ -12,6 +12,8 @@
## 正文
+
+
## 一、说明
#### 1.1 项目结构说明
diff --git a/spring-boot/spring-boot-data-jpa/README.md b/spring-boot/spring-boot-data-jpa/README.md
index 1134aed..5e8b721 100644
--- a/spring-boot/spring-boot-data-jpa/README.md
+++ b/spring-boot/spring-boot-data-jpa/README.md
@@ -10,6 +10,8 @@
## 正文
+
+
## 一、说明
#### 1.1 项目结构
diff --git a/spring-boot/spring-boot-druid-mybatis/README.md b/spring-boot/spring-boot-druid-mybatis/README.md
index 279e5f9..da8e802 100644
--- a/spring-boot/spring-boot-druid-mybatis/README.md
+++ b/spring-boot/spring-boot-druid-mybatis/README.md
@@ -11,6 +11,8 @@
## 正文
+
+
## 一、说明
#### 1.1 项目结构
diff --git a/spring-boot/spring-boot-dubbo/README.md b/spring-boot/spring-boot-dubbo/README.md
index a717a7a..678a282 100644
--- a/spring-boot/spring-boot-dubbo/README.md
+++ b/spring-boot/spring-boot-dubbo/README.md
@@ -5,15 +5,17 @@
三、公共模块(boot-dubbo-common)
四、 服务提供者(boot-dubbo-provider)
4.1 提供方配置
- 4.2 使用注解@Service暴露服务
+ 4.2 使用注解@Service暴露服务
五、服务消费者(boot-dubbo-consumer)
1.消费方的配置
- 2.使用注解@Reference引用远程服务
+ 2.使用注解@Reference引用远程服务
六、项目构建的说明
七、关于dubbo新版本管理控制台的安装说明
## 正文
+
+
## 一、 项目结构说明
1.1 按照dubbo 文档推荐的服务最佳实践,建议将服务接口、服务模型、服务异常等均放在 API 包中,所以项目采用maven多模块的构建方式,在spring-boot-dubbo下构建三个子模块:
diff --git a/spring-boot/spring-boot-jsp/README.md b/spring-boot/spring-boot-jsp/README.md
index e0243ca..ded6b37 100644
--- a/spring-boot/spring-boot-jsp/README.md
+++ b/spring-boot/spring-boot-jsp/README.md
@@ -10,6 +10,8 @@
## 正文
+
+
## 一、说明
#### 1.1 项目结构
diff --git a/spring-boot/spring-boot-kafka/README.md b/spring-boot/spring-boot-kafka/README.md
index 7ba18fa..57d26cc 100644
--- a/spring-boot/spring-boot-kafka/README.md
+++ b/spring-boot/spring-boot-kafka/README.md
@@ -12,7 +12,7 @@
二、 整合 kafka
2.1 kafka基本配置
2.2 KafkaTemplate实现消息发送
- 2.3 @KafkaListener注解实现消息的监听
+ 2.3 @KafkaListener注解实现消息的监听
2.4 测试整合结果
三、关于多消费者组的测试
3.1 创建多分区主题
@@ -23,6 +23,8 @@
## 正文
+
+
## 一、kafka的相关概念:
### 1.主题和分区
diff --git a/spring-boot/spring-boot-memcached/README.md b/spring-boot/spring-boot-memcached/README.md
index 3adae48..99579df 100644
--- a/spring-boot/spring-boot-memcached/README.md
+++ b/spring-boot/spring-boot-memcached/README.md
@@ -13,6 +13,8 @@
## 正文
+
+
## 一、说明
### 1.1 XMemcached客户端说明
diff --git a/spring-boot/spring-boot-mongodb/README.md b/spring-boot/spring-boot-mongodb/README.md
index ea83391..7344b5b 100644
--- a/spring-boot/spring-boot-mongodb/README.md
+++ b/spring-boot/spring-boot-mongodb/README.md
@@ -10,6 +10,8 @@
## 正文
+
+
## 一、说明
#### 1.1 用例结构
diff --git a/spring-boot/spring-boot-mybatis/README.md b/spring-boot/spring-boot-mybatis/README.md
index fb6f682..5fba829 100644
--- a/spring-boot/spring-boot-mybatis/README.md
+++ b/spring-boot/spring-boot-mybatis/README.md
@@ -10,6 +10,8 @@
## 正文
+
+
## 一、说明
#### 1.1 项目结构
diff --git a/spring-boot/spring-boot-rabbitmq/README.md b/spring-boot/spring-boot-rabbitmq/README.md
index e5b8d0c..9a26bfd 100644
--- a/spring-boot/spring-boot-rabbitmq/README.md
+++ b/spring-boot/spring-boot-rabbitmq/README.md
@@ -5,7 +5,7 @@
三、公共模块(rabbitmq-common)
四、服务消费者(rabbitmq-consumer)
4.1 消息消费者配置
- 4.2 使用注解@RabbitListener和@RabbitHandler创建消息监听者
+ 4.2 使用注解@RabbitListener和@RabbitHandler创建消息监听者
五、 消息生产者(rabbitmq-producer)
5.1 消息生产者配置
5.2 创建消息生产者
@@ -14,6 +14,8 @@
## 正文
+
+
## 一、 项目结构说明
1.1 之前关于spring 整合 rabbitmq 我们采用的是单项目的方式,为了使得用例更具有实际意义,这里采用maven多模块的构建方式,在spring-boot-rabbitmq下构建三个子模块:
diff --git a/spring-boot/spring-boot-redis/README.md b/spring-boot/spring-boot-redis/README.md
index 43f6893..bb8ccc8 100644
--- a/spring-boot/spring-boot-redis/README.md
+++ b/spring-boot/spring-boot-redis/README.md
@@ -32,6 +32,8 @@
## 正文
+
+
## 一、说明
#### 1.1 项目结构
diff --git a/spring-boot/spring-boot-servlet/README.md b/spring-boot/spring-boot-servlet/README.md
index d258338..7f66a6f 100644
--- a/spring-boot/spring-boot-servlet/README.md
+++ b/spring-boot/spring-boot-servlet/README.md
@@ -7,11 +7,13 @@
2.1 新建过滤器、监听器和servlet
2.2 注册过滤器、监听器和servlet
三、采用注解方式整合 servlet
- 3.1 新建过滤器、监听器和servlet,分别使用@WebFilter、@WebListener、@WebServlet注解标注
+ 3.1 新建过滤器、监听器和servlet,分别使用@WebFilter、@WebListener、@WebServlet注解标注
3.2 使注解生效
## 正文
+
+
## 一、说明
#### 1.1 项目结构说明
diff --git a/spring-boot/spring-boot-swagger2/README.md b/spring-boot/spring-boot-swagger2/README.md
deleted file mode 100644
index 0740998..0000000
--- a/spring-boot/spring-boot-swagger2/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-@Profile({"dev","test"})
-@ConditionalOnProperty(name = "swagger.enable", havingValue = "true")
\ No newline at end of file
diff --git a/spring-boot/spring-boot-tomcat/README.md b/spring-boot/spring-boot-tomcat/README.md
index 3dd568d..15c82da 100644
--- a/spring-boot/spring-boot-tomcat/README.md
+++ b/spring-boot/spring-boot-tomcat/README.md
@@ -9,6 +9,8 @@
2.3 新建controller和show.jsp 测试整合是否成功
## 正文
+
+
## 一、说明
#### 1.1 项目结构说明
diff --git a/spring-boot/spring-boot-websocket/README.md b/spring-boot/spring-boot-websocket/README.md
index c2bbaf2..d3c30b2 100644
--- a/spring-boot/spring-boot-websocket/README.md
+++ b/spring-boot/spring-boot-websocket/README.md
@@ -4,12 +4,14 @@
1.1 项目结构说明
1.2 主要依赖
二、spring boot websocket
- 2.1 创建消息处理类ChatSocket,使用@ServerEndpoint声明websocket服务
- 2.2 配置ServerEndpointExporter,ServerEndpointExporter会在运行时候自动注册我们用@ServerEndpoint声明的websocket服务。
+ 2.1 创建消息处理类ChatSocket,使用@ServerEndpoint声明websocket服务
+ 2.2 配置ServerEndpointExporter,ServerEndpointExporter会在运行时候自动注册我们用@ServerEndpoint声明的websocket服务。
2.3 前端websocket的实现
2.4 简单登录的实现
## 正文
+
+
## 一、说明
### 1.1 项目结构说明
diff --git a/spring-cloud/spring-cloud-config/README.md b/spring-cloud/spring-cloud-config/README.md
index 81824de..bc2fb99 100644
--- a/spring-cloud/spring-cloud-config/README.md
+++ b/spring-cloud/spring-cloud-config/README.md
@@ -1,455 +1,443 @@
-# spring-cloud-config
-
## 目录
+# spring-cloud-config
+
+## 目录
一、config 简介
二、项目结构
三、config-server 配置中心的实现
- 3.1 导入依赖
- 3.2 在启动类上添加@EnableDiscoveryClient和@EnableConfigServer 注解
- 3.3 指定注册中心地址,并配置git仓库地址的配置文件路径
- 3.4 启动eureka和config-server服务,访问 http://localhost:8020/application-dev.yml
- 3.5 http请求地址和资源文件映射
四、config-client 搭建
- 4.1 导入依赖
- 4.2 新建 `bootstrap.yml`配置文件,指定注册中心地址和配置中心服务名,并在启动类上开启自动注册@EnableDiscoveryClient
- 4.3 创建配置映射类用于测试
- 4.4 依次启动eureka,config-server,config-client ,访问 http://localhost:8030/programmer
五、集成 spring-cloud-bus 实现配置热更新
- 5.1 消息总线简介
- 5.1 导入bus依赖
- 5.2 修改bootstrap.yml 配置,开启总线配置,配置rabbitmq 和 开启热刷新[端点](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-actuator)
- 5.3 用@RefreshScope指定需要热刷新的配置
- 5.4 依次启动eureka,config-server, config-client 服务
- 5.6 直接在 git 上修改配置文件,然后用 `post` 触发热刷新端点 http://localhost:8030/actuator/bus-refresh ,即可看到配置已经热刷新
+
## 正文
-## 一、config 简介
-
-spring cloud config 分为服务端和客户端,服务端称为分布式配置中心,集中管理配置文件,客户端为各个业务单元,它们从配置中心获取相关配置,同时config 还实现了配置热更新,在服务不停机的情况下刷新配置。
-
-
-
-## 二、项目结构
-
-+ config-server: 配置中心;
-+ config-client: 服务单元,可以从配置中心获取相关配置;
-+ eureka: 注册中心。
-
-
-
-
-
-
-
-## 三、config-server 配置中心的实现
-
-#### 3.1 导入依赖
-
-```xml
-
-
- 4.0.0
-
-
- com.heibaiying.config
- spring-cloud-config
- 0.0.1-SNAPSHOT
-
-
- config-server
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.cloud
- spring-cloud-config-server
-
-
- org.springframework.cloud
- spring-cloud-starter-netflix-eureka-client
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
-```
-
-
-
-#### 3.2 在启动类上添加@EnableDiscoveryClient和@EnableConfigServer 注解
-
-```java
-@SpringBootApplication
-@EnableDiscoveryClient
-@EnableConfigServer
-public class ConfigServerApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(ConfigServerApplication.class, args);
- }
-
-}
-```
-
-
-
-#### 3.3 指定注册中心地址,并配置git仓库地址的配置文件路径
-
-```yaml
-server:
- port: 8020
-# 指定注册中心地址
-eureka:
- client:
- serviceUrl:
- defaultZone: http://localhost:8010/eureka/
-# 指定服务命名
-spring:
- application:
- name: config-server
- cloud:
- config:
- server:
- git:
- uri: https://github.com/heibaiying/spring-samples-for-all/
- search-paths: spring-cloud/spring-cloud-test-config/
- # 如果代码仓库是公开的 则 不需要设置用户名和密码
- username:
- password:
- # 指定拉取的配置文件的存放位置,配置文件最后存储的目录为 basedir + search-paths
- # 这个地方还需要注意的是,配置文件的仓库最好只放配置文件
- # 因为配置中心不仅会拉取search-paths下的文件,还会把uri指定仓库中的全部文件拉取到basedir下
- basedir: D:\git-config
- # 指定分支
- label: master
-```
-
-这里的git 仓库就是本用例的仓库,是公开的仓库,所以不用配置用户名和密码,配置文件如下
-
-- application.yml 为主配置;
-- application-dev.yml 为开发环境配置。
-
-
-
-
-
-#### 3.4 启动eureka和config-server服务,访问 http://localhost:8020/application-dev.yml
-
-
-
-这里需要注意的拉取配置的时候,我们此时指定拉取的是dev配置,application.yml实际 配置如下:
-
-
-
-这说明在用配置中心拉取配置的时候,和我们在本地开发的时候是一致的,配置是互补的,即dev中的实际配置应该是主配置和dev配置的结合,且遵循同名属性精确优先的原则。
-
-
-
-#### 3.5 http请求地址和资源文件映射
-
-在本用例中如果我们想要直接访问主配置,用以下路径 http://localhost:8020/application.yml 是不行的,会得到错误页面。如果想要访问主配置,,可以用http://localhost:8020/application-X.yml,其中可以是任意字符,原因是:
-
-请求地址和实际的配置文件应该遵循以下规则,application为配置文件名,profile 为环境,label为分支(如果不指定默认就是master分支)。
-
-- /{application}/{profile}[/{label}]
-- /{application}-{profile}.yml
-- /{label}/{application}-{profile}.yml
-- /{application}-{profile}.properties
-- /{label}/{application}-{profile}.properties
-
-访问主配置:
-
-
-
-
-
-## 四、config-client 搭建
-
-#### 4.1 导入依赖
-
-```xml
-
-
- 4.0.0
-
-
- com.heibaiying.config
- spring-cloud-config
- 0.0.1-SNAPSHOT
-
-
- config-client
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
- org.springframework.cloud
- spring-cloud-starter-config
-
-
-
- org.springframework.cloud
- spring-cloud-starter-netflix-eureka-client
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
-
-```
-
-#### 4.2 新建 `bootstrap.yml`配置文件,指定注册中心地址和配置中心服务名,并在启动类上开启自动注册@EnableDiscoveryClient
-
-这里需要特别说明的是,在之前的所有项目中我们采用的配置文件都是application.yml,但是这里**一定要采用bootstrap.yml**。
-
-假设我们的数据库配置是放在远程配置中心的,那么我们应该先去远程配置中心拉取配置,然后再去进行数据库的自动化配置,反之如果我们先进行了数据库的自动化配置,那么就会因为找不到url或驱动而抛出异常。
-
-- bootstrap.yml(bootstrap.properties)用来程序引导时执行,应用于更加早期配置信息读取,bootstrap.yml 先于 application.yml 加载。
-
-- application.yml(application.properties) 应用程序各个模块的配置信息。
-
-```yaml
-server:
- port: 8030
-spring:
- application:
- name: config-client
- cloud:
- config:
- discovery:
- enabled: true
- # 这里我们指定的是服务名 如果配置中心有多个,且用同一个服务名,我们的客户端拉取配置的时候是负载均衡的,配置中心也就是高可用的
- serviceId: config-server
- # 指定分支
- label: master
- # 指定环境
- profile: dev
-
-
-# 注意指定注册中心的配置不要从公共配置中拉取,要在本地的配置文件中指定
-# 因为我们必须要先从注册中心去获取可用的配置中心, 从配置中心去拉取配置
-eureka:
- client:
- serviceUrl:
- defaultZone: http://localhost:8010/eureka/
-
-```
-
-```java
-@SpringBootApplication
-@EnableDiscoveryClient
-public class ConfigClientApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(ConfigClientApplication.class, args);
- }
-
-}
-
-```
-
-#### 4.3 创建配置映射类用于测试
-
-```java
-@Component
-@ConfigurationProperties(prefix = "programmer")
-@Data
-@ToString
-public class Programmer{
-
- private String name;
- private int age;
- private boolean married;
- private Date hireDate;
- private float salary;
- private int random;
- private Map skill;
- private List company;
- private School school;
-
-}
-```
-
-```java
-@RestController
-public class ConfigController {
-
- @Autowired
- private Programmer programmer;
-
- @RequestMapping("programmer")
- public String getProgrammer() {
- return programmer.toString();
- }
-}
-```
-
-#### 4.4 依次启动eureka,config-server,config-client ,访问 http://localhost:8030/programmer
-
-这里需要注意是在启动eureka和config-server,要稍等一会在启动config-client,这里是为了确保config-server已经将服务注册到eureka,然后我们的config-client才能从eureka中获取配置中心的服务。
-
-
-
-启动的时候可以从控制台看到如下拉取服务的信息:
-
-```shell
-Fetching config from server at : http://localhost:8020/
-Located environment: name=config-client, profiles=[dev], label=master, version=50dcfb85cd751e4f28761cd6bad84c1f73034002, state=null
-```
-
-
-
-## 五、集成 spring-cloud-bus 实现配置热更新
-
-#### 5.1 消息总线简介
-
-在微服务的架构中,我们通常想要构建一个共同的消息主题被所有微服务实例所监听,以便对所有微服务实例的管理和通知,这就是消息总线,spring cloud bus 就是消息总线的一种实现。
-
-目前spring cloud bus 支持的消息中间件有 RabbitMQ和kafka, 我们下面的整合采用的是RrabbitMQ。
-
-关于热更新只需要对配置客户端(config-client)做更改,不需要对(config-server)做改动。
-
-#### 5.1 导入bus依赖
-
-```xml
-
- org.springframework.cloud
- spring-cloud-starter-bus-amqp
-
-
-
- org.springframework.boot
- spring-boot-starter-actuator
-
-```
-
-#### 5.2 修改bootstrap.yml 配置,开启总线配置,配置rabbitmq 和 开启热刷新[端点](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-actuator)
-
-```yml
-server:
- port: 8030
-spring:
- application:
- name: config-client
- cloud:
- config:
- discovery:
- enabled: true
- # 这里我们指定的是服务名 如果配置中心有多个,且用同一个服务名,我们的客户端拉取配置的时候是负载均衡的,配置中心也就是高可用
- serviceId: config-server
- # 指定分支
- label: master
- # 指定环境
- profile: dev
- bus:
- #开启总线
- enabled: true
- # 打开ack跟踪的标志(默认关闭)
- trace:
- enabled: true
- # 使用bus实现热更新
- rabbitmq:
- host: 127.0.0.1
- port: 5672
- username: guest
- password: guest
-
-
-# 注意指定注册中心的配置不要从公共配置中拉取,要在本地的配置文件中指定
-# 因为我们必须要先从注册中心去获取可用的配置中心, 然后从配置中心去拉取配置
-eureka:
- client:
- serviceUrl:
- defaultZone: http://localhost:8010/eureka/
-
-# 暴露热刷新的端点
-management:
- endpoints:
- web:
- exposure:
- include: bus-refresh
-
-```
-
-#### 5.3 用@RefreshScope指定需要热刷新的配置
-
-```java
-@Component
-@ConfigurationProperties(prefix = "programmer")
-@Data
-@ToString
-@RefreshScope // 定义下面配置热刷新范围
-public class Programmer{
-
- private String name;
- private int age;
- private boolean married;
- private Date hireDate;
- private float salary;
- private int random;
- private Map skill;
- private List company;
- private School school;
-
-}
-```
-
-#### 5.4 依次启动eureka,config-server, config-client 服务
-
-在client服务端启动时候,可以在控制台 看到bus 自动创建了交换机、队列等
-
-```
-Created new connection: rabbitConnectionFactory#496c6d94:22/SimpleConnection@185d85d2 [delegate=amqp://guest@127.0.0.1:5672/, localPort= 63713]
-o.s.amqp.rabbit.core.RabbitAdmin : Auto-declaring a non-durable, auto-delete, or exclusive Queue (springCloudBus.anonymous.iY4TIIi9TSe0bL-TWAMhWg) durable:false, auto-delete:true, exclusive:true. It will be redeclared if the broker stops and is restarted while the connection factory is alive, but all messages will be lost.
-```
-
-也可以在 rabbitmq 管控台查看
-
-
-
-
-
-
-
-#### 5.6 直接在 git 上修改配置文件,然后用 `post` 触发热刷新端点 http://localhost:8030/actuator/bus-refresh ,即可看到配置已经热刷新
-
-注意: 这里的只能用 post 方式请求 ,可以用 postman 等测试软件
-
-
-
-热刷新的过程在控制台有详细的打印,部分日志如下:
-
-```shell
-# 消息传播
-Attempting to connect to: [127.0.0.1:5672]
-Created new connection: rabbitConnectionFactory.publisher#b00f2d6:0/SimpleConnection@403c0406 [delegate=amqp://guest@127.0.0.1:5672/, localPort= 62748]
-# 从配置中心拉取配置文件
-Fetching config from server at : http://DESKTOP-8JGSFLJ:8020/
-# 刷新应用上下文 AnnotationConfigApplicationContext
-Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@62e12f66
-```
-
+
+## 一、config 简介
+
+spring cloud config 分为服务端和客户端,服务端称为分布式配置中心,集中管理配置文件,客户端为各个业务单元,它们从配置中心获取相关配置,同时config 还实现了配置热更新,在服务不停机的情况下刷新配置。
+
+
+
+## 二、项目结构
+
++ config-server: 配置中心;
++ config-client: 服务单元,可以从配置中心获取相关配置;
++ eureka: 注册中心。
+
+
+
+
+
+
+
+## 三、config-server 配置中心的实现
+
+#### 3.1 导入依赖
+
+```xml
+
+
+ 4.0.0
+
+
+ com.heibaiying.config
+ spring-cloud-config
+ 0.0.1-SNAPSHOT
+
+
+ config-server
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-config-server
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+```
+
+
+
+#### 3.2 在启动类上添加@EnableDiscoveryClient和@EnableConfigServer 注解
+
+```java
+@SpringBootApplication
+@EnableDiscoveryClient
+@EnableConfigServer
+public class ConfigServerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ConfigServerApplication.class, args);
+ }
+
+}
+```
+
+
+
+#### 3.3 指定注册中心地址,并配置git仓库地址的配置文件路径
+
+```yaml
+server:
+ port: 8020
+# 指定注册中心地址
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://localhost:8010/eureka/
+# 指定服务命名
+spring:
+ application:
+ name: config-server
+ cloud:
+ config:
+ server:
+ git:
+ uri: https://github.com/heibaiying/spring-samples-for-all/
+ search-paths: spring-cloud/spring-cloud-test-config/
+ # 如果代码仓库是公开的 则 不需要设置用户名和密码
+ username:
+ password:
+ # 指定拉取的配置文件的存放位置,配置文件最后存储的目录为 basedir + search-paths
+ # 这个地方还需要注意的是,配置文件的仓库最好只放配置文件
+ # 因为配置中心不仅会拉取search-paths下的文件,还会把uri指定仓库中的全部文件拉取到basedir下
+ basedir: D:\git-config
+ # 指定分支
+ label: master
+```
+
+这里的git 仓库就是本用例的仓库,是公开的仓库,所以不用配置用户名和密码,配置文件如下
+
+- application.yml 为主配置;
+- application-dev.yml 为开发环境配置。
+
+
+
+
+
+#### 3.4 启动eureka和config-server服务,访问 http://localhost:8020/application-dev.yml
+
+
+
+这里需要注意的拉取配置的时候,我们此时指定拉取的是dev配置,application.yml实际 配置如下:
+
+
+
+这说明在用配置中心拉取配置的时候,和我们在本地开发的时候是一致的,配置是互补的,即dev中的实际配置应该是主配置和dev配置的结合,且遵循同名属性精确优先的原则。
+
+
+
+#### 3.5 http请求地址和资源文件映射
+
+在本用例中如果我们想要直接访问主配置,用以下路径 http://localhost:8020/application.yml 是不行的,会得到错误页面。如果想要访问主配置,,可以用http://localhost:8020/application-X.yml,其中可以是任意字符,原因是:
+
+请求地址和实际的配置文件应该遵循以下规则,application为配置文件名,profile 为环境,label为分支(如果不指定默认就是master分支)。
+
+- /{application}/{profile}[/{label}]
+- /{application}-{profile}.yml
+- /{label}/{application}-{profile}.yml
+- /{application}-{profile}.properties
+- /{label}/{application}-{profile}.properties
+
+访问主配置:
+
+
+
+
+
+## 四、config-client 搭建
+
+#### 4.1 导入依赖
+
+```xml
+
+
+ 4.0.0
+
+
+ com.heibaiying.config
+ spring-cloud-config
+ 0.0.1-SNAPSHOT
+
+
+ config-client
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+```
+
+#### 4.2 新建 `bootstrap.yml`配置文件,指定注册中心地址和配置中心服务名,并在启动类上开启自动注册@EnableDiscoveryClient
+
+这里需要特别说明的是,在之前的所有项目中我们采用的配置文件都是application.yml,但是这里**一定要采用bootstrap.yml**。
+
+假设我们的数据库配置是放在远程配置中心的,那么我们应该先去远程配置中心拉取配置,然后再去进行数据库的自动化配置,反之如果我们先进行了数据库的自动化配置,那么就会因为找不到url或驱动而抛出异常。
+
+- bootstrap.yml(bootstrap.properties)用来程序引导时执行,应用于更加早期配置信息读取,bootstrap.yml 先于 application.yml 加载。
+
+- application.yml(application.properties) 应用程序各个模块的配置信息。
+
+```yaml
+server:
+ port: 8030
+spring:
+ application:
+ name: config-client
+ cloud:
+ config:
+ discovery:
+ enabled: true
+ # 这里我们指定的是服务名 如果配置中心有多个,且用同一个服务名,我们的客户端拉取配置的时候是负载均衡的,配置中心也就是高可用的
+ serviceId: config-server
+ # 指定分支
+ label: master
+ # 指定环境
+ profile: dev
+
+
+# 注意指定注册中心的配置不要从公共配置中拉取,要在本地的配置文件中指定
+# 因为我们必须要先从注册中心去获取可用的配置中心, 从配置中心去拉取配置
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://localhost:8010/eureka/
+
+```
+
+```java
+@SpringBootApplication
+@EnableDiscoveryClient
+public class ConfigClientApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ConfigClientApplication.class, args);
+ }
+
+}
+
+```
+
+#### 4.3 创建配置映射类用于测试
+
+```java
+@Component
+@ConfigurationProperties(prefix = "programmer")
+@Data
+@ToString
+public class Programmer{
+
+ private String name;
+ private int age;
+ private boolean married;
+ private Date hireDate;
+ private float salary;
+ private int random;
+ private Map skill;
+ private List company;
+ private School school;
+
+}
+```
+
+```java
+@RestController
+public class ConfigController {
+
+ @Autowired
+ private Programmer programmer;
+
+ @RequestMapping("programmer")
+ public String getProgrammer() {
+ return programmer.toString();
+ }
+}
+```
+
+#### 4.4 依次启动eureka,config-server,config-client ,访问 http://localhost:8030/programmer
+
+这里需要注意是在启动eureka和config-server,要稍等一会在启动config-client,这里是为了确保config-server已经将服务注册到eureka,然后我们的config-client才能从eureka中获取配置中心的服务。
+
+
+
+启动的时候可以从控制台看到如下拉取服务的信息:
+
+```shell
+Fetching config from server at : http://localhost:8020/
+Located environment: name=config-client, profiles=[dev], label=master, version=50dcfb85cd751e4f28761cd6bad84c1f73034002, state=null
+```
+
+
+
+## 五、集成 spring-cloud-bus 实现配置热更新
+
+#### 5.1 消息总线简介
+
+在微服务的架构中,我们通常想要构建一个共同的消息主题被所有微服务实例所监听,以便对所有微服务实例的管理和通知,这就是消息总线,spring cloud bus 就是消息总线的一种实现。
+
+目前spring cloud bus 支持的消息中间件有 RabbitMQ和kafka, 我们下面的整合采用的是RrabbitMQ。
+
+关于热更新只需要对配置客户端(config-client)做更改,不需要对(config-server)做改动。
+
+#### 5.1 导入bus依赖
+
+```xml
+
+ org.springframework.cloud
+ spring-cloud-starter-bus-amqp
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+```
+
+#### 5.2 修改bootstrap.yml 配置,开启总线配置,配置rabbitmq 和 开启热刷新[端点](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-actuator)
+
+```yml
+server:
+ port: 8030
+spring:
+ application:
+ name: config-client
+ cloud:
+ config:
+ discovery:
+ enabled: true
+ # 这里我们指定的是服务名 如果配置中心有多个,且用同一个服务名,我们的客户端拉取配置的时候是负载均衡的,配置中心也就是高可用
+ serviceId: config-server
+ # 指定分支
+ label: master
+ # 指定环境
+ profile: dev
+ bus:
+ #开启总线
+ enabled: true
+ # 打开ack跟踪的标志(默认关闭)
+ trace:
+ enabled: true
+ # 使用bus实现热更新
+ rabbitmq:
+ host: 127.0.0.1
+ port: 5672
+ username: guest
+ password: guest
+
+
+# 注意指定注册中心的配置不要从公共配置中拉取,要在本地的配置文件中指定
+# 因为我们必须要先从注册中心去获取可用的配置中心, 然后从配置中心去拉取配置
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://localhost:8010/eureka/
+
+# 暴露热刷新的端点
+management:
+ endpoints:
+ web:
+ exposure:
+ include: bus-refresh
+
+```
+
+#### 5.3 用@RefreshScope指定需要热刷新的配置
+
+```java
+@Component
+@ConfigurationProperties(prefix = "programmer")
+@Data
+@ToString
+@RefreshScope // 定义下面配置热刷新范围
+public class Programmer{
+
+ private String name;
+ private int age;
+ private boolean married;
+ private Date hireDate;
+ private float salary;
+ private int random;
+ private Map skill;
+ private List company;
+ private School school;
+
+}
+```
+
+#### 5.4 依次启动eureka,config-server, config-client 服务
+
+在client服务端启动时候,可以在控制台 看到bus 自动创建了交换机、队列等
+
+```
+Created new connection: rabbitConnectionFactory#496c6d94:22/SimpleConnection@185d85d2 [delegate=amqp://guest@127.0.0.1:5672/, localPort= 63713]
+o.s.amqp.rabbit.core.RabbitAdmin : Auto-declaring a non-durable, auto-delete, or exclusive Queue (springCloudBus.anonymous.iY4TIIi9TSe0bL-TWAMhWg) durable:false, auto-delete:true, exclusive:true. It will be redeclared if the broker stops and is restarted while the connection factory is alive, but all messages will be lost.
+```
+
+也可以在 rabbitmq 管控台查看
+
+
+
+
+
+
+
+#### 5.6 直接在 git 上修改配置文件,然后用 `post` 触发热刷新端点 http://localhost:8030/actuator/bus-refresh ,即可看到配置已经热刷新
+
+注意: 这里的只能用 post 方式请求 ,可以用 postman 等测试软件
+
+
+
+热刷新的过程在控制台有详细的打印,部分日志如下:
+
+```shell
+# 消息传播
+Attempting to connect to: [127.0.0.1:5672]
+Created new connection: rabbitConnectionFactory.publisher#b00f2d6:0/SimpleConnection@403c0406 [delegate=amqp://guest@127.0.0.1:5672/, localPort= 62748]
+# 从配置中心拉取配置文件
+Fetching config from server at : http://DESKTOP-8JGSFLJ:8020/
+# 刷新应用上下文 AnnotationConfigApplicationContext
+Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@62e12f66
+```
+
diff --git a/spring-cloud/spring-cloud-eureka-cluster/README.md b/spring-cloud/spring-cloud-eureka-cluster/README.md
index 72c19f3..37fd6eb 100644
--- a/spring-cloud/spring-cloud-eureka-cluster/README.md
+++ b/spring-cloud/spring-cloud-eureka-cluster/README.md
@@ -5,18 +5,18 @@
二、三步搭建eureka 高可用注册中心
2.1 引入eureka服务端依赖
2.2 创建三份配置文件,分别代表不同注册中心的配置
- 2.3 启动类上增加注解@EnableEurekaServer激活eureka服务端自动配置
+ 2.3 启动类上增加注解@EnableEurekaServer激活eureka服务端自动配置
三、三步搭建eureka 客户端
3.1 引入eureka客户端依赖
3.2 eureka 客户端配置,指定注册中心地址
- 3.3 启动类上增加注解@EnableDiscoveryClient激活eureka客户端自动配置
+ 3.3 启动类上增加注解@EnableDiscoveryClient激活eureka客户端自动配置
4.启动项目
4.1 这里我们可以采用命令行方式指定配置,分别启动三个注册中心
4.2 高可用集群搭建成功的判定
- 4.2.1 点击下面注册中心的可用实例列表中的地址,访问链接分以下几个情况:
4.3 prefer-ip-address 参数说明
## 正文
+
## 一、项目结构
eureka-server为服务注册中心,负责服务的管理;
diff --git a/spring-cloud/spring-cloud-eureka/README.md b/spring-cloud/spring-cloud-eureka/README.md
index d83cdfa..c0ce2e4 100644
--- a/spring-cloud/spring-cloud-eureka/README.md
+++ b/spring-cloud/spring-cloud-eureka/README.md
@@ -5,15 +5,16 @@
三、三步搭建eureka 服务注册中心
3.1 引入eureka服务端依赖
3.2 eureka 服务端配置
- 3.3 启动类上增加注解@EnableEurekaServer激活eureka服务端自动配置
+ 3.3 启动类上增加注解@EnableEurekaServer激活eureka服务端自动配置
四、三步搭建eureka 客户端
4.1 引入eureka客户端依赖
4.2 eureka 客户端配置
- 4.3 启动类上增加注解@EnableDiscoveryClient激活eureka客户端自动配置
+ 4.3 启动类上增加注解@EnableDiscoveryClient激活eureka客户端自动配置
五、启动项目
5.1 进入注册中心控制台,查看服务注册情况
## 正文
+
## 一、eureka 简介
Spring Cloud Eureka使用Netflix Eureka来实现服务注册与发现,它既包含了服务端组件,也包含了客户端组件。
diff --git a/spring-cloud/spring-cloud-feign/README.md b/spring-cloud/spring-cloud-feign/README.md
index fc42efe..b286e6a 100644
--- a/spring-cloud/spring-cloud-feign/README.md
+++ b/spring-cloud/spring-cloud-feign/README.md
@@ -1,400 +1,388 @@
-# spring-cloud-feign
-
## 目录
+# spring-cloud-feign
+
+## 目录
一、feign 简介
二、项目结构
三、服务提供者的实现
- 3.1 产品服务由`ProductService`提供,并通过`ProducerController`将服务暴露给外部调用。
- 3.2 指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient
四、服务消费者的实现
- 4.1 导入openfeign依赖
- 4.2 指定注册中心地址,并在启动类上添加注解@EnableDiscoveryClient和@EnableFeignClients
- 4.3 创建服务调用公共接口
- 4.4 继承公共接口,创建CProductFeign, 用@FeignClient声明为feign客户端
- 4.5 注入使用 feign 服务调用接口
五、启动测试
- 5.1 启动一个Eureka服务、三个producer服务(注意区分端口)、和一个消费者服务
- 5.2 访问http://localhost:8080/sell/products 查看负载均衡的调用结果
六、 feign 的服务容错
- 6.1 feign 的依赖中默认导入了hystrix 的相关依赖,我们不需要额外导入,只需要开启相关配置即可
- 6.2 在application.yml 中开启hystrix
- 6.3 创建`CProductFeignImpl`,继承feign接口(CProductFeign),定义熔断时候的回退处理
- 6.4 在 @FeignClient 注解中,用fallback参数指定熔断时候的回退处理
- 6.5 测试熔断处理
## 正文
-## 一、feign 简介
-
-在上一个用例中,我们使用ribbon+restTemplate 实现服务之间的远程调用,实际上每一个调用都是模板化的内容,所以spring cloud Feign 在此基础上进行了进一步的封装。我们只需要定义一个接口并使用feign注解的方式来进行配置,同时采用springMvc 注解进行参数绑定就可以完成服务的调用。feign同时还内置实现了负载均衡、服务容错等功能。
-
-
-
-## 二、项目结构
-
-+ common: 公共的接口和实体类;
-+ consumer: 服务的消费者,采用feign调用产品服务;
-+ producer:服务的提供者;
-+ eureka: 注册中心。
-
-
-
-
-
-
-
-## 三、服务提供者的实现
-
-
-
-#### 3.1 产品服务由`ProductService`提供,并通过`ProducerController`将服务暴露给外部调用。
-
-ProductService.java:
-
-```java
-/**
- * @author : heibaiying
- * @description : 产品提供接口实现类
- */
-@Service
-public class ProductService implements IProductService, ApplicationListener {
-
- private static List productList = new ArrayList<>();
-
- public Product queryProductById(int id) {
- return productList.stream().filter(p->p.getId()==id).collect(Collectors.toList()).get(0);
- }
-
-
- public List queryAllProducts() {
- return productList;
- }
-
- @Override
- public void saveProduct(Product product) {
- productList.add(product);
- }
-
- @Override
- public void onApplicationEvent(WebServerInitializedEvent event) {
- int port = event.getWebServer().getPort();
- for (long i = 0; i < 20; i++) {
- productList.add(new Product(i, port + "产品" + i, i / 2 == 0, new Date(), 66.66f * i));
- }
- }
-}
-```
-
-ProducerController.java:
-
-```java
-@RestController
-public class ProducerController implements ProductFeign {
-
- @Autowired
- private IProductService productService;
-
- @GetMapping("products")
- public List productList() {
- return productService.queryAllProducts();
- }
-
- @GetMapping("product/{id}")
- public Product productDetail(@PathVariable int id) {
- return productService.queryProductById(id);
- }
-
- @PostMapping("product")
- public void save(@RequestBody Product product) {
- productService.saveProduct(product);
- }
-}
-```
-
-#### 3.2 指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient
-
-```java
-server:
- port: 8020
-# 指定服务命名
-spring:
- application:
- name: producer
-# 指定注册中心地址
-eureka:
- client:
- serviceUrl:
- defaultZone: http://localhost:8010/eureka/
-```
-
-```java
-@SpringBootApplication
-@EnableDiscoveryClient
-public class ProducerApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(ProducerApplication.class, args);
- }
-
-}
-
-```
-
-
-
-## 四、服务消费者的实现
-
-
-
-#### 4.1 导入openfeign依赖
-
-```xml
-
-
- org.springframework.cloud
- spring-cloud-starter-openfeign
-
-```
-
-#### 4.2 指定注册中心地址,并在启动类上添加注解@EnableDiscoveryClient和@EnableFeignClients
-
-@EnableFeignClients 会去扫描工程中所有用 @FeignClient 声明的 feign 客户端。
-
-```java
-server:
- port: 8080
-# 指定服务命名
-spring:
- application:
- name: consumer
-# 指定注册中心地址
-eureka:
- client:
- serviceUrl:
- defaultZone: http://localhost:8010/eureka/
-```
-
-```java
-@SpringBootApplication
-@EnableDiscoveryClient
-@EnableFeignClients
-public class ConsumerApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(ConsumerApplication.class, args);
- }
-
-}
-```
-
-#### 4.3 创建服务调用公共接口
-
-```java
-/**
- * @author : heibaiying
- * @description : 声明式服务调用
- */
-public interface ProductFeign {
-
- @GetMapping("products")
- List productList();
-
- /**
- * 这是需要强调的是使用feign时候@PathVariable一定要用value指明参数,
- * 不然会抛出.IllegalStateException: PathVariable annotation was empty on param 异常
- */
- @GetMapping("product/{id}")
- Product productDetail(@PathVariable(value = "id") int id);
-
-
- @PostMapping("product")
- void save(@RequestBody Product product);
-}
-
-```
-
-按照官方对于服务最佳化的推荐,这里我们的服务调用接口放在公共模块中,因为在实际的开发中,同一个服务调用接口可能被多个模块所使用。
-
-
-
-
-
-#### 4.4 继承公共接口,创建CProductFeign, 用@FeignClient声明为feign客户端
-
-```java
-/**
- * @author : heibaiying
- * @description : 声明式接口调用
- */
-@FeignClient(value = "producer",configuration = FeignConfig.class)
-public interface CProductFeign extends ProductFeign {
-
-}
-```
-
-#### 4.5 注入使用 feign 服务调用接口
-
-```java
-@Controller
-@RequestMapping("sell")
-public class SellController {
-
- @Autowired
- private CProductFeign cproductFeign;
-
- @GetMapping("products")
- public String productList(Model model) {
- List products = cproductFeign.productList();
- model.addAttribute("products", products);
- return "products";
- }
-
- @GetMapping("product/{id}")
- public String productDetail(@PathVariable int id, Model model) {
- Product product = cproductFeign.productDetail(id);
- model.addAttribute("product", product);
- return "product";
- }
-
-
- @PostMapping("product")
- public String save(@RequestParam String productName) {
- long id = Math.round(Math.random() * 100);
- Product product = new Product(id, productName, false, new Date(), 88);
- cproductFeign.save(product);
- return "redirect:products";
- }
-}
-```
-
-
-
-## 五、启动测试
-
-#### 5.1 启动一个Eureka服务、三个producer服务(注意区分端口)、和一个消费者服务
-
-feign 的依赖中导入了spring-cloud-starter-netflix-ribbon依赖,并且在内部实现了基于ribbon的客户端负载均衡,所以我们这里启动三个producer实例来观察负载均衡的情况。
-
-
-
-**服务注册中心:**
-
-
-
-#### 5.2 访问http://localhost:8080/sell/products 查看负载均衡的调用结果
-
-
-
-
-
-
-
-
-
-
-
-## 六、 feign 的服务容错
-
-#### 6.1 feign 的依赖中默认导入了hystrix 的相关依赖,我们不需要额外导入,只需要开启相关配置即可
-
-
-
-
-
-#### 6.2 在application.yml 中开启hystrix
-
-```yml
-feign:
- hystrix:
- # 如果为true,则OpenFign客户端将使用Hystrix断路器进行封装 默认为false
- enabled: true
-```
-
-#### 6.3 创建`CProductFeignImpl`,继承feign接口(CProductFeign),定义熔断时候的回退处理
-
-```java
-/**
- * @author : heibaiying
- * @description : 定义发生熔断时候的回退处理。除了继承自CProductFeign,还需要用@Component声明为spring的组件
- */
-@Component
-public class CProductFeignImpl implements CProductFeign {
-
- // 发生熔断时候,返回空集合,前端页面会做容错显示
- @Override
- public List productList() {
- return new ArrayList<>();
- }
-
- @Override
- public Product productDetail(int id) {
- return null;
- }
-
- @Override
- public void save(Product product) {
-
- }
-}
-```
-
-页面的简单容错处理:
-
-```html
-
-
-
- 产品列表
-
-
-产品列表:点击查看详情
-
-
- <#if (products?size>0) >
- <#list products as product>
- -
- ${product.name}
-
- #list>
- <#else>
- 当前排队人数过多,请之后再购买!
- #if>
-
-
-
-```
-
-#### 6.4 在 @FeignClient 注解中,用fallback参数指定熔断时候的回退处理
-
-```java
-/**
- * @author : heibaiying
- * @description : 声明式接口调用
- */
-@FeignClient(value = "producer",configuration = FeignConfig.class,fallback = CProductFeignImpl.class)
-public interface CProductFeign extends ProductFeign {
-
-}
-```
-
-#### 6.5 测试熔断处理
-
-hystrix 默认调用超时时间为2s ,这里我们使用线程休眠的方式来模拟超时熔断。
-
-```java
-public List queryAllProducts() {
- /*用于测试 hystrix 超时熔断
- try {
- int i = new Random().nextInt(2500);
- Thread.sleep(i);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }*/
- return productList;
-}
-```
-
-测试结果:
-
+
+## 一、feign 简介
+
+在上一个用例中,我们使用ribbon+restTemplate 实现服务之间的远程调用,实际上每一个调用都是模板化的内容,所以spring cloud Feign 在此基础上进行了进一步的封装。我们只需要定义一个接口并使用feign注解的方式来进行配置,同时采用springMvc 注解进行参数绑定就可以完成服务的调用。feign同时还内置实现了负载均衡、服务容错等功能。
+
+
+
+## 二、项目结构
+
++ common: 公共的接口和实体类;
++ consumer: 服务的消费者,采用feign调用产品服务;
++ producer:服务的提供者;
++ eureka: 注册中心。
+
+
+
+
+
+
+
+## 三、服务提供者的实现
+
+
+
+#### 3.1 产品服务由`ProductService`提供,并通过`ProducerController`将服务暴露给外部调用。
+
+ProductService.java:
+
+```java
+/**
+ * @author : heibaiying
+ * @description : 产品提供接口实现类
+ */
+@Service
+public class ProductService implements IProductService, ApplicationListener {
+
+ private static List productList = new ArrayList<>();
+
+ public Product queryProductById(int id) {
+ return productList.stream().filter(p->p.getId()==id).collect(Collectors.toList()).get(0);
+ }
+
+
+ public List queryAllProducts() {
+ return productList;
+ }
+
+ @Override
+ public void saveProduct(Product product) {
+ productList.add(product);
+ }
+
+ @Override
+ public void onApplicationEvent(WebServerInitializedEvent event) {
+ int port = event.getWebServer().getPort();
+ for (long i = 0; i < 20; i++) {
+ productList.add(new Product(i, port + "产品" + i, i / 2 == 0, new Date(), 66.66f * i));
+ }
+ }
+}
+```
+
+ProducerController.java:
+
+```java
+@RestController
+public class ProducerController implements ProductFeign {
+
+ @Autowired
+ private IProductService productService;
+
+ @GetMapping("products")
+ public List productList() {
+ return productService.queryAllProducts();
+ }
+
+ @GetMapping("product/{id}")
+ public Product productDetail(@PathVariable int id) {
+ return productService.queryProductById(id);
+ }
+
+ @PostMapping("product")
+ public void save(@RequestBody Product product) {
+ productService.saveProduct(product);
+ }
+}
+```
+
+#### 3.2 指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient
+
+```java
+server:
+ port: 8020
+# 指定服务命名
+spring:
+ application:
+ name: producer
+# 指定注册中心地址
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://localhost:8010/eureka/
+```
+
+```java
+@SpringBootApplication
+@EnableDiscoveryClient
+public class ProducerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ProducerApplication.class, args);
+ }
+
+}
+
+```
+
+
+
+## 四、服务消费者的实现
+
+
+
+#### 4.1 导入openfeign依赖
+
+```xml
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+```
+
+#### 4.2 指定注册中心地址,并在启动类上添加注解@EnableDiscoveryClient和@EnableFeignClients
+
+@EnableFeignClients 会去扫描工程中所有用 @FeignClient 声明的 feign 客户端。
+
+```java
+server:
+ port: 8080
+# 指定服务命名
+spring:
+ application:
+ name: consumer
+# 指定注册中心地址
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://localhost:8010/eureka/
+```
+
+```java
+@SpringBootApplication
+@EnableDiscoveryClient
+@EnableFeignClients
+public class ConsumerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ConsumerApplication.class, args);
+ }
+
+}
+```
+
+#### 4.3 创建服务调用公共接口
+
+```java
+/**
+ * @author : heibaiying
+ * @description : 声明式服务调用
+ */
+public interface ProductFeign {
+
+ @GetMapping("products")
+ List productList();
+
+ /**
+ * 这是需要强调的是使用feign时候@PathVariable一定要用value指明参数,
+ * 不然会抛出.IllegalStateException: PathVariable annotation was empty on param 异常
+ */
+ @GetMapping("product/{id}")
+ Product productDetail(@PathVariable(value = "id") int id);
+
+
+ @PostMapping("product")
+ void save(@RequestBody Product product);
+}
+
+```
+
+按照官方对于服务最佳化的推荐,这里我们的服务调用接口放在公共模块中,因为在实际的开发中,同一个服务调用接口可能被多个模块所使用。
+
+
+
+
+
+#### 4.4 继承公共接口,创建CProductFeign, 用@FeignClient声明为feign客户端
+
+```java
+/**
+ * @author : heibaiying
+ * @description : 声明式接口调用
+ */
+@FeignClient(value = "producer",configuration = FeignConfig.class)
+public interface CProductFeign extends ProductFeign {
+
+}
+```
+
+#### 4.5 注入使用 feign 服务调用接口
+
+```java
+@Controller
+@RequestMapping("sell")
+public class SellController {
+
+ @Autowired
+ private CProductFeign cproductFeign;
+
+ @GetMapping("products")
+ public String productList(Model model) {
+ List products = cproductFeign.productList();
+ model.addAttribute("products", products);
+ return "products";
+ }
+
+ @GetMapping("product/{id}")
+ public String productDetail(@PathVariable int id, Model model) {
+ Product product = cproductFeign.productDetail(id);
+ model.addAttribute("product", product);
+ return "product";
+ }
+
+
+ @PostMapping("product")
+ public String save(@RequestParam String productName) {
+ long id = Math.round(Math.random() * 100);
+ Product product = new Product(id, productName, false, new Date(), 88);
+ cproductFeign.save(product);
+ return "redirect:products";
+ }
+}
+```
+
+
+
+## 五、启动测试
+
+#### 5.1 启动一个Eureka服务、三个producer服务(注意区分端口)、和一个消费者服务
+
+feign 的依赖中导入了spring-cloud-starter-netflix-ribbon依赖,并且在内部实现了基于ribbon的客户端负载均衡,所以我们这里启动三个producer实例来观察负载均衡的情况。
+
+
+
+**服务注册中心:**
+
+
+
+#### 5.2 访问http://localhost:8080/sell/products 查看负载均衡的调用结果
+
+
+
+
+
+
+
+
+
+
+
+## 六、 feign 的服务容错
+
+#### 6.1 feign 的依赖中默认导入了hystrix 的相关依赖,我们不需要额外导入,只需要开启相关配置即可
+
+
+
+
+
+#### 6.2 在application.yml 中开启hystrix
+
+```yml
+feign:
+ hystrix:
+ # 如果为true,则OpenFign客户端将使用Hystrix断路器进行封装 默认为false
+ enabled: true
+```
+
+#### 6.3 创建`CProductFeignImpl`,继承feign接口(CProductFeign),定义熔断时候的回退处理
+
+```java
+/**
+ * @author : heibaiying
+ * @description : 定义发生熔断时候的回退处理。除了继承自CProductFeign,还需要用@Component声明为spring的组件
+ */
+@Component
+public class CProductFeignImpl implements CProductFeign {
+
+ // 发生熔断时候,返回空集合,前端页面会做容错显示
+ @Override
+ public List productList() {
+ return new ArrayList<>();
+ }
+
+ @Override
+ public Product productDetail(int id) {
+ return null;
+ }
+
+ @Override
+ public void save(Product product) {
+
+ }
+}
+```
+
+页面的简单容错处理:
+
+```html
+
+
+
+ 产品列表
+
+
+产品列表:点击查看详情
+
+
+ <#if (products?size>0) >
+ <#list products as product>
+ -
+ ${product.name}
+
+ #list>
+ <#else>
+ 当前排队人数过多,请之后再购买!
+ #if>
+
+
+
+```
+
+#### 6.4 在 @FeignClient 注解中,用fallback参数指定熔断时候的回退处理
+
+```java
+/**
+ * @author : heibaiying
+ * @description : 声明式接口调用
+ */
+@FeignClient(value = "producer",configuration = FeignConfig.class,fallback = CProductFeignImpl.class)
+public interface CProductFeign extends ProductFeign {
+
+}
+```
+
+#### 6.5 测试熔断处理
+
+hystrix 默认调用超时时间为2s ,这里我们使用线程休眠的方式来模拟超时熔断。
+
+```java
+public List queryAllProducts() {
+ /*用于测试 hystrix 超时熔断
+ try {
+ int i = new Random().nextInt(2500);
+ Thread.sleep(i);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }*/
+ return productList;
+}
+```
+
+测试结果:
+
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-hystrix/README.md b/spring-cloud/spring-cloud-hystrix/README.md
index 2653473..a211ed4 100644
--- a/spring-cloud/spring-cloud-hystrix/README.md
+++ b/spring-cloud/spring-cloud-hystrix/README.md
@@ -1,346 +1,338 @@
-# spring-cloud-hystrix-turbine
-
## 目录
+# spring-cloud-hystrix-turbine
+
+## 目录
一、hystrix 简介
1.1 熔断器
1.2 hystrix 工作机制
二、项目结构
三、整合 hystrix (以consumer模块为例)
- 3.1 引入依赖
- 3.2 暴露端点
- 3.3 在启动类上添加注解@EnableHystrix和@EnableHystrixDashboard
- 3.4 使用 @HystrixCommand 定义失败回退的方法
- 3.5 模拟熔断
- 3.5 启动服务,访问 localhost:8030/hystrix
四、使用turbine 实现聚合监控
- 4.1 创建turbine模块,导入依赖
- 4.2 指定注册中心地址和聚合的项目,这里我们监控 consumer,producer 两个项目
- 4.3 在启动类上添加注解
- 4.4 依次启动eureka、producer、consumer、turbine四个项目
五、整合过程中可能出现的问题
5.1 无法访问监控页面
5.2 页面一直loading 或者访问端点页面一直出现ping
## 正文
-## 一、hystrix 简介
-
-#### 1.1 熔断器
-
-在分布式系统中,由于服务之间相互的依赖调用,如果一个服务单元发生了故障就有可能导致故障蔓延至整个系统,从而衍生出一系列的保护机制,断路器就是其中之一。
-
-断路器可以在服务单元发生故障的时候,及时切断与服务单元的连接,避免资源被长时间占用。spring cloud hystrix组件实现了断路器、线程隔离等一系列基本功能,并具有服务降级、服务熔断、请求缓存、请求合并以及服务监控等配套功能。
-
-
-
-#### 1.2 hystrix 工作机制
-
-- 当一个服务的处理请求的失败次数低于阈值时候,熔断器处于关闭状态,服务正常;
-- 当一个服务的处理请求的失败次数大于阈值时候,熔断器开启,这时候所有的请求都会执行快速失败,是不会去调用实际的服务的;
-- 当熔断器处于打开状态的一段时间后,熔断器处于半打开状态,这时候一定数量的请求回去调用实际的服务,如果调用成功,则代表服务可用了,熔断器关闭;如果还是失败,则代表服务还是不可用,熔断器继续关闭。
-
-
-
-## 二、项目结构
-
-[spring-cloud-ribbon](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-ribbon)用例已经实现通过ribbon+restTemplate实现服务间的调用,本用例在其基础上进行hystrix 的整合。
-
-+ common: 公共的接口和实体类;
-+ consumer: 服务的消费者,采用RestTemplate调用产品服务;
-+ producer:服务的提供者;
-+ eureka: 注册中心;
-+ turbine:多个熔断器的聚合监控。
-
-
-
-
-
-## 三、整合 hystrix (以consumer模块为例)
-
-#### 3.1 引入依赖
-
-hystrix的仪表盘功能实际上是从[端点](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-actuator)获取数据,所以需要actuator starter开启端点的相关功能。
-
-```xml
-
-
- org.springframework.cloud
- spring-cloud-starter-netflix-hystrix
-
-
-
- org.springframework.cloud
- spring-cloud-starter-netflix-hystrix-dashboard
-
-
-
- org.springframework.boot
- spring-boot-starter-actuator
-
-```
-
-#### 3.2 暴露端点
-
-```java
-management:
- endpoints:
- web:
- exposure:
- # 需要开启hystrix.stream端点的暴露 这样才能获取到监控信息 * 代表开启所有可监控端点
- include: "*"
-```
-
-#### 3.3 在启动类上添加注解@EnableHystrix和@EnableHystrixDashboard
-
-```java
-@SpringBootApplication
-@EnableDiscoveryClient
-@EnableHystrix
-@EnableHystrixDashboard
-public class ConsumerApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(ConsumerApplication.class, args);
- }
-}
-```
-
-#### 3.4 使用 @HystrixCommand 定义失败回退的方法
-
-```java
-@HystrixCommand(fallbackMethod = "queryProductsFail")
-public List queryAllProducts() {
- ResponseEntity responseEntity = restTemplate.getForEntity("http://producer/products", List.class);
- List productList = responseEntity.getBody();
- return productList;
-}
-
-// 如果发送熔断返回空集合,在前端判断处理
-public List queryProductsFail() {
- return new ArrayList<>();
-}
-```
-
-```html
-
-
-
- 产品列表
-
-
-产品列表:点击查看详情
-
-
- <#if (products?size>0) >
- <#list products as product>
- -
- ${product.name}
-
- #list>
- <#else>
- 当前排队人数过多,请之后再购买!
- #if>
-
-
-
-```
-
-#### 3.5 模拟熔断
-
-这里被调用方采用线程休眠的方式模拟服务超时,Hystrix默认超时时间为2s,调用远程服务时候超过这个时间,会触发熔断。
-
-```java
-public List queryAllProducts() {
- // hystrix 默认超时是2秒
- int i = new Random().nextInt(2500);
- try {
- Thread.sleep(i);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- return productList;
-}
-```
-
-3.5 启动服务,访问http://localhost:8030/sell/products ,多次刷新查看熔断情况
-
-
-
-#### 3.5 启动服务,访问 localhost:8030/hystrix
-
-依次输出http://localhost:8030/actuator/hystrix.stream(监控地址) ,2000(延迟时间),title可以任意填写,进入监控台。
-
-需要注意的是在spring cloud Finchley.SR2,监控地址中都是有/actuator的,因为在spring boot 2.x 的所有端点(包括自定义端点)都是暴露在这个路径下,在启动时候的控制台输出的日志可以查看到所有暴露端点的映射。
-
-**登录页面**:
-
-
-
-**监控页面**:
-
-
-
-**关于各个参数的说明参见[官方wiki](https://github.com/Netflix-Skunkworks/hystrix-dashboard/wiki)提供的图**:
-
-
-
-
-
-
-
-## 四、使用turbine 实现聚合监控
-
-单体监控和聚合监控:
-
-
-
-
-
-#### 4.1 创建turbine模块,导入依赖
-
-```xml
-
-
- 4.0.0
-
-
- com.heibaiying.hystrix
- spring-cloud-hystrx
- 0.0.1-SNAPSHOT
-
-
- turbine
-
-
-
- org.springframework.cloud
- spring-cloud-starter-netflix-eureka-client
-
-
- org.springframework.boot
- spring-boot-starter-actuator
-
-
- org.springframework.cloud
- spring-cloud-starter-netflix-hystrix
-
-
- org.springframework.cloud
- spring-cloud-starter-netflix-hystrix-dashboard
-
-
- org.springframework.cloud
- spring-cloud-starter-netflix-turbine
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
-
-```
-
-
-
-#### 4.2 指定注册中心地址和聚合的项目,这里我们监控 consumer,producer 两个项目
-
-```java
-server:
- port: 8040
-# 指定服务命名
-spring:
- application:
- name: turbine
-# 指定注册中心地址
-eureka:
- client:
- serviceUrl:
- defaultZone: http://localhost:8010/eureka/
-# 指定聚合的项目
-turbine:
- aggregator:
- cluster-config: default
- combine-host-port: true
- app-config: consumer,producer
- clusterNameExpression: "'default'"
-```
-
-
-
-#### 4.3 在启动类上添加注解
-
-```java
-@SpringBootApplication
-@EnableDiscoveryClient
-@EnableHystrix
-@EnableHystrixDashboard
-@EnableTurbine
-public class TurbineApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(TurbineApplication.class, args);
- }
-
-}
-```
-
-
-
-#### 4.4 依次启动eureka、producer、consumer、turbine四个项目
-
-在 localhost:8030/hystrix或者localhost:8030/hystrix(consumer和producer都集成了hystrix) 页面输入http://localhost:8040/turbine.stream,查看断路器聚合信息
-
-
-
-**显示了不同服务单元(consumer,producer)的多个断路器信息:**
-
-
-
-## 五、整合过程中可能出现的问题
-
-#### 5.1 无法访问监控页面
-
-1. 一般是端点链接输入不对,在F版本的spring cloud 中,输入监控的端点链接是 http://localhost:8030/actuator/hystrix.stream ,中间是有/actuator/(之前版本的没有/actuator/)
-
-2. 没有暴露端点链接,暴露端点链接有两种方式,一种是我们在上文中提到的基于配置的方式
-
- ```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;
- }
- ```
-
- 这两种方式二选一即可,就算是采用代码的方式,还是建议将地址设置为/actuator/hystrix.stream,而不是原来的hystrix.stream,因为turbine默认也是从/actuator/hystrix.stream去获取信息。
-
-#### 5.2 页面一直loading 或者访问端点页面一直出现ping
-
-这种情况是熔断器所在的方法没有被调用,所以没有产生监控数据,不是整合问题,这时候调用一下熔断器所在方法即可。
-
-
+
+## 一、hystrix 简介
+
+#### 1.1 熔断器
+
+在分布式系统中,由于服务之间相互的依赖调用,如果一个服务单元发生了故障就有可能导致故障蔓延至整个系统,从而衍生出一系列的保护机制,断路器就是其中之一。
+
+断路器可以在服务单元发生故障的时候,及时切断与服务单元的连接,避免资源被长时间占用。spring cloud hystrix组件实现了断路器、线程隔离等一系列基本功能,并具有服务降级、服务熔断、请求缓存、请求合并以及服务监控等配套功能。
+
+
+
+#### 1.2 hystrix 工作机制
+
+- 当一个服务的处理请求的失败次数低于阈值时候,熔断器处于关闭状态,服务正常;
+- 当一个服务的处理请求的失败次数大于阈值时候,熔断器开启,这时候所有的请求都会执行快速失败,是不会去调用实际的服务的;
+- 当熔断器处于打开状态的一段时间后,熔断器处于半打开状态,这时候一定数量的请求回去调用实际的服务,如果调用成功,则代表服务可用了,熔断器关闭;如果还是失败,则代表服务还是不可用,熔断器继续关闭。
+
+
+
+## 二、项目结构
+
+[spring-cloud-ribbon](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-ribbon)用例已经实现通过ribbon+restTemplate实现服务间的调用,本用例在其基础上进行hystrix 的整合。
+
++ common: 公共的接口和实体类;
++ consumer: 服务的消费者,采用RestTemplate调用产品服务;
++ producer:服务的提供者;
++ eureka: 注册中心;
++ turbine:多个熔断器的聚合监控。
+
+
+
+
+
+## 三、整合 hystrix (以consumer模块为例)
+
+#### 3.1 引入依赖
+
+hystrix的仪表盘功能实际上是从[端点](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-boot/spring-boot-actuator)获取数据,所以需要actuator starter开启端点的相关功能。
+
+```xml
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-hystrix
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-hystrix-dashboard
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+```
+
+#### 3.2 暴露端点
+
+```java
+management:
+ endpoints:
+ web:
+ exposure:
+ # 需要开启hystrix.stream端点的暴露 这样才能获取到监控信息 * 代表开启所有可监控端点
+ include: "*"
+```
+
+#### 3.3 在启动类上添加注解@EnableHystrix和@EnableHystrixDashboard
+
+```java
+@SpringBootApplication
+@EnableDiscoveryClient
+@EnableHystrix
+@EnableHystrixDashboard
+public class ConsumerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ConsumerApplication.class, args);
+ }
+}
+```
+
+#### 3.4 使用 @HystrixCommand 定义失败回退的方法
+
+```java
+@HystrixCommand(fallbackMethod = "queryProductsFail")
+public List queryAllProducts() {
+ ResponseEntity responseEntity = restTemplate.getForEntity("http://producer/products", List.class);
+ List productList = responseEntity.getBody();
+ return productList;
+}
+
+// 如果发送熔断返回空集合,在前端判断处理
+public List queryProductsFail() {
+ return new ArrayList<>();
+}
+```
+
+```html
+
+
+
+ 产品列表
+
+
+产品列表:点击查看详情
+
+
+ <#if (products?size>0) >
+ <#list products as product>
+ -
+ ${product.name}
+
+ #list>
+ <#else>
+ 当前排队人数过多,请之后再购买!
+ #if>
+
+
+
+```
+
+#### 3.5 模拟熔断
+
+这里被调用方采用线程休眠的方式模拟服务超时,Hystrix默认超时时间为2s,调用远程服务时候超过这个时间,会触发熔断。
+
+```java
+public List queryAllProducts() {
+ // hystrix 默认超时是2秒
+ int i = new Random().nextInt(2500);
+ try {
+ Thread.sleep(i);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return productList;
+}
+```
+
+3.5 启动服务,访问http://localhost:8030/sell/products ,多次刷新查看熔断情况
+
+
+
+#### 3.5 启动服务,访问 localhost:8030/hystrix
+
+依次输出http://localhost:8030/actuator/hystrix.stream(监控地址) ,2000(延迟时间),title可以任意填写,进入监控台。
+
+需要注意的是在spring cloud Finchley.SR2,监控地址中都是有/actuator的,因为在spring boot 2.x 的所有端点(包括自定义端点)都是暴露在这个路径下,在启动时候的控制台输出的日志可以查看到所有暴露端点的映射。
+
+**登录页面**:
+
+
+
+**监控页面**:
+
+
+
+**关于各个参数的说明参见[官方wiki](https://github.com/Netflix-Skunkworks/hystrix-dashboard/wiki)提供的图**:
+
+
+
+
+
+
+
+## 四、使用turbine 实现聚合监控
+
+单体监控和聚合监控:
+
+
+
+
+
+#### 4.1 创建turbine模块,导入依赖
+
+```xml
+
+
+ 4.0.0
+
+
+ com.heibaiying.hystrix
+ spring-cloud-hystrx
+ 0.0.1-SNAPSHOT
+
+
+ turbine
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-hystrix
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-hystrix-dashboard
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-turbine
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+```
+
+
+
+#### 4.2 指定注册中心地址和聚合的项目,这里我们监控 consumer,producer 两个项目
+
+```java
+server:
+ port: 8040
+# 指定服务命名
+spring:
+ application:
+ name: turbine
+# 指定注册中心地址
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://localhost:8010/eureka/
+# 指定聚合的项目
+turbine:
+ aggregator:
+ cluster-config: default
+ combine-host-port: true
+ app-config: consumer,producer
+ clusterNameExpression: "'default'"
+```
+
+
+
+#### 4.3 在启动类上添加注解
+
+```java
+@SpringBootApplication
+@EnableDiscoveryClient
+@EnableHystrix
+@EnableHystrixDashboard
+@EnableTurbine
+public class TurbineApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(TurbineApplication.class, args);
+ }
+
+}
+```
+
+
+
+#### 4.4 依次启动eureka、producer、consumer、turbine四个项目
+
+在 localhost:8030/hystrix或者localhost:8030/hystrix(consumer和producer都集成了hystrix) 页面输入http://localhost:8040/turbine.stream,查看断路器聚合信息
+
+
+
+**显示了不同服务单元(consumer,producer)的多个断路器信息:**
+
+
+
+## 五、整合过程中可能出现的问题
+
+#### 5.1 无法访问监控页面
+
+1. 一般是端点链接输入不对,在F版本的spring cloud 中,输入监控的端点链接是 http://localhost:8030/actuator/hystrix.stream ,中间是有/actuator/(之前版本的没有/actuator/)
+
+2. 没有暴露端点链接,暴露端点链接有两种方式,一种是我们在上文中提到的基于配置的方式
+
+ ```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;
+ }
+ ```
+
+ 这两种方式二选一即可,就算是采用代码的方式,还是建议将地址设置为/actuator/hystrix.stream,而不是原来的hystrix.stream,因为turbine默认也是从/actuator/hystrix.stream去获取信息。
+
+#### 5.2 页面一直loading 或者访问端点页面一直出现ping
+
+这种情况是熔断器所在的方法没有被调用,所以没有产生监控数据,不是整合问题,这时候调用一下熔断器所在方法即可。
+
+
diff --git a/spring-cloud/spring-cloud-ribbon/README.md b/spring-cloud/spring-cloud-ribbon/README.md
index 3a2fd7a..41be5aa 100644
--- a/spring-cloud/spring-cloud-ribbon/README.md
+++ b/spring-cloud/spring-cloud-ribbon/README.md
@@ -1,331 +1,325 @@
-# spring-cloud-ribbon
-
## 目录
+# spring-cloud-ribbon
+
+## 目录
一、ribbon 简介
二、项目结构
三、服务提供者的实现
- 3.1 产品服务由`ProductService`提供,并通过`ProducerController`将服务暴露给外部调用。
- 3.2 指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient
四、服务消费者的实现
- 4.1 导入负载均衡需要的依赖
- 4.2 指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient
- 4.3 使用@LoadBalanced配置RestTemplate即可实现客户端负载均衡
- 4.4 使用RestTemplate调用远程服务
五、启动测试
- 5.1 启动一个Eureka服务、三个producer服务(注意区分端口)、和一个消费者服务
- 5.2 访问http://localhost:8080/sell/products 查看负载均衡的调用结果
六、 附1: 关于RestTemplate的说明
6.1 restTemplate 规范
- 6.2 ForEntity()和ForObject的区别
+ 6.2 ForEntity()和ForObject()的区别
七、 附2: 关于ribbon更多负载均衡的策略
7.1 内置的负载均衡的策略如下图
7.2 配置文件指定负载均衡的方式
7.3 代码指定负载均衡的方式
## 正文
-## 一、ribbon 简介
-
-ribbon是Netfix公司开源的负载均衡组件,采用服务端负载均衡的方式,即消费者客户端维护可用的服务列表,并通过负载均衡的方式将请求按照指定的策略分摊给消费者,从而达到负载均衡的方式。
-
-
-
-## 二、项目结构
-
-+ common: 公共的接口和实体类;
-+ consumer: 服务的消费者,采用RestTemplate调用产品服务;
-+ producer:服务的提供者;
-+ eureka: 注册中心,ribbon 从注册中心获取可用的服务列表,是实现负载均衡的基础。这里使用我们在[服务的注册与发现](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-eureka)这个用例中搭建的简单注册中心作为测试即可。
-
-
-
-
-
-## 三、服务提供者的实现
-
-#### 3.1 产品服务由`ProductService`提供,并通过`ProducerController`将服务暴露给外部调用。
-
-
-
-ProductService.java:
-
-```java
-/**
- * @author : heibaiying
- * @description : 产品提供接口实现类
- * 这里为了之后直观的看到负载均衡的结果,我们继承了 ApplicationListener,从 WebServerInitializedEvent 获取服务的端口号,并拼接在产品名称上
- */
-@Service
-public class ProductService implements IProductService, ApplicationListener {
-
- private static List productList = new ArrayList<>();
-
- public Product queryProductById(int id) {
- for (Product product : productList) {
- if (product.getId() == id) {
- return product;
- }
- }
- return null;
- }
-
- public List queryAllProducts() {
- return productList;
- }
-
- @Override
- public void saveProduct(Product product) {
- productList.add(product);
- }
-
- @Override
- public void onApplicationEvent(WebServerInitializedEvent event) {
- int port = event.getWebServer().getPort();
- for (long i = 0; i < 20; i++) {
- productList.add(new Product(i, port + "产品" + i, i / 2 == 0, new Date(), 66.66f * i));
- }
- }
-}
-```
-
-ProducerController.java:
-
-```java
-@RestController
-public class ProducerController {
-
- @Autowired
- private IProductService productService;
-
- @GetMapping("products")
- public List productList() {
- return productService.queryAllProducts();
- }
-
- @GetMapping("product/{id}")
- public Product productDetail(@PathVariable int id) {
- return productService.queryProductById(id);
- }
-
- @PostMapping("product")
- public void save(@RequestBody Product product) {
- productService.saveProduct(product);
- }
-}
-```
-
-#### 3.2 指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient
-
-```java
-server:
- port: 8020
-# 指定服务命名
-spring:
- application:
- name: producer
-# 指定注册中心地址
-eureka:
- client:
- serviceUrl:
- defaultZone: http://localhost:8010/eureka/
-```
-
-```java
-@SpringBootApplication
-@EnableDiscoveryClient
-public class ProducerApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(ProducerApplication.class, args);
- }
-
-}
-
-```
-
-
-
-## 四、服务消费者的实现
-
-
-
-#### 4.1 导入负载均衡需要的依赖
-
-```xml
-
-
- org.springframework.cloud
- spring-cloud-starter-netflix-ribbon
-
-```
-
-#### 4.2 指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient
-
-```java
-server:
- port: 8080
-# 指定服务命名
-spring:
- application:
- name: consumer
-# 指定注册中心地址
-eureka:
- client:
- serviceUrl:
- defaultZone: http://localhost:8010/eureka/
-```
-
-```java
-@SpringBootApplication
-@EnableDiscoveryClient
-public class ConsumerApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(ConsumerApplication.class, args);
- }
-
-}
-```
-
-#### 4.3 使用@LoadBalanced配置RestTemplate即可实现客户端负载均衡
-
-```java
-import org.springframework.cloud.client.loadbalancer.LoadBalanced;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.client.RestTemplate;
-
-@Configuration
-public class RibbonConfig {
-
- @LoadBalanced // 配置客户端负载均衡
- @Bean
- public RestTemplate restTemplate() {
- return new RestTemplate();
- }
-}
-```
-
-#### 4.4 使用RestTemplate调用远程服务
-
-这里我们在调用远程服务的时候,url填写的是服务名+具体接口地址 ,由于我们的同一个服务会存在多个实例,在使用@LoadBalanced配置RestTemplate调用服务时,客户端就会从按照指定的负载均衡的方式将请求分摊到多个实例上。(默认的负载均衡采用的是RoundRobinRule(轮询)的策略,有特殊需求时候可以采用其他内置的策略规则,或者实现IRule来定义自己的负载均衡策略)。
-
-```java
-@Service
-public class ProductService implements IProductService {
-
- @Autowired
- private RestTemplate restTemplate;
-
- public Product queryProductById(int id) {
- ResponseEntity responseEntity = restTemplate.getForEntity("http://producer/product/{1}", Product.class, id);
- return responseEntity.getBody();
- }
-
-
- public List queryAllProducts() {
- ResponseEntity responseEntity = restTemplate.getForEntity("http://producer/products", List.class);
- List productList = responseEntity.getBody();
- return productList;
- }
-
- public void saveProduct(Product product) {
- restTemplate.postForObject("http://producer/product", product, Void.class);
- }
-}
-
-```
-
-
-
-## 五、启动测试
-
-#### 5.1 启动一个Eureka服务、三个producer服务(注意区分端口)、和一个消费者服务
-
-
-
-**服务注册中心:**
-
-
-
-#### 5.2 访问http://localhost:8080/sell/products 查看负载均衡的调用结果
-
-
-
-
-
-## 六、 附1: 关于RestTemplate的说明
-
-#### 6.1 restTemplate 规范
-
-restTemplate 调用对应resultful接口时候,使用的方法应该与接口声明方式(@GetMapping、@PostMapping、@PutMapping、@DeleteMapping)保持一致。请求类型与对应的调用方法如下。
-
-- GET请求(getForObject 、getForEntity)
-- POST请求(postForObject 、postForEntity)
-- PUT请求(put)
-- DELETE请求 (delete)
-
-#### 6.2 ForEntity()和ForObject的区别
-
-- `ForEntity()`发送一个请求,返回的ResponseEntity包含了响应体所映射成的对象
-
-- `ForObject()`发送一个请求,返回的请求体将映射为一个对象
-
-例如:
-
-```java
-ResponseEntity responseEntity = restTemplate.getForEntity("http://producer/product/{1}", Product.class, id);
-Product product = restTemplate.getForObject("http://producer/product/{1}", Product.class, id);
-```
-
-
-
-## 七、 附2: 关于ribbon更多负载均衡的策略
-
-Ribbon内置了多种负载均衡策略,如果有更复杂的需求,可以自己实现IRule。
-
-#### 7.1 内置的负载均衡的策略如下图
-
-
-
-图片来源于博客:[Ribbon负载均衡策略与自定义配置](https://blog.csdn.net/jrn1012/article/details/77837680)
-
-
-
-#### 7.2 配置文件指定负载均衡的方式
-
-要设置`IRule`名为的服务名称`users`,您可以设置以下属性:
-
-```yaml
-users:
- ribbon:
- NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
-```
-
-
-
-#### 7.3 代码指定负载均衡的方式
-
-```java
-@Configuration
-@RibbonClient(name = "custom", configuration = CustomConfiguration.class)
-public class TestConfiguration {
-}
-```
-
-```java
-@Configuration
-public class CustomConfiguration {
-
- @Bean
- public IRule ribbonRule() {
- return new BestAvailableRule();
- }
-}
-```
-
-在使用代码方式的时候需要注意 [官方文档](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).
-
-
-该`CustomConfiguration`类必须是`@Configuration`标注的,但需要注意的它不是在`@ComponentScan`主应用程序上下文。否则,它将由所有`@RibbonClients`共享。如果你使用`@ComponentScan`(或`@SpringBootApplication`),你需要采取一些措施来避免它被扫描到(例如,你可以把它放在一个独立的,非重叠的包,或用`@ComponentScan`时显示扫描指定的包)。
+
+## 一、ribbon 简介
+
+ribbon是Netfix公司开源的负载均衡组件,采用服务端负载均衡的方式,即消费者客户端维护可用的服务列表,并通过负载均衡的方式将请求按照指定的策略分摊给消费者,从而达到负载均衡的方式。
+
+
+
+## 二、项目结构
+
++ common: 公共的接口和实体类;
++ consumer: 服务的消费者,采用RestTemplate调用产品服务;
++ producer:服务的提供者;
++ eureka: 注册中心,ribbon 从注册中心获取可用的服务列表,是实现负载均衡的基础。这里使用我们在[服务的注册与发现](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-eureka)这个用例中搭建的简单注册中心作为测试即可。
+
+
+
+
+
+## 三、服务提供者的实现
+
+#### 3.1 产品服务由`ProductService`提供,并通过`ProducerController`将服务暴露给外部调用。
+
+
+
+ProductService.java:
+
+```java
+/**
+ * @author : heibaiying
+ * @description : 产品提供接口实现类
+ * 这里为了之后直观的看到负载均衡的结果,我们继承了 ApplicationListener,从 WebServerInitializedEvent 获取服务的端口号,并拼接在产品名称上
+ */
+@Service
+public class ProductService implements IProductService, ApplicationListener {
+
+ private static List productList = new ArrayList<>();
+
+ public Product queryProductById(int id) {
+ for (Product product : productList) {
+ if (product.getId() == id) {
+ return product;
+ }
+ }
+ return null;
+ }
+
+ public List queryAllProducts() {
+ return productList;
+ }
+
+ @Override
+ public void saveProduct(Product product) {
+ productList.add(product);
+ }
+
+ @Override
+ public void onApplicationEvent(WebServerInitializedEvent event) {
+ int port = event.getWebServer().getPort();
+ for (long i = 0; i < 20; i++) {
+ productList.add(new Product(i, port + "产品" + i, i / 2 == 0, new Date(), 66.66f * i));
+ }
+ }
+}
+```
+
+ProducerController.java:
+
+```java
+@RestController
+public class ProducerController {
+
+ @Autowired
+ private IProductService productService;
+
+ @GetMapping("products")
+ public List productList() {
+ return productService.queryAllProducts();
+ }
+
+ @GetMapping("product/{id}")
+ public Product productDetail(@PathVariable int id) {
+ return productService.queryProductById(id);
+ }
+
+ @PostMapping("product")
+ public void save(@RequestBody Product product) {
+ productService.saveProduct(product);
+ }
+}
+```
+
+#### 3.2 指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient
+
+```java
+server:
+ port: 8020
+# 指定服务命名
+spring:
+ application:
+ name: producer
+# 指定注册中心地址
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://localhost:8010/eureka/
+```
+
+```java
+@SpringBootApplication
+@EnableDiscoveryClient
+public class ProducerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ProducerApplication.class, args);
+ }
+
+}
+
+```
+
+
+
+## 四、服务消费者的实现
+
+
+
+#### 4.1 导入负载均衡需要的依赖
+
+```xml
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-ribbon
+
+```
+
+#### 4.2 指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient
+
+```java
+server:
+ port: 8080
+# 指定服务命名
+spring:
+ application:
+ name: consumer
+# 指定注册中心地址
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://localhost:8010/eureka/
+```
+
+```java
+@SpringBootApplication
+@EnableDiscoveryClient
+public class ConsumerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ConsumerApplication.class, args);
+ }
+
+}
+```
+
+#### 4.3 使用@LoadBalanced配置RestTemplate即可实现客户端负载均衡
+
+```java
+import org.springframework.cloud.client.loadbalancer.LoadBalanced;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+public class RibbonConfig {
+
+ @LoadBalanced // 配置客户端负载均衡
+ @Bean
+ public RestTemplate restTemplate() {
+ return new RestTemplate();
+ }
+}
+```
+
+#### 4.4 使用RestTemplate调用远程服务
+
+这里我们在调用远程服务的时候,url填写的是服务名+具体接口地址 ,由于我们的同一个服务会存在多个实例,在使用@LoadBalanced配置RestTemplate调用服务时,客户端就会从按照指定的负载均衡的方式将请求分摊到多个实例上。(默认的负载均衡采用的是RoundRobinRule(轮询)的策略,有特殊需求时候可以采用其他内置的策略规则,或者实现IRule来定义自己的负载均衡策略)。
+
+```java
+@Service
+public class ProductService implements IProductService {
+
+ @Autowired
+ private RestTemplate restTemplate;
+
+ public Product queryProductById(int id) {
+ ResponseEntity responseEntity = restTemplate.getForEntity("http://producer/product/{1}", Product.class, id);
+ return responseEntity.getBody();
+ }
+
+
+ public List queryAllProducts() {
+ ResponseEntity responseEntity = restTemplate.getForEntity("http://producer/products", List.class);
+ List productList = responseEntity.getBody();
+ return productList;
+ }
+
+ public void saveProduct(Product product) {
+ restTemplate.postForObject("http://producer/product", product, Void.class);
+ }
+}
+
+```
+
+
+
+## 五、启动测试
+
+#### 5.1 启动一个Eureka服务、三个producer服务(注意区分端口)、和一个消费者服务
+
+
+
+**服务注册中心:**
+
+
+
+#### 5.2 访问http://localhost:8080/sell/products 查看负载均衡的调用结果
+
+
+
+
+
+## 六、 附1: 关于RestTemplate的说明
+
+#### 6.1 restTemplate 规范
+
+restTemplate 调用对应resultful接口时候,使用的方法应该与接口声明方式(@GetMapping、@PostMapping、@PutMapping、@DeleteMapping)保持一致。请求类型与对应的调用方法如下。
+
+- GET请求(getForObject 、getForEntity)
+- POST请求(postForObject 、postForEntity)
+- PUT请求(put)
+- DELETE请求 (delete)
+
+#### 6.2 ForEntity()和ForObject()的区别
+
+- `ForEntity()`发送一个请求,返回的ResponseEntity包含了响应体所映射成的对象
+
+- `ForObject()`发送一个请求,返回的请求体将映射为一个对象
+
+例如:
+
+```java
+ResponseEntity responseEntity = restTemplate.getForEntity("http://producer/product/{1}", Product.class, id);
+Product product = restTemplate.getForObject("http://producer/product/{1}", Product.class, id);
+```
+
+
+
+## 七、 附2: 关于ribbon更多负载均衡的策略
+
+Ribbon内置了多种负载均衡策略,如果有更复杂的需求,可以自己实现IRule。
+
+#### 7.1 内置的负载均衡的策略如下图
+
+
+
+图片来源于博客:[Ribbon负载均衡策略与自定义配置](https://blog.csdn.net/jrn1012/article/details/77837680)
+
+
+
+#### 7.2 配置文件指定负载均衡的方式
+
+要设置`IRule`名为的服务名称`users`,您可以设置以下属性:
+
+```yaml
+users:
+ ribbon:
+ NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
+```
+
+
+
+#### 7.3 代码指定负载均衡的方式
+
+```java
+@Configuration
+@RibbonClient(name = "custom", configuration = CustomConfiguration.class)
+public class TestConfiguration {
+}
+```
+
+```java
+@Configuration
+public class CustomConfiguration {
+
+ @Bean
+ public IRule ribbonRule() {
+ return new BestAvailableRule();
+ }
+}
+```
+
+在使用代码方式的时候需要注意 [官方文档](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).
+
+
+该`CustomConfiguration`类必须是`@Configuration`标注的,但需要注意的它不是在`@ComponentScan`主应用程序上下文。否则,它将由所有`@RibbonClients`共享。如果你使用`@ComponentScan`(或`@SpringBootApplication`),你需要采取一些措施来避免它被扫描到(例如,你可以把它放在一个独立的,非重叠的包,或用`@ComponentScan`时显示扫描指定的包)。
diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/README.md b/spring-cloud/spring-cloud-sleuth-zipkin/README.md
index 223dfb5..28221f4 100644
--- a/spring-cloud/spring-cloud-sleuth-zipkin/README.md
+++ b/spring-cloud/spring-cloud-sleuth-zipkin/README.md
@@ -9,6 +9,7 @@
五、启动项目
## 正文
+
## 一、简介
在微服务架构中,几乎每一个前端的请求都会经过多个服务单元协调来提供服务,形成复杂的服务调用链路。当服务发生问题时候,很难知道问题来源于链路的哪一个环节,这时候就需要进行链路追踪。
diff --git a/spring-cloud/spring-cloud-zuul/README.md b/spring-cloud/spring-cloud-zuul/README.md
index 5dafd11..dad3147 100644
--- a/spring-cloud/spring-cloud-zuul/README.md
+++ b/spring-cloud/spring-cloud-zuul/README.md
@@ -1,408 +1,401 @@
-# spring-cloud-zuul
-
## 目录
+# spring-cloud-zuul
+
+## 目录
一、zuul简介
1.1 API 网关
1.2 zuul
二、项目结构
三、构建api 网关 zuul
- 3.1 引入依赖
- 3.2 在启动类上添加注解@EnableZuulProxy和@EnableDiscoveryClient
- 3.3 指定注册中心、配置网关的路由规则
- 3.4 启动eureka、producer、consumer、zuul服务,访问 localhost:8090/consumer/sell/product
四、错误熔断
- 4.1 zuul 默认整合了 hystrix ,不用导入其他额外依赖
- 4.2 创建 CustomZuulFallbackProvider并实现FallbackProvider 接口,同时用@Component声明为spring 组件,即可实现熔断时候的回退服务
五、zuul 过滤器
六、负载均衡
- zuul 默认集成了ribbon 实现了负载均衡。只要启动多个实例即可查看到负载均衡的效果。
- 这里我们直接在idea 中启动多个实例来测试:
- 负载均衡测试结果:
七、附:关于版本问题可能导致的 zuul 启动失败
## 正文
-## 一、zuul简介
-
-### 1.1 API 网关
-
-api 网关是整个微服务系统的门面,所有的外部访问需要通过网关进行调度和过滤。它实现了请求转发、负载均衡、校验过滤、错误熔断、服务聚合等功能。
-
-下图是直观的显示api Gateway 在微服务网关中的作用(图片引用自spring boot 官网)。
-
-
-
-### 1.2 zuul
-
-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的整合。
-
-+ common: 公共的接口和实体类;
-+ consumer: 服务的消费者,采用feign调用产品服务;
-+ producer:服务的提供者;
-+ eureka: 注册中心;
-+ zuul: api网关。
-
-聚合项目目录如下:
-
-
-
-zuul 项目目录如下:
-
-
-
-
-
-## 三、构建api 网关 zuul
-
-#### 3.1 引入依赖
-
-主要的依赖是 spring-cloud-starter-netflix-zuul
-
-```xml
-
-
- 4.0.0
-
-
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.0.8.RELEASE
-
-
-
- zuul
-
-
- 1.8
- Finchley.SR2
-
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-freemarker
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
-
- org.springframework.cloud
- spring-cloud-starter-netflix-eureka-client
-
-
-
- org.springframework.cloud
- spring-cloud-starter-netflix-zuul
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
-
-
-
- org.springframework.cloud
- spring-cloud-dependencies
- ${spring-cloud.version}
- pom
- import
-
-
-
-
-
-```
-
-
-
-#### 3.2 在启动类上添加注解@EnableZuulProxy和@EnableDiscoveryClient
-
-@EnableZuulProxy会自动设置Zuul服务器端点并在其中开启一些反向代理过滤器,以便将请求转发到后端服务器。
-
-```java
-@SpringBootApplication
-@EnableZuulProxy
-@EnableDiscoveryClient
-public class ZuulApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(ZuulApplication.class, args);
- }
-
-}
-```
-
-
-
-#### 3.3 指定注册中心、配置网关的路由规则
-
-zuul 需要指定注册中心的地址,zuul 会从eureka获取其他微服务的实例信息,然后按照指定的路由规则进行请求转发。
-
-```yaml
-server:
- port: 8090
-# 指定服务命名
-spring:
- application:
- name: zuul
-# 指定注册中心地址
-eureka:
- client:
- serviceUrl:
- defaultZone: http://localhost:8010/eureka/
-# 网关的路由
-zuul:
- routes:
- xxxx: #这个地方的值是可以任意的字符串
- path: /producer/**
- serviceId: producer
- consumer:
- path: /consumer/**
- serviceId: consumer
-```
-
-
-
-#### 3.4 启动eureka、producer、consumer、zuul服务,访问 localhost:8090/consumer/sell/product
-
-
-
-
-
-## 四、错误熔断
-
-#### 4.1 zuul 默认整合了 hystrix ,不用导入其他额外依赖
-
-
-
-#### 4.2 创建 CustomZuulFallbackProvider并实现FallbackProvider 接口,同时用@Component声明为spring 组件,即可实现熔断时候的回退服务
-
-```java
-/**
- * @author : heibaiying
- * @description : zuul 的熔断器
- */
-@Component
-public class CustomZuulFallbackProvider implements FallbackProvider {
-
- /*
- * 定义熔断将用于哪些路由的服务
- */
- @Override
- public String getRoute() {
- return "consumer";
- }
-
- @Override
- public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
- return new ClientHttpResponse() {
-
- /**
- * 返回响应的HTTP状态代码
- */
- @Override
- public HttpStatus getStatusCode() throws IOException {
- return HttpStatus.SERVICE_UNAVAILABLE;
- }
-
- /**
- * 返回HTTP状态代码
- */
- @Override
- public int getRawStatusCode() throws IOException {
- return HttpStatus.SERVICE_UNAVAILABLE.value();
- }
-
- /**
- * 返回响应的HTTP状态文本
- */
- @Override
- public String getStatusText() throws IOException {
- return HttpStatus.SERVICE_UNAVAILABLE.getReasonPhrase();
- }
-
- @Override
- public void close() {
-
- }
-
- /**
- * 将消息正文作为输入流返回
- */
- @Override
- public InputStream getBody() throws IOException {
- return new ByteArrayInputStream("商城崩溃了,请稍后重试!".getBytes());
- }
-
- /**
- * 将消息正文作为输入流返回
- */
- @Override
- public HttpHeaders getHeaders() {
- HttpHeaders httpHeaders = new HttpHeaders();
- httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
- return httpHeaders;
- }
- };
- }
-}
-```
-
-正确返回了内容、同时返回的http状态码也和我们设置的一样。
-
-
-
-
-
-## 五、zuul 过滤器
-
-创建自定义过滤器继承自CustomZuulFilter,当我们访问网关的时候,如果判断session 中没有对应的 code,则跳转到我们自定义的登录页面。
-
-```java
-/**
- * @author : heibaiying
- * @description : 自定义filter过滤器
- */
-
-@Component
-public class CustomZuulFilter extends ZuulFilter {
-
- /**
- * 返回过滤器的类型
- */
- @Override
- public String filterType() {
- return FilterConstants.PRE_TYPE;
- }
-
- /**
- * 返回过滤器的优先级顺序
- */
- @Override
- public int filterOrder() {
- return 0;
- }
-
- /**
- * 从此方法返回“true”意味着应该调用下面的 run()方法
- */
- @Override
- public boolean shouldFilter() {
- return true;
- }
-
- /**
- * ZuulFilter的核心校验方法
- */
- @Override
- public Object run() throws ZuulException {
- RequestContext currentContext = RequestContext.getCurrentContext();
- HttpServletRequest request = currentContext.getRequest();
- String code = (String)request.getSession().getAttribute("code");
- if (StringUtils.isEmpty(code)){
- // 设置值为false 不将请求转发到对应的服务上
- currentContext.setSendZuulResponse(false);
- // 设置返回的状态码
- currentContext.setResponseStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION.value());
- HttpServletResponse response = currentContext.getResponse();
- try {
- // 跳转到登录页面
- response.sendRedirect("/index");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return null;
- }
-}
-```
-
-index.ftl:
-
-```html
-
-
-
- Title
-
-
-
-
-
-```
-
-
-
-## 六、负载均衡
-
-#### zuul 默认集成了ribbon 实现了负载均衡。只要启动多个实例即可查看到负载均衡的效果。
-
-
-
-#### 这里我们直接在idea 中启动多个实例来测试:
-
-
-
-#### 负载均衡测试结果:
-
-
-
-
-
-
-
-
-
-## 七、附:关于版本问题可能导致的 zuul 启动失败
-
-如果出现以下错误导致启动失败,是 spring boot 版本不兼容导致的错误,Finchley SR2版本 spring cloud 中的 zuul 和 spring boot 2.1.x 版本存在不兼容。如果出现这个问题,则将 spring boot 将至 2.0.x 的版本即可,用例中采用的是 2.0.8 版本。在实际的开发中应该严格遵循spring 官方的版本依赖说明。
-
-```java
-APPLICATION FAILED TO START
-
----
-
-Description:
-
-The bean 'counterFactory', defined in class path resource [org/springframework/cloud/netflix/zuul/ZuulServerAutoConfiguration$ZuulCounterFactoryConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/cloud/netflix/zuul/ZuulServerAutoConfiguration$ZuulMetricsConfiguration.class] and overriding is disabled.
-
-Action:
-
-Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
-
-```
-
-**spring cloud 版本说明**:
-
-| Release Train | Boot Version |
-| ------------- | ------------ |
-| Greenwich | 2.1.x |
-| Finchley | 2.0.x |
-| Edgware | 1.5.x |
-| Dalston | 1.5.x |
-
-更多组件的版本说明可以在[spring cloud overview](https://spring.io/projects/spring-cloud#overview) 页面查看。
+
+## 一、zuul简介
+
+### 1.1 API 网关
+
+api 网关是整个微服务系统的门面,所有的外部访问需要通过网关进行调度和过滤。它实现了请求转发、负载均衡、校验过滤、错误熔断、服务聚合等功能。
+
+下图是直观的显示api Gateway 在微服务网关中的作用(图片引用自spring boot 官网)。
+
+
+
+### 1.2 zuul
+
+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的整合。
+
++ common: 公共的接口和实体类;
++ consumer: 服务的消费者,采用feign调用产品服务;
++ producer:服务的提供者;
++ eureka: 注册中心;
++ zuul: api网关。
+
+聚合项目目录如下:
+
+
+
+zuul 项目目录如下:
+
+
+
+
+
+## 三、构建api 网关 zuul
+
+#### 3.1 引入依赖
+
+主要的依赖是 spring-cloud-starter-netflix-zuul
+
+```xml
+
+
+ 4.0.0
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.8.RELEASE
+
+
+
+ zuul
+
+
+ 1.8
+ Finchley.SR2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-freemarker
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-zuul
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+```
+
+
+
+#### 3.2 在启动类上添加注解@EnableZuulProxy和@EnableDiscoveryClient
+
+@EnableZuulProxy会自动设置Zuul服务器端点并在其中开启一些反向代理过滤器,以便将请求转发到后端服务器。
+
+```java
+@SpringBootApplication
+@EnableZuulProxy
+@EnableDiscoveryClient
+public class ZuulApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ZuulApplication.class, args);
+ }
+
+}
+```
+
+
+
+#### 3.3 指定注册中心、配置网关的路由规则
+
+zuul 需要指定注册中心的地址,zuul 会从eureka获取其他微服务的实例信息,然后按照指定的路由规则进行请求转发。
+
+```yaml
+server:
+ port: 8090
+# 指定服务命名
+spring:
+ application:
+ name: zuul
+# 指定注册中心地址
+eureka:
+ client:
+ serviceUrl:
+ defaultZone: http://localhost:8010/eureka/
+# 网关的路由
+zuul:
+ routes:
+ xxxx: #这个地方的值是可以任意的字符串
+ path: /producer/**
+ serviceId: producer
+ consumer:
+ path: /consumer/**
+ serviceId: consumer
+```
+
+
+
+#### 3.4 启动eureka、producer、consumer、zuul服务,访问 localhost:8090/consumer/sell/product
+
+
+
+
+
+## 四、错误熔断
+
+#### 4.1 zuul 默认整合了 hystrix ,不用导入其他额外依赖
+
+
+
+#### 4.2 创建 CustomZuulFallbackProvider并实现FallbackProvider 接口,同时用@Component声明为spring 组件,即可实现熔断时候的回退服务
+
+```java
+/**
+ * @author : heibaiying
+ * @description : zuul 的熔断器
+ */
+@Component
+public class CustomZuulFallbackProvider implements FallbackProvider {
+
+ /*
+ * 定义熔断将用于哪些路由的服务
+ */
+ @Override
+ public String getRoute() {
+ return "consumer";
+ }
+
+ @Override
+ public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
+ return new ClientHttpResponse() {
+
+ /**
+ * 返回响应的HTTP状态代码
+ */
+ @Override
+ public HttpStatus getStatusCode() throws IOException {
+ return HttpStatus.SERVICE_UNAVAILABLE;
+ }
+
+ /**
+ * 返回HTTP状态代码
+ */
+ @Override
+ public int getRawStatusCode() throws IOException {
+ return HttpStatus.SERVICE_UNAVAILABLE.value();
+ }
+
+ /**
+ * 返回响应的HTTP状态文本
+ */
+ @Override
+ public String getStatusText() throws IOException {
+ return HttpStatus.SERVICE_UNAVAILABLE.getReasonPhrase();
+ }
+
+ @Override
+ public void close() {
+
+ }
+
+ /**
+ * 将消息正文作为输入流返回
+ */
+ @Override
+ public InputStream getBody() throws IOException {
+ return new ByteArrayInputStream("商城崩溃了,请稍后重试!".getBytes());
+ }
+
+ /**
+ * 将消息正文作为输入流返回
+ */
+ @Override
+ public HttpHeaders getHeaders() {
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
+ return httpHeaders;
+ }
+ };
+ }
+}
+```
+
+正确返回了内容、同时返回的http状态码也和我们设置的一样。
+
+
+
+
+
+## 五、zuul 过滤器
+
+创建自定义过滤器继承自CustomZuulFilter,当我们访问网关的时候,如果判断session 中没有对应的 code,则跳转到我们自定义的登录页面。
+
+```java
+/**
+ * @author : heibaiying
+ * @description : 自定义filter过滤器
+ */
+
+@Component
+public class CustomZuulFilter extends ZuulFilter {
+
+ /**
+ * 返回过滤器的类型
+ */
+ @Override
+ public String filterType() {
+ return FilterConstants.PRE_TYPE;
+ }
+
+ /**
+ * 返回过滤器的优先级顺序
+ */
+ @Override
+ public int filterOrder() {
+ return 0;
+ }
+
+ /**
+ * 从此方法返回“true”意味着应该调用下面的 run()方法
+ */
+ @Override
+ public boolean shouldFilter() {
+ return true;
+ }
+
+ /**
+ * ZuulFilter的核心校验方法
+ */
+ @Override
+ public Object run() throws ZuulException {
+ RequestContext currentContext = RequestContext.getCurrentContext();
+ HttpServletRequest request = currentContext.getRequest();
+ String code = (String)request.getSession().getAttribute("code");
+ if (StringUtils.isEmpty(code)){
+ // 设置值为false 不将请求转发到对应的服务上
+ currentContext.setSendZuulResponse(false);
+ // 设置返回的状态码
+ currentContext.setResponseStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION.value());
+ HttpServletResponse response = currentContext.getResponse();
+ try {
+ // 跳转到登录页面
+ response.sendRedirect("/index");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+}
+```
+
+index.ftl:
+
+```html
+
+
+
+ Title
+
+
+
+
+
+```
+
+
+
+## 六、负载均衡
+
+#### zuul 默认集成了ribbon 实现了负载均衡。只要启动多个实例即可查看到负载均衡的效果。
+
+
+
+#### 这里我们直接在idea 中启动多个实例来测试:
+
+
+
+#### 负载均衡测试结果:
+
+
+
+
+
+
+
+
+
+## 七、附:关于版本问题可能导致的 zuul 启动失败
+
+如果出现以下错误导致启动失败,是 spring boot 版本不兼容导致的错误,Finchley SR2版本 spring cloud 中的 zuul 和 spring boot 2.1.x 版本存在不兼容。如果出现这个问题,则将 spring boot 将至 2.0.x 的版本即可,用例中采用的是 2.0.8 版本。在实际的开发中应该严格遵循spring 官方的版本依赖说明。
+
+```java
+APPLICATION FAILED TO START
+
+---
+
+Description:
+
+The bean 'counterFactory', defined in class path resource [org/springframework/cloud/netflix/zuul/ZuulServerAutoConfiguration$ZuulCounterFactoryConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/cloud/netflix/zuul/ZuulServerAutoConfiguration$ZuulMetricsConfiguration.class] and overriding is disabled.
+
+Action:
+
+Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
+
+```
+
+**spring cloud 版本说明**:
+
+| Release Train | Boot Version |
+| ------------- | ------------ |
+| Greenwich | 2.1.x |
+| Finchley | 2.0.x |
+| Edgware | 1.5.x |
+| Dalston | 1.5.x |
+
+更多组件的版本说明可以在[spring cloud overview](https://spring.io/projects/spring-cloud#overview) 页面查看。