SpringCloud学习(五):Zuul 路由过滤/网关

菜鸟学渣接触spring cloud 系列...

公司也上微服务了,再不学习下就凉了,所以来踩坑吧...

版本:

  spring-boot:  2.0

  spring-cloud: Finchley.SR1

已有项目:

  [eureka-server]              # 注册中心   port 8761

  [eureka-client-one]       #  微服务1    port 8501

  [eureka-client-two]       #  微服务2    port 8502

  [eureka-client-turbine] #  断路监控   port 8503

能上图绝不BB

  

  添加网关后,所有微服务API都通过ZUUL访问,zuul根据url分发到各个微服务实例

  spring-cloud-gateway是Spring自己撸的网关,和netflx-zuul性质一样,后面也去学习一下.

一、Zuul网关  [eureka-client-zuul]

  新建项目[eureka-client-zuul]

  引入依赖  spring-cloud-starter-netflix-zuul

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.renzku</groupId>
    <artifactId>eureka-client-zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>eureka-client-zuul</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>

    <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>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>
pom.xml

  配置文件  application.yml

server:
  port: 8601

spring:
  application:
    name: eureka-client-zuul

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

# 动态路由后面研究
# 默认引入eureka后不手动配置,会自动为每个服务都创建一个默认路由规则: 访问路径的前缀为serviceId配置的服务名称,这里修改下
zuul:
  routes:
    clientOne:
      path: /client-one/**
      serviceId: eureka-client-one
    clientTwo:
      path: /client-two/**
      serviceId: eureka-client-two
#      url: http://localhost:8502/

  启动类  EurekaClientZuulApplication.java

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class EurekaClientZuulApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaClientZuulApplication.class, args);
    }


}

  目录结构

  

  

  访问 http://localhost:8601/client-one 和 http://localhost:8601/client-two

  zuul根据url分别访问了微服务[eureka-client-one]和[eureka-client-two]

  

 

二、ZuulFilter过滤

  过滤器有4中:

    pre: 该类型的filters在Request routing到源web-service之前执行。用来实现Authentication、选择源服务地址等
    routing:该类型的filters用于把Request routing到源web-service,源web-service是实现业务逻辑的服务。这里使用HttpClient请求web-service。
    post:该类型的filters在ROUTING返回Response后执行。用来实现对Response结果进行修改,收集统计数据以及把Response传输会客户端。  
    error:上面三个过程中任何一个出现错误都交由ERROR类型的filters进行处理。

  顺序:

  

                    来源: https://blog.csdn.net/tianyaleixiaowu/article/details/77893822

  ‘pre' 过滤器  ZuulRequestFilter.java

public class ZuulRequestFilter extends ZuulFilter {

    public int filterOrder() {
        // filter 顺序
        return 5 - 1;
    }

    public String filterType() {
    // filter 类型
return "pre"; } @Override public boolean shouldFilter() {
    // filter 是否生效,这里一般根据请求头中的header灵活设置
return true; } public Object run() { RequestContext ctx = getCurrentContext(); // 添加个头信息 转发到其他微服务的请求头中会带上 “requestFilterParam” ctx.addZuulRequestHeader("requestFilterParam", "here is RequestFilter!"); return null; } }

  'post'过滤器   ZuulResponseFilter.java

public class ZuulResponseFilter extends ZuulFilter {
    public String filterType() {
        return "post";
    }

    public int filterOrder() {
        return 999;
    }

    public boolean shouldFilter() {
        return true;
    }

    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletResponse servletResponse = context.getResponse();
        // 添加个头信息   最后返回数据的头信息header中会带上  “responseFilterParam”
        servletResponse.addHeader("responseFilterParam", "here is ResponseFilter!");
        return null;
    }
}

  启动类加入Filter使生效

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class EurekaClientZuulApplication {

    @Bean
    public ZuulRequestFilter requestFilter(){
        return new ZuulRequestFilter();
    }

    @Bean
    public ZuulResponseFilter responseFilter(){
        return new ZuulResponseFilter();
    }

    public static void main(String[] args) {
        SpringApplication.run(EurekaClientZuulApplication.class, args);
    }
}

  

  测试 ZuulRequestFilter 和 ZuulResponseFilter:

  [eureka-client-one]中添加个Rest API: “/zuul/test"

@RestController
public class HelloWorld {

    @RequestMapping("/")
    @HystrixCommand(fallbackMethod =  "someBoom")
    public String home(){
        int a = 0, c = 1;
        int d = c/a;  // 抛出异常触发
        return "hello world";
    }

    public String someBoom(){
        return "wokao, 魂淡";
    }

    @RequestMapping("/zuul/test")
    public String zuulTest(@RequestHeader String requestFilterParam){
        return "requestFilterParam: " + requestFilterParam + " .--client one";
    }
}

  通过网关访问  http://localhost:8601/client-one/zuul/test

  可以看到 2个过滤器都生效了..

  

 

三、Zuul 断路器

  如果某个微服务炸了,zuul可以实现断路器的功能

  从依赖来看,是基于hystrix

  

  新增fallback类   MyZuulFallbackProvider.java  

/**
 * 默认回退
 */
public class MyZuulFallbackProvider implements FallbackProvider{
    /**
     * 为那个微服务提供回退: *\null为 所有
     * @return 这里不是eureka的serviceId,而是zuul.routes下的值,比如为[eureka-client-one]断路,则return "clientOne"
     */
    @Override
    public String getRoute() {
        return null;
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return 200;
            }

            @Override
            public String getStatusText() throws IOException {
                return "OK";
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("zuul fallback".getBytes());   // 回退信息
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return headers;
            }
        };
    }
}

  启动类加入使其生效

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class EurekaClientZuulApplication {

    @Bean
    public ZuulRequestFilter requestFilter(){
        return new ZuulRequestFilter();
    }

    @Bean
    public ZuulResponseFilter responseFilter(){
        return new ZuulResponseFilter();
    }

    @Bean
    public FallbackProvider fallbackProvider(){
        return new MyZuulFallbackProvider();
    }

    public static void main(String[] args) {
        SpringApplication.run(EurekaClientZuulApplication.class, args);
    }
}

 

  现在把[eureka-client-one]关闭,zuul路由访问必定报错,触发fallback

  访问   http://localhost:8601/client-one/zuul/test

  

 

posted on 2018-09-09 22:17  江湖吹风  阅读(673)  评论(0编辑  收藏  举报

renzku