实战项目代码:SpringCloud_Test_GitHub
上一章:(二)SpringCloud 服务发现Netflix Eureka 和 服务调用Netflix Feign
在该章我们介绍剩余的SpringCloud组件
1.熔断器——Netflix Hystrix
在第一章我们已经大致说了一下熔断器的作用——防止服务器雪崩
那么现在我们就介绍一下Hystrix熔断器,Hystrix 能使你的系统在出现依赖服务失效的时候,通过隔离系统所依赖的服务,防止服务级联失败,同时提供失败回退机制,更优雅地应对失效,并使你的系统能更快地
从异常中恢复。
工作模式:
1.1 快速入门
模拟情况:我们在上章中使用Teacher服务调用了Student服务,如果Student服务挂了,我们再次使用Teacher服务调用Student服务,就会失败。
关闭Student服务,使用postman发送请求给http://localhost:9002/teacher/student/1
{
"timestamp": "2019-08-03T06:43:43.280+0000",
"status": 500,
"error": "Internal Server Error",
"message": "connect timed out executing GET http://student/student/1",
"path": "/teacher/student/1"
}
这不仅消耗时间,而且返回的消息十分不友好,下面我们来使用熔断器
Feign 本身支持Hystrix,不需要额外引入依赖。
- 在配置文件中打开Feign
#开启熔断器
feign:
hystrix:
enabled: true
- 创建StudentClient的接口实现类StudentClientImpl,com.springcloud.teacher.client.impl.StudentClientImpl
@Component
public class StudentClientImpl implements StudentClient {
@Override
public Result findById(int studentid) {
return new Result("熔断器触发了");
}
}
- 修改StudentClient接口的注解
@FeignClient(value = "student",fallback = StudentClientImpl.class)
- 重新启动Teacher服务,再次使用postman测试,返回如下消息
{
"message": "熔断器触发了",
"data": null
}
- 我们在不重启Teacher服务的情况下,启动Student服务,再次使用postman测试,返回如下消息
{
"message": "查询成功",
"data": {
"id": 1,
"name": "小明",
"age": 10
}
}
也就是说Hystrix会判断Student服务是否在运行,如果在运行则走Student服务,如果没有运行则走本地的方法,这是一个动态的过程,因为他不用Teacher服务重新编译启动,非常智能。
2.服务网关——Netflix Zuul
Zuul就像一个总管,他管理则有关的服务,只向外暴露一个接口,消费者通过这个接口可以访问所有他管理的服务
Zuul组件的核心是一系列的过滤器,这些过滤器可以完成以下功能:
- 身份认证和安全: 识别每一个资源的验证要求,并拒绝那些不符的请求
- 动态路由:动态将请求路由到不同后端集群
- 压力测试:逐渐增加指向集群的流量,以了解性能
- 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求
- 静态响应处理:边缘位置进行响应,避免转发到内部集群
- 多区域弹性:跨域AWS Region进行请求路由,旨在实现ELB(ElasticLoad Balancing)使用多样化
当然你不用了解上面所有的功能,你只要知道zuul有路由、过滤的作用就行了。
2.1 快速入门
- 创建manager子工程
- 向子工程中导入坐标
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
- 编写配置信息application.yml
server:
port: 9011
spring:
application:
name: manager
eureka:
client:
serviceUrl: #Eureka客户端与Eureka服务端进行交互地址
defaultZone: http://127.0.0.1:9010/eureka/
instance:
prefer-ip-address: true
zuul:
routes:
student: #线路名称
path: /student/** #线路url配置规则
serviceId: student #调用服务的ID
teacher:
path: /teacher/**
serviceId: teacher
- 编写ManagerApplication启动类,com.springcloud.manager.ManagerApplication
@SpringBootApplication
@EnableZuulProxy //启动Zull代理
public class ManagerApplication {
public static void main(String[] args) {
SpringApplication.run(ManagerApplication.class,args);
}
}
- 编写ManagerFiler过滤器com.springcloud.manager.Filer.ManagerFiler
@Component
public class ManagerFiler extends ZuulFilter {
//设置是在请求前(pre)执行过滤器还是请求后(post)
@Override
public String filterType() {
return "pre";
}
//有多个过滤器时的执行顺序,数值越小越先执行
@Override
public int filterOrder() {
return 0;
}
//设置该过滤器是否可用
@Override
public boolean shouldFilter() {
return true;
}
//具体逻辑,返回object即为放行(null也是object类型)
@Override
public Object run() throws ZuulException {
//终止运行方法
// RequestContext requestContext = RequestContext.getCurrentContext();
// requestContext.setSendZuulResponse(false);
System.out.println("进过了过滤器.....");
return null;
}
}
- 启动Zuul服务,需要重启Student服务和Teacher服务,使用postman进行测试http://localhost:9011/teacher/teacher/student/1 第一个teacher是告诉zuul请求需要访问的服务名
注:zuul转发是不会携带消费者发送过来的头信息,需要自己手动在run()方法中转发,requestContext可以获得request,使用request获取头信息中的信息,使用requestContext.addZuulRequestHeader()设置转发头信息。
3.分布式配置——Spring Cloud Config
当我们的服务越来越多的时候,配置文件的管理会非常麻烦,因为代码一般上线不会改变,但是配置信息是有可能会改变的,所有我们需要将配置文件集中起来统一管理。
在Spring Cloud中,有分布式配置中心组件spring cloudconfig ,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。在spring cloud config 组件中,分两个角色,一是config server,二是config client。
Config Server是一个可横向扩展、集中式的配置服务器,它用于集中管理应用程序各个环境下的配置,默认使用Git存储配置文件内容,也可以使用SVN存储,或者是本地文件存储。
Config Client是Config Server的客户端,用于操作存储在Config Server中的配置内容。微服务在启动时会请求Config Server获取配置文件的内容,请求到后再启动容器。
本次我们使用“码云”来作为远端Git 存放配置信息
3.1 上次服务配置信息
- 注册码云帐号
- 创建仓库
- 将Student中application.yml复制出来更名为student-test.yml,上传到刚刚创建的仓库(这里我只做student服务的,其他服务请自行修改)
文件命名规则:
{application}-{profile}.yml或{application}-{profile}.properties
application为应用名称 profile指的开发环境(用于区分开发环境,测试环境、生产环境
等)
4.复制仓库地址
3.2 配置中心服务端
- 创建子工程config,导入坐标
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
- 创建配置文件application.yml
server:
port: 12000
spring:
application:
name: config
cloud:
config:
server:
git:
uri: https://gitee.com/dreamylois/springcloud_test.git #填写刚刚复制的仓库地址
- 创建启动类com.springcloud.config.ConfigApplication
@SpringBootApplication
@EnableConfigServer //开启配置服务
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class,args);
}
}
- 启动服务,在浏览器中输入http://localhost:12000/student-test.yml,可看见该配置文件的信息
3.3 配置客户端
- 向student项目中pom添加坐标
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
- 删除student项目中的application.yml配置文件,创建bootstrap.yml(名称固定,不能修改)
spring:
cloud:
config:
name: student
profile: test
label: master
uri: http://localhost:12000
name:远端配置文件名称前半段,profile:远端配置文件名称后半段,uri:config服务地址
- 重启Student服务,使用postman发送请求http://localhost:9001/student/1,返回信息正常
4.消息总线——Spring Cloud Bus
我们使用Spring Cloud Config将配置信息放在了远端git上面,但是我们修改git上的配置信息是不会影响到已经在运行的服务,只有重启才能改变配置,而重启这件事情是非常麻烦的事情。所有我们希望能够修改git上面的配置信息来自动更新已经运行的服务,那么我们的Spring Cloud Bus就该登场了。
4.1 配置服务端
使用Bus需要rabbitMQ消息中间件,如果没有安装可以参考我博客中相关文章
- 向config项目的pom中添加坐标
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
- 修改config项目的配置文件application.yml,rabbitmq需要在spring中
rabbitmq:
host: 127.0.0.1
management: # 暴露触发消息总线的地址
endpoints:
web:
exposure:
include: "bus-refresh"
4.2 配置客户端
这里我们还是用Student服务为例
- 修改student项目中的pom,添加如下坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
- 修改码云上的student-test.yml文件,添加如下配置信息,rabbitmq还是要在spring中
rabbitmq:
host: 127.0.0.1
4.3 测试
- 依次重启eureka、config和student服务
- 创建另一个数据库和表,建表语句如下
create database `springcloudtest1`;
use `springcloudtest1`;
drop table if exists `tb_student`;
create table `tb_student`(
`id` int PRIMARY KEY AUTO_INCREMENT ,
`name`varchar(100) DEFAULT NULL COMMENT '姓名',
`age`int DEFAULT 0 COMMENT '年龄'
);
insert into `tb_student`(`name`,`age`) values('测试信息111',10);
insert into `tb_student`(`name`,`age`) values('测试信息222',12);
- 使用postman发送请求http://localhost:9001/student/,返回如下信息
{
"message": "查询成功",
"data": [
{
"id": 1,
"name": "小明",
"age": 10
},
{
"id": 2,
"name": "小王",
"age": 12
}
]
}
- 修改码云上student的配置信息,将数据库的url改为如下,访问springcloudtest1数据库
url: jdbc:mysql://127.0.0.1:3306/springcloudtest1?characterEncoding=UTF8
- 重点:使用postman访问“http://127.0.0.1:12000/actuator/bus-refresh” 访问方式:post,返回消息空白即为成功。
- 再次使用postman访问http://localhost:9001/student/,返回信息如下
{
"message": "查询成功",
"data": [
{
"id": 1,
"name": "测试信息111",
"age": 10
},
{
"id": 2,
"name": "测试信息222",
"age": 12
}
]
}
4.4 访问自定义配置信息
上面我们使用的自动更新只会自动更新框架内的信息,如果我们在配置文件中写了一些自己的字段,是不会进行自动更新的。
- 向码云student配置信息添加如下内容
message: 11111
- 修改StudentController中相关内容
@Value("${message}") //获取配置文件中的信息
private String message;
@RequestMapping(method = RequestMethod.GET)
public Result findAll(){
System.out.println(message); //打印信息
return new Result("查询成功",studentService.findAll());
}
- 重启Student服务,使用postman发送请求http://localhost:9001/student/
- 修改码云中的student配置信息中的message为22222
- 使用postman发送请求更新配置信息,再次向Student发送请求http://localhost:9001/student/
- 观察控制台输出,发现两次输出都是“11111”,表示并没有自动更新
如何解决这个问题呢? - 我们只需要在StudentController类上加上注解@RefreshScope即可
- 重启Student服务,向服务发送请求,控制台打印为22222
- 更新码云上的配置message为11111,使用postman发送更新配置信息请求
- 再次向Student服务发送请求,控制台打印11111
上一章:(二)SpringCloud 服务发现Netflix Eureka 和 服务调用Netflix Feign
相关内容:
(一)初见SpringCloud、主要框架简介、与SpringBoot版本对应关系,实战环境搭建
(二)SpringCloud 服务发现Netflix Eureka 和 服务调用Netflix Feign
(三)SpringCloud 熔断器Netflix Hystrix、服务网关Netflix Zuul、分布式配置Spring Cloud Config、消息总线Spring Cloud Bus
RabbitMQ简单入门教程(安装及工作模式介绍)图文教学通俗易懂
作者编写不易,转载请注明我的博客,如果觉得写的不错的话,请随手点个赞,谢谢!!!
作者编写不易,转载请注明我的博客,如果觉得写的不错的话,请随手点个赞,谢谢!!!
作者编写不易,转载请注明我的博客,如果觉得写的不错的话,请随手点个赞,谢谢!!!