• Zuul使用总结


    目录

    启用网关

    负载均衡

    路由端点

    配置指定微服务的访问路径

    忽略微服务

    前缀

    灰度发布功能

    敏感Header

    接口容错

    限流

    过来的url改造成别的url

    Zuul的自带Route过滤器使用

    actuator查看路由和过滤器

    Pre过滤器控制不通过Route过滤器


    启用网关

    新建项目引入依赖

    1. <dependency>
    2. <groupId>org.springframework.cloud</groupId>
    3. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    4. </dependency>
    5. <dependency>
    6. <groupId>org.springframework.cloud</groupId>
    7. <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    8. </dependency>

    配置文件

    1. eureka.client.service-url.defaultZone=http://euk1.com:7001/eureka/
    2. spring.application.name=zuulserver
    3. server.port=80

    启动类

    @EnableZuulProxy

    测试访问

    网关会将服务名转换成具体服务的ip和端口,实际进行访问

    http://localhost/consumer/alive

    负载均衡

    启动两个Consumer

    轮询访问上面地址,会看到返回结果中,端口一直轮询在变。说明负载均衡生效了,默认是轮询

    consumer.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

    路由端点

    调试的时候,看网关请求的地址,以及 映射是否正确。网关请求有误时,可以通过此处排查错误。

    配置

    1. management.endpoints.web.exposure.include=*
    2. management.endpoint.health.show-details=always
    3. management.endpoint.health.enabled=true
    4. management.endpoint.routes.enabled=true

    配置指定微服务的访问路径

    1. 通过服务名配置(虚拟主机名)

    zuul.routes.consumer=/xxoo/**

    配置前先访问,然后做对比。

    2.自定义映射

    zuul.routes.xx.path=/xx/**
    zuul.routes.xx.url=http://mashibing.com

    3. .自定义下的负载均衡

    zuul.routes.xx.path=/xx/**
    zuul.routes.xx.service-id=cuid

    cuid.ribbon.listOfServers=localhost:82,localhost:83
    ribbon.eureka.enabled=false

    忽略微服务

    配置

    zuul.ignored-services=user-provider

    前缀

    zuul.prefix=/api/v1

    带上前缀请求

    zuul.strip-prefix=false

    灰度发布功能

    zuul服务器的

    pom.xml:需要引入eureka客户端、zuul、ribbon-discovery-filter-spring-cloud-starter这三个。

    ribbon-discovery-filter-spring-cloud-starter主要用于网关选择集群中的某一个节点。主要方法是RibbonFilterContextHolder.getCurrentContext().add("version","v2");(详情见java代码)
    
    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"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0</modelVersion>
    5. <parent>
    6. <groupId>org.springframework.boot</groupId>
    7. <artifactId>spring-boot-starter-parent</artifactId>
    8. <version>2.3.10.RELEASE</version>
    9. <relativePath/> <!-- lookup parent from repository -->
    10. </parent>
    11. <groupId>com.kingdee</groupId>
    12. <artifactId>zuul</artifactId>
    13. <version>0.0.1-SNAPSHOT</version>
    14. <name>zuul</name>
    15. <description>Demo project for Spring Boot</description>
    16. <properties>
    17. <java.version>1.8</java.version>
    18. <spring-cloud.version>Hoxton.SR11</spring-cloud.version>
    19. </properties>
    20. <dependencies>
    21. <dependency>
    22. <groupId>org.springframework.cloud</groupId>
    23. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    24. </dependency>
    25. <dependency>
    26. <groupId>org.springframework.cloud</groupId>
    27. <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    28. </dependency>
    29. <dependency>
    30. <groupId>io.jmnarloch</groupId>
    31. <artifactId>ribbon-discovery-filter-spring-cloud-starter</artifactId>
    32. <version>2.1.0</version>
    33. </dependency>
    34. <dependency>
    35. <groupId>org.springframework.boot</groupId>
    36. <artifactId>spring-boot-starter-test</artifactId>
    37. <scope>test</scope>
    38. <exclusions>
    39. <exclusion>
    40. <groupId>org.junit.vintage</groupId>
    41. <artifactId>junit-vintage-engine</artifactId>
    42. </exclusion>
    43. </exclusions>
    44. </dependency>
    45. </dependencies>
    46. <dependencyManagement>
    47. <dependencies>
    48. <dependency>
    49. <groupId>org.springframework.cloud</groupId>
    50. <artifactId>spring-cloud-dependencies</artifactId>
    51. <version>${spring-cloud.version}</version>
    52. <type>pom</type>
    53. <scope>import</scope>
    54. </dependency>
    55. </dependencies>
    56. </dependencyManagement>
    57. <build>
    58. <plugins>
    59. <plugin>
    60. <groupId>org.springframework.boot</groupId>
    61. <artifactId>spring-boot-maven-plugin</artifactId>
    62. </plugin>
    63. </plugins>
    64. </build>
    65. </project>

    java代码:

    1. package com.kingdee.zuul.filter;
    2. import com.netflix.zuul.ZuulFilter;
    3. import com.netflix.zuul.context.RequestContext;
    4. import com.netflix.zuul.exception.ZuulException;
    5. import io.jmnarloch.spring.cloud.ribbon.support.RibbonFilterContextHolder;
    6. import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
    7. import org.springframework.stereotype.Component;
    8. import javax.servlet.http.HttpServletRequest;
    9. /**
    10. * @author :zhouhaitao
    11. * @date :Created in 2021/5/20 23:39
    12. * @description
    13. * @modified By:
    14. * @version: v1.0
    15. */
    16. @Component
    17. public class GrayFilter extends ZuulFilter {
    18. @Override
    19. public String filterType() {
    20. return FilterConstants.ROUTE_TYPE;
    21. }
    22. @Override
    23. public int filterOrder() {
    24. return 0;
    25. }
    26. @Override
    27. public boolean shouldFilter() {
    28. return true;
    29. }
    30. @Override
    31. public Object run() throws ZuulException {
    32. RequestContext currentContent = RequestContext.getCurrentContext();
    33. HttpServletRequest request = currentContent.getRequest();
    34. String userId = request.getHeader("userId");
    35. //根据用户Id查规则
    36. if("1".equals(userId)){
    37. RibbonFilterContextHolder.getCurrentContext().add("version","v2");
    38. }else{
    39. RibbonFilterContextHolder.getCurrentContext().add("version","v1");
    40. }
    41. return null;
    42. }
    43. }

    敏感Header

    这个主要是设置cookie里哪些值会被传到后面!!

    测试点:

    停止一个api-driver。访问:yapi:网关token,看返回。

    初始请求。返回值中token为msb cookie

    加上下面配置

    敏感的header不会传播到下游去,也就是说此处的token不会传播的其它的微服务中去。

    1. zuul:
    2. #一下配置,表示忽略下面的值向微服务传播,以下配置为空表示:所有请求头都透传到后面微服务。
    3. sensitive-headers: token

    访问。网关token为null。

    接口容错

    1. @Component
    2. public class MsbFallback implements FallbackProvider{
    3. /**
    4. * 表明为哪个微服务提供回退
    5. * 服务Id ,若需要所有服务调用都支持回退,返回null 或者 * 即可
    6. */
    7. @Override
    8. public String getRoute() {
    9. // TODO Auto-generated method stub
    10. return "*";
    11. }
    12. @Override
    13. public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
    14. if (cause instanceof HystrixTimeoutException) {
    15. return response(HttpStatus.GATEWAY_TIMEOUT);
    16. } else {
    17. return response(HttpStatus.INTERNAL_SERVER_ERROR);
    18. }
    19. }
    20. private ClientHttpResponse response(final HttpStatus status) {
    21. return new ClientHttpResponse() {
    22. @Override
    23. public HttpStatus getStatusCode() throws IOException {
    24. //return status;
    25. return HttpStatus.BAD_REQUEST;
    26. }
    27. @Override
    28. public int getRawStatusCode() throws IOException {
    29. //return status.value();
    30. return HttpStatus.BAD_REQUEST.value();
    31. }
    32. @Override
    33. public String getStatusText() throws IOException {
    34. //return status.getReasonPhrase();
    35. //return HttpStatus.BAD_REQUEST.name();
    36. return HttpStatus.BAD_REQUEST.getReasonPhrase();
    37. }
    38. @Override
    39. public void close() {
    40. }
    41. @Override
    42. public InputStream getBody() throws IOException {
    43. String msg = "{\"msg\":\"服务故障\"}";
    44. return new ByteArrayInputStream(msg.getBytes());
    45. }
    46. @Override
    47. public HttpHeaders getHeaders() {
    48. HttpHeaders headers = new HttpHeaders();
    49. headers.setContentType(MediaType.APPLICATION_JSON);
    50. return headers;
    51. }
    52. };
    53. }
    54. }

    选用基础yml

    测试点:启动eureka,api-driver, online-taxi-zuul

    正常启动,正常访问yapi 网关token。正常

    停止api-driver。

    则走了容错 方法。

    将fallback的改成:

    1. @Override
    2. public String getRoute() {
    3. // TODO Auto-generated method stub
    4. // return "*";
    5. return "api-passenger";
    6. }

    在访问上面 yapi 中 zuul,中网关token。则报500。

    再改成:

    1. @Override
    2. public String getRoute() {
    3. // TODO Auto-generated method stub
    4. // return "*";
    5. // return "api-passenger";
    6. return "api-driver";
    7. }

    重写访问,熔断生效。

    最后改回去*。

    限流

    保护自己,用ratelimit。

    令牌桶

    假设进入高速公路的车辆需要在入口处领取到通行卡才能进入高速公路。为了节约人力成本,入口处放置自动出卡机。按照国家高速公路交通安全法的规定,在高速公路上行驶的车辆,车速超过100km/h时,应与同车道前车保持100米以上距离。为了保持最小安全行车距离100米,按车速100km/h计算,需要间隔至少3.6秒才能放行一辆车,因此出卡机每隔3.6秒出一张通行卡。在自动出卡机下放置一个盒子,自动出卡机按照3.6秒的间隔向盒子中投放通行卡。每辆进入高速公路的车辆,从盒子中领取通行卡之后才可以进入高速公路。

    令牌桶可以看作是一个存放一定数量令牌的容器。系统按设定的速度向桶中放置令牌。当桶中令牌满时,多出的令牌溢出,桶中令牌不再增加。在使用令牌桶对流量规格进行评估时,是以令牌桶中的令牌数量是否足够满足报文的转发为依据的。每个需要被转发的报文,都要从令牌桶中领取一定数量的令牌(具体数量视报文大小而定),才可以被正常转发。如果桶中存在足够的令牌可以用来转发报文,称流量遵守或符合约定值,否则称为不符合或超标。

    1. 启动jmeter,双击:jmeter.bat

    2. 右击TestPlan,add ,Threads,Thread Group

    3. 右击测试令牌桶线程组,add,sampler, http request。

    4. 在线程组:

      1、Number of Threads(users):用户个数

      2、Ramp-up Period(in seconds):在多长时间内,加载指定的用户个数,单位为s。假如需加载100个用户,在5s中之内加载完成,那么平均每秒钟加载20个用户。

      3、Loop Count(循环次数):用户执行操作的循环次数,如果选择forever,则永远循环下去。

       

    测试点:启动eureka,api-driver,online-taxi-zuul。

    令牌桶设置成2,jemter 用10个并发。可以看到控制台输出结果。

    过来的url改造成别的url

    例如老项目中,原来的url,微服务改造后变成别的url了,通过网关进行转发

    例如

    app : /url/xxx/xxx将url中的test31转成服务提供的test3

    方法1

    1. zuul.
    2. route.
    3. 随便写自定义名
    4. path:=/account/**
    5. serviceId=account
    6. /account/a
    7. 没有/a

    问题:原来的url不动1,而服务没有提供相应的接口

    这个方法实际上是修改服务名,而不是修改对应的具体接口

    方法2:

    使用灰度的方式,使用filter进行转发

    方法3:

    使用nginx进行转发

    方法4:

    使用Zuul的自定义route过滤器进行转发

    1.过滤器,route。

    2.获取 请求过来的url(请求)

    3. url (请求)= url (目的地)映射。

    4. 设置RequestContext 中的 serviceld , url

    开发之前,想清楚步骤。

    技术和业务做选择和取舍。

    1. @Component
    2. public class CommonServicePathFilter extends ZuulFilter {
    3. private final static String GETWAY_FOWARD_PREFIX="getway_forward_";
    4. private final static String GETWAY_COMPAY_CONFIG_KEY = "getway_company";
    5. @Autowired
    6. private RedisTemplate redisTemplate;
    7. @Override
    8. public String filterType() {
    9. //这里很重要,必须是route
    10. return "route";
    11. }
    12. @Override
    13. public int filterOrder() {
    14. return 1;
    15. }
    16. @Override
    17. public Object run() throws ZuulException {
    18. RequestContext ctx = RequestContext.getCurrentContext();
    19. String url = ctx.getRequest().getRequestURI();
    20. Map<String,String> forwardMap = getForwardMap(url);
    21. if(forwardMap != null){
    22. String fowardUrl = forwardMap.get(url);
    23. String serviceId = getServiceId(fowardUrl);
    24. String requestUrl = getRequestUrl(fowardUrl,serviceId);
    25. //1.设置目标service的Controller的路径
    26. ctx.put(FilterConstants.REQUEST_URI_KEY,requestUrl);
    27. //2.设置目标service的serviceId
    28. ctx.put(FilterConstants.SERVICE_ID_KEY,serviceId);
    29. }
    30. return null;
    31. }
    32. private String getServiceId(String url){
    33. if(url.startsWith("/")){
    34. String temp = url.substring(1);
    35. return temp.split("/")[0];
    36. }else{
    37. return null;
    38. }
    39. }
    40. private String getRequestUrl(String url,String serviceId){
    41. return url.substring(serviceId.length() +1);
    42. }
    43. @Override
    44. public boolean shouldFilter() {
    45. return true;
    46. }
    47. private Map<String,String> getForwardMap(String originalUrl){
    48. //todo:这里是返回一个map,传入一个originUrl,返回一个要转发的url
    49. }
    50. }

    Zuul的自带Route过滤器使用

    路由过滤器

    RibbonXXXFilter :将url 路由到服务

    SimpleHostRoutingFilter :将url路由到 url 地址

    SendForwardFilter : 转发(转向zuul自己)

    RibbonRoutingFilter  order 10

    将url路由到服务

    1. zuul:
    2. routes:
    3. quality: /请求路径/**

    其中 quality 为服务的名称

    SimpleHostRoutingFilter order 100

    将url路由到url地址

    yml 配置:

    1. zuul:
    2. routes:
    3. #自己转发到自己 名字任意起
    4. xxx: 如果找不到会报404的错误(类似于将让eureka找到自己的服务,这个是zuul里面的)
    5. path: /前端请求的地址/**
    6. url: http://…… 接口的地址(全路径)

    SendForwardFilter  order 500

    将url路由到自己的controller

    yml 配置:

    1. zuul:
    2. routes:
    3. #自己转发到自己 名字任意起
    4. xxx:
    5. path: /前端请求的地址/**
    6. url: forward:/接口的地址

    例如

    访问 localhost:9090/forword1/

     设置

    实际上访问zuul的

    actuator查看路由和过滤器

    路由规则的查看。http://localhost:9100/actuator/routes

    1. pom:
    2. <dependency>
    3. <groupld>org.springframework.boot</groupId>
    4. <artifactId>spring-boot-starter-actuator</artifactId>
    5. </dependency>
    6. yml:
    7. management:
    8. endpoints:
    9. web:
    10. exposure:
    11. include: "*"
    12. endpoint:
    13. health:
    14. ##默认是never
    15. show-details: ALWAYS
    16. enabled: true
    17. routes:
    18. enabled: true

    过滤器的查看: http://localhost:9100/actuator/filters

    Pre过滤器控制不通过Route过滤器

    ip过滤。次数限制,设备号过滤。

    pre过滤器中设置。sendzuulresponse (false ),只控制不向 route过滤器 执行(即其他的pre还是执行的)

    因为ribbonroutefilter的shouldFilter判断了sendZuulResponse条件。

  • 相关阅读:
    Hive 最全面试题及答案(基础篇)
    银发经济硬战:福寿康稳步拓荒,小柏家护轻装上阵
    [Linux]----文件系统
    TP-Link家用路由器上网与防蹭网
    Android学习笔记 2.4.3 实例——使用QuickContactBadge关联联系人 && 2.4.4 实例——可折叠的悬浮按钮
    caffe之upsample实现
    新增文件收藏夹、回收站、终端等功能,1Panel开源面板v1.8.0发布
    金融企业容器云建设中资源智能优化实践
    能实现单个电机的启停、正反转和PWM直流调速,电机运行时数码管显示为1,电机停止时数码管显示为0,液晶屏在电机正转时显示字符F,反转时显示R,并显示当前转速。
    模型优化方法
  • 原文地址:https://blog.csdn.net/xushiyu1996818/article/details/124580985