SpringClub06-zuul 网关

1.zuul API网关

zuul API 网关,为微服务应用提供统一的对外访问接口。
zuul 还提供过滤器,对所有微服务提供统一的请求校验。

1.1 新建 sp11-zuul 项目

SpringClub06-zuul 网关_第1张图片

1.2 添加依赖

SpringClub06-zuul 网关_第2张图片

1.2.1 pom.xml

  • 需要添加 sp01-commons 依赖


    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.2.1.RELEASE
         
    
    cn.tedu
    sp11-zuul
    0.0.1-SNAPSHOT
    sp11-zuul
    Demo project for Spring Boot

    
        1.8
        Hoxton.RELEASE
    

    
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-zuul
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
        
            cn.tedu
            sp01-commons
            0.0.1-SNAPSHOT
        
    

    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                ${spring-cloud.version}
                pom
                import
            
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

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/eureka

zuul:
  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
@SpringBootApplication
public class Sp11ZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(Sp11ZuulApplication.class, args);
    }
}

1.5 启动项目

启动服务

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;
@Component
public 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 访问测试

3. zuul 集成 ribbon

3.1 zuul + ribbon 负载均衡

zuul 已经集成了 ribbon,默认已经实现了负载均衡

3.2 zuul + ribbon 重试

3.2.1 pom.xml 添加 spring-retry 依赖

  • 需要 spring-retry 依赖

    org.springframework.retry
    spring-retry

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/eureka

zuul:
  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;
@Component
public 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;
@Component
public 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/eureka

zuul:
  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

5.2 开启监控

启动 sp08-hystrix-dashboard,填入 zuul 的监控端点路径,开启监控
http://localhost:4001/hystrix
填入监控端点:
http://localhost:3001/actuator/hystrix.stream
监控
必须通过zuul网关访问后台服务才会长生监控数据

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")

监控

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:

你可能感兴趣的:(intellij-idea,springboot)