1.zuul API网关

zuul API 网关,为微服务利用提供对立的对外拜访接口。
zuul 还提供过滤器,对所有微服务提供对立的申请校验。

1.1 新建 sp11-zuul 我的项目

1.2 增加依赖

1.2.1 pom.xml

  • 须要增加 sp01-commons 依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.2.1.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <groupId>cn.tedu</groupId>    <artifactId>sp11-zuul</artifactId>    <version>0.0.1-SNAPSHOT</version>    <name>sp11-zuul</name>    <description>Demo project for Spring Boot</description>    <properties>        <java.version>1.8</java.version>        <spring-cloud.version>Hoxton.RELEASE</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-test</artifactId>            <scope>test</scope>            <exclusions>                <exclusion>                    <groupId>org.junit.vintage</groupId>                    <artifactId>junit-vintage-engine</artifactId>                </exclusion>            </exclusions>        </dependency>        <dependency>            <groupId>cn.tedu</groupId>            <artifactId>sp01-commons</artifactId>            <version>0.0.1-SNAPSHOT</version>        </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>

1.3 批改 application.yml 文件

  • zuul 路由配置能够省略,缺省以服务 id 作为拜访门路
spring:  application:    name: zuul    server:  port: 3001  eureka:  client:    service-url:      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eurekazuul:  routes:    item-service: /item-service/**    user-service: /user-service/**    order-service: /order-service/**

1.4 主程序增加 @EnableZuulProxy 注解

package cn.tedu.sp11;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.netflix.zuul.EnableZuulProxy;@EnableZuulProxy@EnableDiscoveryClient@SpringBootApplicationpublic class Sp11ZuulApplication {    public static void main(String[] args) {        SpringApplication.run(Sp11ZuulApplication.class, args);    }}

1.5 启动我的项目

  • http://eureka1:2001
  • http://localhost:3001/item-service/35
  • `http://localhost:3001/i
  • tem-service/decreaseNumber`
    应用postman,POST发送以下格局数据:
    [{"id":1, "name":"abc", "number":23},{"id":2, "name":"def", "number":11}]
  • http://localhost:3001/user-service/7
  • http://localhost:3001/user-service/7/score?score=100
  • http://localhost:3001/order-service/123abc
  • http://localhost:3001/order-service/

2. zuul 申请过滤

2.1 定义过滤器,继承 ZuulFilter

在 sp11-zuul 我的项目中新建过滤器类

package com.tedu.sp11.filter;import cn.tedu.web.util.JsonResult;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;import com.netflix.zuul.exception.ZuulException;import org.apache.commons.lang.StringUtils;import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;@Componentpublic class AccessFilter extends ZuulFilter {    //过滤器类型:pre,post,routing,error @Override public String filterType() {        //return "pre";//前置过滤器 return FilterConstants.PRE_TYPE;    }    //过滤器插入的地位 @Override public int filterOrder() {        return 6;//放到第六个地位 }    //对用户申请进行判断,是否执行过滤代码 @Override public boolean shouldFilter() {        //只对 item-service 调用进行过滤,如果调用 user-service 和 order-service,不执行过滤代码 //取得调用服务的id RequestContext context=RequestContext.getCurrentContext();        String serviceId= (String) context.get(FilterConstants.SERVICE_ID_KEY);        return "item-service".equalsIgnoreCase(serviceId);    }    //过滤代码 @Override public Object run() throws ZuulException {        //取得request对象 RequestContext context=RequestContext.getCurrentContext();        HttpServletRequest request=context.getRequest();        //收到token参数 String token=request.getParameter("token");        //如果没有,阻止拜访,并间接向客户端返回响应 if (StringUtils.isBlank(token)){            //阻止持续拜访 context.setSendZuulResponse(false);            //向客户端返回响应 JsonResult{code:401,msg:not,login,data:null} String json=JsonResult.err().code(JsonResult.NOT_LOGIN).msg("not login").toString();            context.addZuulResponseHeader("Content-Type","application/json;charset=UTF-8" );            context.setResponseBody(json);        }        return null;//返回值没有任何作用 }}

2.2 拜访测试

  • 没有token参数不容许拜访
    http://localhost:3001/item-service/35
  • 有token参数能够拜访
    http://localhost:3001/item-service/35?token=1234

3. zuul 集成 ribbon

3.1 zuul + ribbon 负载平衡

zuul 曾经集成了 ribbon,默认曾经实现了负载平衡

3.2 zuul + ribbon 重试

3.2.1 pom.xml 增加 spring-retry 依赖

  • 须要 spring-retry 依赖
<dependency>    <groupId>org.springframework.retry</groupId>    <artifactId>spring-retry</artifactId></dependency>

3.2.2 配置 zuul 开启重试,并配置 ribbon 重试参数

  • 须要开启重试,默认不开启 zuul:retryable: true
spring:  application:    name: zuul    server:  port: 3001  eureka:  client:    service-url:      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eurekazuul:  retryable: true#  routes:#    item-service: /item-service/**#    user-service: /user-service/**#    order-service: /order-service/**    ribbon:  ConnectTimeout: 1000  ReadTimeout: 1000  MaxAutoRetriesNextServer: 1  MaxAutoRetries: 1

4. zuul 集成 hystrix

0配置,曾经启用了hystrix

4.1 zuul + hystrix 降级

4.1.1 创立降级类

  • getRoute() 办法中指定利用此降级类的服务id,星号或null值能够通配所有服务
ItemServiceFallback
package com.tedu.sp11.fallback;import cn.tedu.web.util.JsonResult;import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpStatus;import org.springframework.http.client.ClientHttpResponse;import org.springframework.stereotype.Component;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.nio.charset.StandardCharsets;@Componentpublic class ItemFB implements FallbackProvider {    //返回一个 service id,针对指定的服务进行降级解决 //返回 "*" 或者 null,对所有服务都利用这个降级类 @Override public String getRoute() {        return "item-service";    }    //降级响应,返回一个封装响应数据的 response 对象 @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 HttpStatus.OK.value();            }            @Override public String getStatusText() throws IOException {                return HttpStatus.OK.getReasonPhrase();            }            @Override public void close() {            }            @Override public InputStream getBody() throws IOException {                //JsonResult{code:401,msg:调用商品失败,data:null} String json = JsonResult.err().msg("调用商品失败").toString();                return new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));            }            @Override public HttpHeaders getHeaders() {                //content-Type:application/json;charset=UTF-8 HttpHeaders headers = new HttpHeaders();                headers.add("content-Type", "application/json;charset=UTF-8");                return headers;            }        };    }}
OrderServiceFallback
package com.tedu.sp11.fallback;import cn.tedu.web.util.JsonResult;import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpStatus;import org.springframework.http.client.ClientHttpResponse;import org.springframework.stereotype.Component;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.nio.charset.StandardCharsets;@Componentpublic class OrderFB implements FallbackProvider {    //返回一个 service id,针对指定的服务进行降级解决 //返回 "*" 或者 null,对所有服务都利用这个降级类 @Override public String getRoute() {        return "order-service";    }    //降级响应,返回一个封装响应数据的 response 对象 @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 HttpStatus.OK.value();            }            @Override public String getStatusText() throws IOException {                return HttpStatus.OK.getReasonPhrase();            }            @Override public void close() {            }            @Override public InputStream getBody() throws IOException {                //JsonResult{code:401,msg:调用商品失败,data:null} String json = JsonResult.err().msg("调用订单服务失败").toString();                return new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));            }            @Override public HttpHeaders getHeaders() {                //content-Type:application/json;charset=UTF-8 HttpHeaders headers = new HttpHeaders();                headers.add("content-Type", "application/json;charset=UTF-8");                return headers;            }        };    }}

4.2 升高 hystrix 超时工夫,以便测试降级

spring:  application:    name: zuul    server:  port: 3001  eureka:  client:    service-url:      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eurekazuul:  retryable: true    ribbon:  ConnectTimeout: 1000  ReadTimeout: 2000  MaxAutoRetriesNextServer: 1  MaxAutoRetries: 1  hystrix:  command:    default:      execution:        isolation:          thread:            timeoutInMilliseconds: 500

4.3 启动服务,测试降级

http://localhost:3001/item-service/35

5. zuul + hystrix 数据监控

5.1 裸露 hystrix.stream 监控端点

  • zuul 曾经蕴含 actuator 依赖
management:  endpoints:    web:      exposure:        include: hystrix.stream
  • 启动服务,查看裸露的监控端点
    http://localhost:3001/actuator
    http://localhost:3001/actuator/hystrix.stream

5.2 开启监控

启动 sp08-hystrix-dashboard,填入 zuul 的监控端点门路,开启监控
http://localhost:4001/hystrix
填入监控端点:
http://localhost:3001/actuator/hystrix.stream

必须通过zuul网关拜访后盾服务才会长生监控数据

  • http://localhost:3001/item-service/35
  • http://localhost:3001/item-service/decreaseNumber
    应用postman,POST发送以下格局数据:
    [{"id":1, "name":"abc", "number":23},{"id":2, "name":"def", "number":11}]
  • http://localhost:3001/user-service/7
  • http://localhost:3001/user-service/7/score?score=100
  • http://localhost:3001/order-service/123abc
  • http://localhost:3001/order-service/

6. zuul + turbine 聚合监控

6.1 批改 turbine 我的项目,聚合 zuul 服务实例

 spring:  application:    name: turbin    server:  port: 5001  eureka:  client:    service-url:      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka      turbine:  app-config: order-service, zuul  cluster-name-expression: new String("default")
  • 应用hystrix仪表盘, 对 turbine 监控端点进行监控, 此端点聚合了订单服务和zull网关服务的监控数据
    http://localhost:5001/turbine.stream

6.2 熔断测试

ab -n 20000 -c 50 http://localhost:3001/order-service/123abc

7. zuul Cookie过滤

zuul 会过滤敏感 http 协定头,默认过滤以下协定头:

  • Cookie
  • Set-Cookie
  • Authorization

能够设置 zuul 不过滤这些协定头

zuul:  sensitive-headers: