1 概述

在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现、服务消费、负载均衡、熔断器、智能路由、配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统。一个简单的微服务系统如下图:

07. zuul路由网关 - 图1

在 Spring Cloud 微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(Zuul、Ngnix),再到达服务网关(Zuul 集群),然后再到具体的服。服务统一注册到高可用的服务注册中心集群,服务的所有的配置文件由配置服务管理,配置服务的配置文件放在 GIT 仓库,方便开发人员随时改配置

是什么

Zuul包含了对请求的路由和过滤两个最主要的功能:
其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础.

Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。

注意:Zuul服务最终还是会注册进Eureka

提供=代理+路由+过滤三大功能

能干嘛?

  1. 路由
  2. 过滤

官网资料

链接

2 路由基本配置

案例

1 新建Module模块cloud-zuul-gateway-9527

2 pom.xml

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.cloud</groupId>
  8. <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
  9. </dependency>
  10. <!-- actuator监控 -->
  11. <dependency>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-actuator</artifactId>
  14. </dependency>
  15. <!-- hystrix容错-->
  16. <dependency>
  17. <groupId>org.springframework.cloud</groupId>
  18. <artifactId>spring-cloud-starter-hystrix</artifactId>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.springframework.cloud</groupId>
  22. <artifactId>spring-cloud-starter-config</artifactId>
  23. </dependency>
  24. <!-- 日常标配 -->
  25. <dependency>
  26. <groupId>com.spiritmark.cloud</groupId>
  27. <artifactId>cloud-api</artifactId>
  28. <version>${project.version}</version>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.springframework.boot</groupId>
  32. <artifactId>spring-boot-starter-jetty</artifactId>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.springframework.boot</groupId>
  36. <artifactId>spring-boot-starter-web</artifactId>
  37. </dependency>
  38. <dependency>
  39. <groupId>org.springframework.boot</groupId>
  40. <artifactId>spring-boot-starter-test</artifactId>
  41. </dependency>
  42. <!-- 热部署插件 -->
  43. <dependency>
  44. <groupId>org.springframework</groupId>
  45. <artifactId>springloaded</artifactId>
  46. </dependency>
  47. <dependency>
  48. <groupId>org.springframework.boot</groupId>
  49. <artifactId>spring-boot-devtools</artifactId>
  50. </dependency>
  51. </dependencies>

3 yml

server: 
  port: 9527

spring: 
  application:
    name: microservicecloud-zuul-gateway

eureka: 
  client: 
    service-url: 
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka  
  instance:
    instance-id: gateway-9527.com
    prefer-ip-address: true 


info:
  app.name: microcloud
  company.name: www.spiritmark.com
  build.artifactId: $project.artifactId$
  build.version: $project.version$

4 C:\Windows\System32\drivers\etc\hosts修改

127.0.0.1 myzuul.com
image.png

5 主启动类Zuul9527

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy  //zuul注解
public class Zuul9527
{
  public static void main(String[] args)
  {
   SpringApplication.run(Zuul9527.class, args);
  }
}

6 启动 3个注册中心、cloud-provider-dept-8001、Zuul9527网关
image.png

7 测试
不用路由 http://localhost:8001/dept/get/2
启用路由 http://myzuul.com:9527/microservicecloud-dept/dept/get/2

3 路由访问映射规则

继续改造cloud-zuul-gateway-9527项目
设置代理名称 修改yml

zuul: 
  routes: 
    mydept.serviceId: microservicecloud-dept
    mydept.path: /mydept/**

设置代理前
http://myzuul.com:9527/microservicecloud-dept/dept/get/2
设置代理后 只有一个能请求成功 不对外暴露服务的名称
http://myzuul.com:9527/mydept/dept/get/1

原真实服务名忽略
修改yml

zuul: 
  ignored-services: microservicecloud-dept  #忽略 多个 ignored-services: "*"
  routes: 
    mydept.serviceId: microservicecloud-dept
    mydept.path: /mydept/**

设置统一公共前缀
修改yml

zuul: 
  prefix: /spiritmark  # 设置统一公共前缀
  ignored-services: "*"
  routes: 
    mydept.serviceId: microservicecloud-dept
    mydept.path: /mydept/**

路由说明:

  • 访问时加上前缀 /spiritmark
  • /mydept/任何 开头的请求都转发给 microservicecloud-dept服务

请求地址 : http://myzuul.com:9527/spiritmark/mydept/dept/get/1

配置网关路由失败回调


@Component
public class WebAdminFeignFallbackProvider implements FallbackProvider {

    @Override
    public String getRoute() {
        // ServiceId,如果需要所有调用都支持回退,则 return "*" 或 return null
        return "*";
    }

    /**
     * 如果请求服务失败,则返回指定的信息给调用者
     * @param route
     * @param cause
     * @return
     */
    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            /**
             * 网关向 api 服务请求失败了,但是消费者客户端向网关发起的请求是成功的,
             * 不应该把 api 的 404,500 等问题抛给客户端
             * 网关和 api 服务集群对于客户端来说是黑盒
             * @return
             * @throws IOException
             */
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return HttpStatus.OK.value();
            }

            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.OK.getReasonPhrase();
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                ObjectMapper objectMapper = new ObjectMapper();
                Map<String, Object> map = new HashMap<>();
                map.put("status", 200);
                map.put("message", "无法连接,请检查您的网络");
                return new ByteArrayInputStream(objectMapper.writeValueAsString(map).getBytes("UTF-8"));
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                // 和 getBody 中的内容编码一致
                headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
                return headers;
            }
        };
    }
}