1. 今日内容
1.Feign
远程调用
熔断器支持
日志配置
2.Gateway--->nginx
网关搭建
网关路由
动态路由
路由前缀
过滤器
3.Config配置中心
搭建配置中心从gitee读取配置文件
改造用户服务将配置提取至配置中心
4.Bus消息总线
docker安装rabbitmq
使用消息总线完成服务配置的的批量更新
一、Feign
介绍:Feign是一个http请求的轻量级别的框架,在cloud中又有“伪装”。
1. 远程调用
步骤:
- 创建consumer-service-feign模块
- web/lombok/eureka-client/openfeign
- 在启动类添加
- eurekaclient注解
- 开启feign支持
- 编写配置文件
- 复制consumer-service配置文件,建议修服务的应用名称
- 编写controller、service接口完成调用
- 测试
过程:
-
启动类注解
@SpringBootApplication @EnableEurekaClient //注册到注册中心 @EnableFeignClients //开启feign支持 public class ConsumerServiceFeignApplication { public static void main(String[] args) { SpringApplication.run(ConsumerServiceFeignApplication.class, args); } }
-
业务代码
@RestController @RequestMapping("consumer") public class ConsumerController { @Autowired private ConsumerService consumerService; @GetMapping("findUserById/{id}") public User findUserById(@PathVariable Integer id){ return consumerService.findUserById(id); } } @FeignClient("user-service") public interface ConsumerService { /** * String url = "http://user-service/user/findUserById/" + id; * 注意事项: * 1.feign在使用PathVariable注解时必须显示的声明参数,否则异常 */ @GetMapping("user/findUserById/{id}") User findUserById(@PathVariable("id") Integer id); }
-
在测试的过程中发现feign具备了ribbon的功能
2. 熔断支持
步骤:
- 在配置文件中开启熔断器支持
- 编写service的实现类
过程:
-
配置文件开启支持
#开启熔断器支持 feign: hystrix: enabled: true
-
实现类
@Component public class ConsumerServiceImpl implements ConsumerService { /* 服务降级方法 */ @Override public User findUserById(Integer id) { User user = new User(); user.setId(id); user.setNote("服务繁忙,请您稍后再试..."); return user; } }
-
在service中声明服务降级的类字节码
@FeignClient(value = "user-service",fallback = ConsumerServiceImpl.class) public interface ConsumerService { /** * String url = "http://user-service/user/findUserById/" + id; * 注意事项: * 1.feign在使用PathVariable注解时必须显示的声明参数,否则异常 */ @GetMapping("user/findUserById/{id}") User findUserById(@PathVariable("id") Integer id); }
3. 日志配置
步骤:
- 在配置文件中声明日志级别(info/debug/error)
- 编写feign日志配置类
- 在service中配置feign日志配置类的class字节码(经测试,可以不配置也会生效)
过程:
-
配置文件声明日志级别
#日志级别配置 logging: level: com.itheima: debug
-
feign配置类
@Configuration //声明是一个配置类 public class FeignLogConfig { /* logger注意导包---》 import feign.Logger; */ @Bean public Logger.Level configLog(){ return Logger.Level.FULL; } }
二、Gateway
介绍:网关系统,路由(负载)+鉴权。是用于替换zuul(网关),gateway是cloud自己全新的组件。
1. 网关搭建
步骤:
- 创建gateway-service服务
- eureka-client
- gateway
- 配置文件
- 复制配置文件—》修改应用名称
- 在启动类添加注解
- eurekaclient注解
过程:
-
配置文件
server: port: 10010 spring: application: name: gateway-server eureka: client: service-url: defaultZone: http://localhost:8761/eureka
-
启动类
@SpringBootApplication @EnableEurekaClient public class GatewayServerApplication { public static void main(String[] args) { SpringApplication.run(GatewayServerApplication.class, args); } }
-
注意事项:
- 千万不要选择web依赖,gateway启动时使用的是webful。
2. 网关路由
-
配置文件
server: port: 10010 spring: application: name: gateway-server cloud: gateway: routes: - id: consumer-service-feign-route uri: http://localhost:8081 predicates: - Path=/** eureka: client: service-url: defaultZone: http://localhost:8761/eureka
存在问题uri硬编码需要写活------》动态。
3. 动态路由
步骤:
-
创建两个消费者的启动类
-
修改网关配置文件
server: port: 10010 spring: application: name: gateway-server cloud: gateway: routes: - id: consumer-service-feign-route #动态路由通过lb协议可以根据服务的应用名称将服务列表从注册中心获取到本地,然后通过ribbon进行负载 uri: lb://consumer-service-feign #http://localhost:8081 predicates: - Path=/** eureka: client: service-url: defaultZone: http://localhost:8761/eureka
4. 路由前缀
-
添加前缀 + 去除前缀
server: port: 10010 spring: application: name: gateway-server cloud: gateway: routes: - id: consumer-service-feign-route #动态路由通过lb协议可以根据服务的应用名称将服务列表从注册中心获取到本地,然后通过ribbon进行负载 uri: lb://consumer-service-feign #http://localhost:8081 predicates: - Path=/** filters: #添加前缀 - PrefixPath=/consumer #去除前缀 - StripPrefix=1 eureka: client: service-url: defaultZone: http://localhost:8761/eureka
配置 请求地址 最终地址 PrefixPath=/consumer http://localhost:10010/consumer/findUserById/2 http://localhost:8081/consumer/consumer/findUserById/2 PrefixPath=/consumer http://localhost:10010/findUserById/2 http://localhost:8081/consumer/findUserById/2 PrefixPath=/consumer/abc http://localhost:10010/findUserById/2 http://localhost:8081/consumer/abc/findUserById/2 StripPrefix=1 http://localhost:10010/consumer/findUserById/2 http://localhost:8081/findUserById/2 StripPrefix=1 http://localhost:10010/consumer/consumer/findUserById/2 http://localhost:8081/consumer/findUserById/2 StripPrefix=2 http://localhost:10010/consumer/consumer/findUserById/2 http://localhost:8081/findUserById/2
5. 过滤器
server:
port: 10010
spring:
application:
name: gateway-server
cloud:
gateway:
routes:
- id: consumer-service-feign-route
#动态路由通过lb协议可以根据服务的应用名称将服务列表从注册中心获取到本地,然后通过ribbon进行负载
uri: lb://consumer-service-feign #http://localhost:8081
predicates:
- Path=/**
filters:
#添加前缀
- PrefixPath=/consumer
#去除前缀
- StripPrefix=1
#全局过滤器添加响应头
default-filters:
- AddResponseHeader=i-love,itheima
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
6. 自定义过滤器
需求:
判断用户是否有登录?通过token令牌? 从请求数据中获取token参数,判断是否为空?
步骤:
- 创建类实现全局过滤器,Ordered接口
- 重写filter方法
- 获取请求对象
- 从请求对象中获取请求参数token
- 对token进行判空校验
- 如果为空拦截
- 如果不为空放行
- order方法
- 过滤器优先级别—》数值越小优先级别越高
- 重写filter方法
- 返回
过程:
-
@Component public class MyFilter implements GlobalFilter,Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { //- 获取请求对象 ServerHttpRequest request = exchange.getRequest(); //- 从请求对象中获取请求参数token String token = request.getQueryParams().getFirst("token"); //- 对token进行判空校验 if(StringUtils.isEmpty(token)){ //token为空 //- 如果为空拦截 ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.UNAUTHORIZED); //401表示无权限访问 //编译返回 return response.setComplete(); } //- 如果不为空放行 return chain.filter(exchange); } /** * @Description: 值越小优先级越高,建议值要小于2,因为路由也是一个过滤器,并且路由过滤器的优先级别为2 */ @Override public int getOrder() { return 0; } }
-
http://localhost:10010/consumer/findUserById/2?token=121546456485
三、Config配置中心
介绍:
用于管理配置文件,在配置文件中存在两种,一种是叫application.yml一般用于配置一些项目信息,另一种是boostrap.yml一般用于配置项目启动时需要加载的配置,两者bootstrap优先级别更高。
1. 配置中心服务搭建
步骤:
- 创建config-server项目
- web/eureka-client/config-server
- 在启动类添加注解
- eurekaclient
- configserver注解声明是一个配置中心
- 编写配置文件
- 端口
- 应用名称
- 注册中心
- git地址(暂时不配置)
- 创建git仓库存放配置文件
过程:
-
启动类添加注解
@SpringBootApplication @EnableEurekaClient //注册到注册中心 @EnableConfigServer //声明是一个配置中心 public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } }
-
配置文件
server: port: 1200 spring: application: name: config-server cloud: config: server: git: uri: https://gitee.com/guodongzz/jiuye-31.git #账密公开仓库不需要填写,如果是私有仓库必须明文填写, # username: # password: eureka: client: service-url: defaultZone: http://localhost:8761/eureka
2. 改造用户服务
步骤:
-
在gitee创建三个配置文件
-
user-dev.yml
#db spring: datasource: #serverTimezone=UTC url: jdbc:mysql://127.0.0.1/itheima?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC driver-class-name: com.mysql.cj.jdbc.Driver username: root password: root application: name: user-service #mybatis mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.itheima.pojo personName: caixukun-dev
-
user-test.yml
#db spring: datasource: #serverTimezone=UTC url: jdbc:mysql://127.0.0.1/itheima?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC driver-class-name: com.mysql.cj.jdbc.Driver username: root password: root application: name: user-service #mybatis mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.itheima.pojo personName: caixukun-test
-
user-prod.yml
#db spring: datasource: #serverTimezone=UTC url: jdbc:mysql://127.0.0.1/itheima?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC driver-class-name: com.mysql.cj.jdbc.Driver username: root password: root application: name: user-service #mybatis mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.itheima.pojo personName: caixukun-prod
-
-
添加依赖 config
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
-
在UserController中获取personName
@Value("${personName}") private String personName; /** * @Author: guodong * @Date: 9:50 2020/9/22 * @Parms [] * @ReturnType: java.lang.String * @Description: 获取personName区分使用的配置文件环境 */ @GetMapping("getPersonName") public String getPersonName() { return personName; }
-
在配置文件中声明要使用配置中心
-
将application.yml------>bootstrap.yml
-
将配置文件中的db+mybatis配置删除
-
编写配置使用配置中心
- 声明要使用的配置文件名称
- 配置文件环境
- git分支名称
- 声明要使用配置中心
- 配置中心的服务id
eureka: client: service-url: defaultZone: http://localhost:8761/eureka #注册中心的地址 server: port: 9091 spring: cloud: config: #配置文件名称 name: user profile: dev #配置文件环境 label: master #git分支名称 discovery: enabled: true #开启使用配置中心 service-id: config-server #配置中心的服务应用名称
-
3. 配置更新问题
演示:
修改配置文件personName内容刷新91和92服务发现配置信息没有发生变化。
解决:
-
导入actuator依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
-
暴露刷新地址—》refresh
eureka: client: service-url: defaultZone: http://localhost:8761/eureka #注册中心的地址 server: port: 9091 spring: cloud: config: #配置文件名称 name: user profile: dev #配置文件环境 label: master #git分支名称 discovery: enabled: true #开启使用配置中心 service-id: config-server #配置中心的服务应用名称 management: endpoints: web: exposure: include: refresh #暴露刷新地址
-
在UserController添加@RefreshScope注解表示允许刷新
@RefreshScope //表示允许刷新 public class UserController { //省略 }
-
使用postman请求刷新地址发送post请求
http://localhost:9091/actuator/refresh
http://localhost:9092/actuator/refresh
注意:
- 刷新时必须使用post请求
- 暴露的刷新地址必须叫refresh
四、Bus-消息总线
介绍:
消息总线,类比于微信,用于发送接收消息。
1. 安装RabbitMq
#docker复习
docker images
docker search 镜像名称
docker pull 镜像名称:版本号
docker rmi 镜像名称:版本号
docker images -q
docker ps
docker ps -a
#交互式容器 一旦创建直接进入容器内部,退出容器后容器自动停止运行
docker run -it --name=容器名称 镜像 /bin/bash
#守护式容器 创建后不会进入容器内部,需要使用命令方可进入,容器退出后不会停止运行
docker run -id --name=容器名称 -p 外部端口:内部端口 镜像
docker start 容器名称
docker stop 容器名称
docker rm 容器名称 #运行时的容器需要停止后再删除
docker rm -f 容器名称 #不建议使用
#安装mq
docker run -id --name=c_rabbitmq -p 15672:15672 -p 5672:5672 rabbitmq:management
#测试访问
http://ip:15672 #如果可以看到管理页面代表部署成功 账密: guest/guest
2. 改造配置中心
步骤:
-
导入bus-amqp依赖、actuator依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
-
修改配置文件
-
mq配置信息
-
暴露刷新地址
-
server: port: 1200 spring: application: name: config-server cloud: config: server: git: uri: https://gitee.com/guodongzz/jiuye-31.git rabbitmq: host: 192.168.200.132 #以下三个配置使用默认值即可 # port: 5672 # username: guest # password: guest #账密公开仓库不需要填写,如果是私有仓库必须明文填写, # username: # password: eureka: client: service-url: defaultZone: http://localhost:8761/eureka #暴露刷新地址 management: endpoints: web: exposure: include: bus-refresh
-
3. 改造用户服务
步骤:
- 导入bus-amqp依赖
- 在配置文件中添加mq信息
- 在UserController添加@RefreshScope注解表示允许刷新(已经添加过,此处无需再次添加)
4. 使用postman批量刷新,post请求
http://localhost:1200/actuator/bus-refresh
5 扩展:刷新单个服务
http://localhost:1200/actuator/bus-refresh/user-service:9091
6. bus刷新流程
- 使用postman请求config-server配置中心
- 配置中心发送更新消息到mq
- 用户服务监听到消息
- 用户服务从配置中心主动拉取配置文件
- 配置中心从gitee获取最新的配置文件