Spring Cloud Eureka--Zuul API网关 Hystrix实践

x33g5p2x  于2021-11-17 转载在 Spring  
字(14.2k)|赞(0)|评价(0)|浏览(396)

统一的入口

1.新建spring模块:sp06-zuul

2.添加依赖

eureka+zuul

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <parent>
  5. <artifactId>springcloud1</artifactId>
  6. <groupId>cn.tedu</groupId>
  7. <version>1.0-SNAPSHOT</version>
  8. </parent>
  9. <groupId>cn.tedu</groupId>
  10. <artifactId>sp06-zuul</artifactId>
  11. <version>0.0.1-SNAPSHOT</version>
  12. <name>sp06-zuul</name>
  13. <description>Demo project for Spring Boot</description>
  14. <properties>
  15. <java.version>1.8</java.version>
  16. </properties>
  17. <dependencies>
  18. <dependency>
  19. <groupId>org.springframework.cloud</groupId>
  20. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-test</artifactId>
  25. <scope>test</scope>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.springframework.cloud</groupId>
  29. <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
  30. </dependency>
  31. <dependency>
  32. <groupId>cn.tedu</groupId>
  33. <artifactId>sp01-commons</artifactId>
  34. <version>1.0-SNAPSHOT</version>
  35. </dependency>
  36. </dependencies>
  37. <build>
  38. <plugins>
  39. <plugin>
  40. <groupId>org.springframework.boot</groupId>
  41. <artifactId>spring-boot-maven-plugin</artifactId>
  42. </plugin>
  43. </plugins>
  44. </build>
  45. </project>

3.yml配置

  1. spring:
  2. application:
  3. name: zuul
  4. # eureka2001 3001 3001 4001 5001 6001
  5. server:
  6. port: 3001
  7. eureka:
  8. client:
  9. service-url:
  10. defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka
  11. zuul:
  12. routes:
  13. # **包含深层子路径
  14. # *只包含一层路径
  15. # service-id 作为访问子路径,是默认设置
  16. # 根据注册表中的注册信息,zuul可以自动配置,防止注册表不全
  17. # 最好自己手动配置
  18. item-service: /item-service/**
  19. user-service: /user-service/**
  20. order-service: /order-service/**

4.启动类注解

@EnableZuulProxy

  1. package cn.tedu.sp06;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
  5. @SpringBootApplication
  6. @EnableZuulProxy
  7. public class Sp06ZuulApplication {
  8. public static void main(String[] args) {
  9. SpringApplication.run(Sp06ZuulApplication.class, args);
  10. }
  11. }

5. rest.http测试

  1. ### 获取订单的商品列表
  2. GET http://localhost:8001/ty4g33t3
  3. ### 减少商品库存
  4. POST http://localhost:8001/decreaseNumber
  5. Accept: application/json
  6. Content-Type: application/json
  7. [{"id":1, "name":"abc", "number":23},{"id":2, "name":"def", "number":11}]
  8. ### 获取用户
  9. GET http://localhost:8101/7
  10. ###
  11. GET http://localhost:8101/8
  12. ###
  13. GET http://localhost:8101/9
  14. ###
  15. GET http://localhost:8101/10
  16. ### 增加积分
  17. GET http://localhost:8101/8/score?score=1000
  18. ### 获取订单
  19. GET http://localhost:8201/iujhygf435tg
  20. ### 添加订单
  21. GET http://localhost:8201/add
  22. # ---------------------------------------------------------------------------------
  23. ### 获取订单的商品列表
  24. GET http://localhost:3001/item-service/ty4g33t3
  25. ### 减少商品库存
  26. POST http://localhost:3001/item-service/decreaseNumber
  27. Accept: application/json
  28. Content-Type: application/json
  29. [{"id":1, "name":"abc", "number":23},{"id":2, "name":"def", "number":11}]
  30. ### 获取用户
  31. GET http://localhost:3001/user-service/7
  32. ###
  33. GET http://localhost:3001/user-service/8
  34. ###
  35. GET http://localhost:3001/user-service/9
  36. ###
  37. GET http://localhost:3001/user-service/10
  38. ### 增加积分
  39. GET http://localhost:3001/user-service/8/score?score=1000
  40. ### 获取订单
  41. GET http://localhost:3001/order-service/iujhygf435tg
  42. ### 添加订单
  43. GET http://localhost:3001/order-service/add

统一权限校验

  • zuul的过滤器XZuulProxy,可以过滤客户端请求,在过滤器中可以检查访问权限
    前置、路由、后置\、错误过滤器
    测试:http://localhost:3001/item-service/jsihfhj 没有登录不允许访问
    http://localhost:3001/item-service/jsihfhj?token=ndhfjdhsjfdjs bfjhdskj 有令牌,则一登陆允许访问 (真正项目token应放在协议头,很测试没有登录系统)

1.新建过滤器类

  • AccessFilter 按照Zull的规则实现 继承ZuulFilter

2.重写ZuulFilter接口的四个抽象方法

  • 设置过滤器的类型
  • 设置过滤器添加的顺序号
  • 针对当前请求判断是否要执行下面的过滤代码
  • 过滤代码
  • @Component 自动扫描自动创建实例
    实现代码
  1. package cn.tedu.sp06.filter;
  2. import cn.tedu.web.util.JsonResult;
  3. import com.netflix.zuul.ZuulFilter;
  4. import com.netflix.zuul.context.RequestContext;
  5. import com.netflix.zuul.exception.ZuulException;
  6. import org.apache.commons.lang.StringUtils;
  7. import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
  8. import org.springframework.stereotype.Component;
  9. import javax.servlet.http.HttpServletRequest;
  10. @Component
  11. public class AccessFilter extends ZuulFilter {
  12. /*设置过滤器的类型 pre routing post error*/
  13. @Override
  14. public String filterType() {
  15. // return "pre";
  16. return FilterConstants.PRE_TYPE;
  17. }
  18. /*设置过滤器添加的顺序号 前置过滤器中有五个默认过滤器 自定义过滤器放在末尾 位置为6*/
  19. @Override
  20. public int filterOrder() {
  21. return 6;
  22. }
  23. /*针对当前请求判断是否要执行下面的过滤代码*/
  24. @Override
  25. public boolean shouldFilter() {
  26. /*调用商品需要判断权限 * 调用用户/订单不检查权限(这里只演示实现,不考虑业务逻辑) * */
  27. //1.获得一个请求上下文对象
  28. RequestContext ctx=RequestContext.getCurrentContext();
  29. //2.从上下文对象获得调用后台服务的 serviceid 类型要转成字符串类型
  30. String serviceId = (String)ctx.get(FilterConstants.SERVICE_ID_KEY);//"serviceId"
  31. //3.如果调用了item-service 返回true
  32. return "item-service".equals(serviceId);
  33. }
  34. /*过滤代码,检查权限*/
  35. @Override
  36. public Object run() throws ZuulException {
  37. //1.获得上下文对象
  38. RequestContext ctx=RequestContext.getCurrentContext();
  39. //2.获得Request对象
  40. HttpServletRequest request = ctx.getRequest();
  41. //3.接收token参数
  42. String token = request.getParameter("token");
  43. //4.如果token不存在: ①null ②"" ③" "
  44. if(StringUtils.isBlank(token)){ //区别idEmpty()
  45. //5.阻止继续调用
  46. ctx.setSendZuulResponse(false);//发送zuul响应关闭
  47. //6.直接返回响应 提示未登录
  48. //JsonResult--{code:400,msg:未登录,data:null}
  49. String json=JsonResult.build().code(400).msg("not log in").toString();
  50. //响应协议头
  51. ctx.addZuulResponseHeader("Content-Type", "application/json;charset=UTF-8");
  52. //响应协议体
  53. ctx.setResponseBody(json);
  54. }
  55. return null;//zuul当前版本这个返回值不起任何作用
  56. }
  57. }

设置过滤器的类型

实现效果

  • 为什么顺序号为6???
  • 前置过滤器中有五个默认过滤器PreDecorationFilter 自定义过滤器放在末尾 位置为6
    在第五个过滤器放入了serviceid

Zuul集成Ribbon

  • 负载均衡默认启用
  • 重试默认禁用
  • 在最前面重试会造成后台服务器大面积出现故障
    也可以启用重试,一般不会启用
    设置:
  • 添加spring-retry依赖
    xml <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
  • yml配置启用重试
  1. spring:
  2. application:
  3. name: zuul
  4. # eureka2001 3001 3001 4001 5001 6001
  5. server:
  6. port: 3001
  7. eureka:
  8. client:
  9. service-url:
  10. defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka
  11. zuul:
  12. routes:
  13. # **包含深层子路径
  14. # *只包含一层路径
  15. # service-id 作为访问子路径,是默认设置
  16. # 根据注册表中的注册信息,zuul可以自动配置,防止注册表不全
  17. # 最好自己手动配置
  18. item-service: /item-service/**
  19. user-service: /user-service/**
  20. order-service: /order-service/**
  21. retryable: true
  22. # 对所有服务都有效的通用配置
  23. ribbon:
  24. MaxAutoRetries: 1
  25. # 对某一个单独配置
  26. item-service:
  27. ribbon:
  28. MaxAutoRetries: 0

Zuul集成Hystrix

  • Hystrix是容错和限流工具(与sentinel相似)
  • Hystrix容错:通过降级处理
  • Hystrix限流:熔断

1. Zuul网关使用Hystrix进行同错处理,执行降级

  • Zuul默认已经启用Hystrix,任何基础配置都不用做
  • 调用后台服务失败,执行前面模块中的降级代码,返回降级结果
    ①给出错误提示
    ②返回缓存数据
    ③根据业务逻辑返回任何结果都可以

1.新建降级类 ItemFB 实现FallbackProvider接口

  1. package cn.tedu.sp06.fb;
  2. import cn.tedu.web.util.JsonResult;
  3. import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
  4. import org.springframework.http.HttpHeaders;
  5. import org.springframework.http.HttpStatus;
  6. import org.springframework.http.client.ClientHttpResponse;
  7. import org.springframework.stereotype.Component;
  8. import java.io.ByteArrayInputStream;
  9. import java.io.IOException;
  10. import java.io.InputStream;
  11. import java.nio.charset.StandardCharsets;
  12. @Component
  13. public class itemFB implements FallbackProvider {
  14. /*设置针对哪个后台服务进行降级 * -item-service只针对商品服务降级 * *:对所有服务都应用当前降级类 * null:对所有服务都应用当前降级类 * */
  15. @Override
  16. public String getRoute() {
  17. return "item-service";
  18. }
  19. /*向客户端返回的响应数据*/
  20. @Override
  21. public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
  22. return new ClientHttpResponse() {
  23. @Override/*返回状态码对象*/
  24. public HttpStatus getStatusCode() throws IOException {
  25. return HttpStatus.INTERNAL_SERVER_ERROR;
  26. }
  27. @Override/*状态码的码*/
  28. public int getRawStatusCode() throws IOException {
  29. return HttpStatus.INTERNAL_SERVER_ERROR.value();
  30. }
  31. @Override/*状态码的文本*/
  32. public String getStatusText() throws IOException {
  33. return HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase();
  34. }
  35. @Override
  36. public void close() {
  37. //用来关闭流
  38. //BAIS不占用底层系统资源,不需要关闭
  39. }
  40. @Override/*协议体*/
  41. public InputStream getBody() throws IOException {
  42. //JsonResult -{code msg data}
  43. String json = JsonResult.build().code(500).msg("后台服务出错请稍后重试").toString();
  44. return new ByteArrayInputStream(json.getBytes("UTF-8"));
  45. }
  46. @Override/*协议头*/
  47. public HttpHeaders getHeaders() {
  48. HttpHeaders h = new HttpHeaders();
  49. h.add("Content-Type", "application/json;charset=UTF-8");
  50. return h;
  51. }
  52. };
  53. }
  54. }

2.新建降级类 ItemFB 实现FallbackProvider接口

  1. package cn.tedu.sp06.fb;
  2. import cn.tedu.web.util.JsonResult;
  3. import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
  4. import org.springframework.http.HttpHeaders;
  5. import org.springframework.http.HttpStatus;
  6. import org.springframework.http.client.ClientHttpResponse;
  7. import org.springframework.stereotype.Component;
  8. import java.io.ByteArrayInputStream;
  9. import java.io.IOException;
  10. import java.io.InputStream;
  11. @Component
  12. public class orderFB implements FallbackProvider {
  13. /*设置针对哪个后台服务进行降级 * -item-service只针对商品服务降级 * *:对所有服务都应用当前降级类 * null:对所有服务都应用当前降级类 * */
  14. @Override
  15. public String getRoute() {
  16. return "order-service";
  17. }
  18. /*向客户端返回的响应数据*/
  19. @Override
  20. public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
  21. return new ClientHttpResponse() {
  22. @Override/*返回状态码对象*/
  23. public HttpStatus getStatusCode() throws IOException {
  24. return HttpStatus.INTERNAL_SERVER_ERROR;
  25. }
  26. @Override/*状态码的码*/
  27. public int getRawStatusCode() throws IOException {
  28. return HttpStatus.INTERNAL_SERVER_ERROR.value();
  29. }
  30. @Override/*状态码的文本*/
  31. public String getStatusText() throws IOException {
  32. return HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase();
  33. }
  34. @Override
  35. public void close() {
  36. //用来关闭流
  37. //BAIS不占用底层系统资源,不需要关闭
  38. }
  39. @Override/*协议体*/
  40. public InputStream getBody() throws IOException {
  41. //JsonResult -{code msg data}
  42. String json = JsonResult.build().code(500).msg("后台服务出错请稍后重试").toString();
  43. return new ByteArrayInputStream(json.getBytes("UTF-8"));
  44. }
  45. @Override/*协议头*/
  46. public HttpHeaders getHeaders() {
  47. HttpHeaders h = new HttpHeaders();
  48. h.add("Content-Type", "application/json;charset=UTF-8");
  49. return h;
  50. }
  51. };
  52. }
  53. }

实现效果

2. Zuul集成Hystrix实现限流,熔断

  • 当流量 过大,后台服务出现故障,可以断开链路,限制后台故障服务
  • 在06添加断路器,断开连接后,直接执行06的降级代码(不会进行远程调用),返回降级结果(短路请求),执行效率很高
    断路器打开条件:
    ①20次/10s 请求,必须首先满足
    ②50%请求出错,执行了降级代码
    if(20){if(50%){}}
  • 断路器打开之后,会进入半开状态
    在半开状态下,会向服务器尝试发送一次客户端调用
    调用成功,自动关闭断路器恢复正常;
    调用失败,继续保持打开状态。再进入半开状态
    打开 半开 打开 半开…循环

Hystrix dashboard

  • 对降流和熔断的情况进行监控,可以通过监控快速定位故障模块
  • 调用02.03.04在06产生监控日志 使用Actuator工具
  • Actuator是spring提供的监控指标工具,可以暴露项目的各种监控指标
    ①健康状态
    ②spring容器中的所有对象
    ③spring mvc 映射的所有路径
    ④环境变量
    ⑤堆内存镜像(java虚拟机使用的堆内存)

暴露Actuator监控指标

1. Actuator依赖→06

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
  4. </dependency>

actuator依赖于zuul

2. 06yml配置

  1. m.e.w.e.i="*" # *:暴露所有监控指标
  2. m.e.w.e.i=health,beans,mappings # *:暴露指定监控指标
  3. m.e.w.e.i=hystrix.stream
  4. ***********************************************************
  5. #暴露actuator的监控指标
  6. management:
  7. endpoints:
  8. web:
  9. exposure:
  10. include: "*" #暴露所有监控

3.访问

http://localhost:3001/actuator

  1. ### actuator
  2. GET http://localhost:3001/actuator
  3. ###
  4. GET http://localhost:3001/actuator/health
  5. ###
  6. GET http://localhost:3001/actuator/info
  7. ###
  8. GET http://localhost:3001/actuator/beans
  9. ###
  10. GET http://localhost:3001/actuator/mappings
  11. ###
  12. GET http://localhost:3001/actuator/heapdump
  13. ###
  14. GET http://localhost:3001/actuator/hystrix.stream

搭建Hystrix-dashboard(仪表盘)

1. 新建spring模块: sp07-hystrix-dashboard

2. 调整pom.xml 添加hystrix dashboard依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <parent>
  5. <artifactId>springcloud1</artifactId>
  6. <groupId>cn.tedu</groupId>
  7. <version>1.0-SNAPSHOT</version>
  8. </parent>
  9. <groupId>cn.tedu</groupId>
  10. <artifactId>sp07-hystrix-dashboard</artifactId>
  11. <version>0.0.1-SNAPSHOT</version>
  12. <name>sp07-hystrix-dashboard</name>
  13. <description>Demo project for Spring Boot</description>
  14. <properties>
  15. <java.version>1.8</java.version>
  16. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  17. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  18. </properties>
  19. <dependencies>
  20. <dependency>
  21. <groupId>org.springframework.cloud</groupId>
  22. <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-test</artifactId>
  27. <scope>test</scope>
  28. </dependency>
  29. </dependencies>
  30. <build>
  31. <plugins>
  32. <plugin>
  33. <groupId>org.apache.maven.plugins</groupId>
  34. <artifactId>maven-compiler-plugin</artifactId>
  35. <version>3.8.1</version>
  36. <configuration>
  37. <source>1.8</source>
  38. <target>1.8</target>
  39. <encoding>UTF-8</encoding>
  40. </configuration>
  41. </plugin>
  42. <plugin>
  43. <groupId>org.springframework.boot</groupId>
  44. <artifactId>spring-boot-maven-plugin</artifactId>
  45. <version>2.4.1</version>
  46. <configuration>
  47. <mainClass>cn.tedu.sp07.Sp07HystrixDashboardApplication</mainClass>
  48. </configuration>
  49. <executions>
  50. <execution>
  51. <id>repackage</id>
  52. <goals>
  53. <goal>repackage</goal>
  54. </goals>
  55. </execution>
  56. </executions>
  57. </plugin>
  58. </plugins>
  59. </build>
  60. </project>

3. 配置yml

  1. server:
  2. port: 4001
  3. #允许抓取日志的服务器列表
  4. hystrix:
  5. dashboard:
  6. proxy-stream-allow-list: localhost

4. 启动类添加注解

@EnableHystrixDashboard

  1. package cn.tedu.sp07;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
  5. @SpringBootApplication
  6. @EnableHystrixDashboard
  7. public class Sp07HystrixDashboardApplication {
  8. public static void main(String[] args) {
  9. SpringApplication.run(Sp07HystrixDashboardApplication.class, args);
  10. }
  11. }

5. 启动访问

  1. http://localhost:4001/hystrix
  2. http://localhost:3001/actuator/hystrix.stream

相关文章