SpringCloud之网关zuul
1、微服务网关介绍和使用场景
1)什么是网关
API Gateway,是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能 提供路由请求、鉴权、监控、缓存、限流等功能
统一接入
智能路由
AB测试、灰度测试
负载均衡、容灾处理
日志埋点(类似Nignx日志)
流量监控
限流处理
服务降级
安全防护
鉴权处理
监控
机器网络隔离
2)主流的网关
zuul:是Netflix开源的微服务网关,和Eureka,Ribbon,Hystrix等组件配合使用,Zuul 2.0比1.0的性能提高很多
kong: 由Mashape公司开源的,基于Nginx的API gateway
nginx+lua:是一个高性能的HTTP和反向代理服务器,lua是脚本语言,让Nginx执行Lua脚本,并且高并发、非阻塞的处理各种请求
2、SpringCloud的网关组件zuul基本使用
1、加入依赖
<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> </dependency> </dependencies>
2、启动类加入注解 @EnableZuulProxy
默认集成断路器 @EnableCircuitBreaker
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication @EnableZuulProxy public class ApiGatewayApplication { public static void main(String[] args) { SpringApplication.run(ApiGatewayApplication.class, args); } }
默认访问规则
http://gateway:port/service-id/**
例子:默认 /order-service/api/v1/order/save?user_id=2&product_id=1
自定义 /xdclass_order/api/v1/order/save?user_id=2&product_id=1
自定义路由转发:
zuul:
routes:
order-service: /apigateway/**
环境隔离配置:
需求 :不想让默认的服务对外暴露接口
/order-service/api/v1/order/save
配置:
zuul:
ignored-patterns: /*-service/api/v1/order/save
yml 配置:
server:
port: 9000
#服务的名称
spring:
application:
name: api-gateway
#指定注册中心地址
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
#/order-service/api/v1/order/save?user_id=2&product_id=1
#自定义路由映射(注意有路由覆盖的地方,所以一般会加个模块/apigateway/order, order模块)
zuul:
routes:
order-service: /apigateway/order/**
product-service: /apigateway/product/**
#统一入口为上面的配置,其他入口忽略(即不能通过 /order-service/api/v1/order/save 来访问)
ignored-patterns: /*-service/**
#处理http请求头为空的问题(默认的过滤集合包含 "cookie" ,所以后端拿不到 “cookie”, 将集合过滤设为空)
sensitive-headers:
3、Zuul常用问题分析和网关过滤器原理分析
Zuul网关原理和过滤器生命周期,
1、路由名称定义问题
路由映射重复覆盖问题
2、Http请求头过滤问题(如cookie)
3、过滤器执行顺序问题 ,过滤器的order值越小,越先执行
4、共享RequestContext,上下文对象
4、自定义Zuul过滤器实现登录鉴权
简介:自定义Zuul过滤器实现登录鉴权
1、新建一个filter包
2、新建一个类,实现ZuulFilter,重写里面的方法
3、在类顶部加注解,@Component,让Spring扫描
package net.xdclass.apigateway.filter; 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.http.HttpStatus; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE; /** * 登录过滤器 */ @Component public class LoginFilter extends ZuulFilter { /** * 过滤器类型,前置过滤器 * * @return */ @Override public String filterType() { return PRE_TYPE; } /** * 过滤器顺序,越小越先执行 * * @return */ @Override public int filterOrder() { return 4; } /** * 过滤器是否生效 * * @return */ @Override public boolean shouldFilter() { RequestContext requestContext = RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); //System.out.println(request.getRequestURI()); ///apigateway/product/api/v1/product/list //System.out.println(request.getRequestURL()); //http://localhost:9000/apigateway/product/api/v1/product/list //ACL if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())) { return true; } else if ("/apigateway/order/api/v1/order/list".equalsIgnoreCase(request.getRequestURI())) { return false; } else if ("/apigateway/order/api/v1/order/find".equalsIgnoreCase(request.getRequestURI())) { return true; } return false; } /** * 业务逻辑 * * @return * @throws ZuulException */ @Override public Object run() throws ZuulException { //JWT RequestContext requestContext = RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); //token对象 String token = request.getHeader("token"); if (StringUtils.isBlank((token))) { token = request.getParameter("token"); } //登录校验逻辑 根据公司情况自定义 JWT if (StringUtils.isBlank(token)) { requestContext.setSendZuulResponse(false); requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value()); } return null; } }
访问“/apigateway/order/api/v1/order/save”时需要鉴权
5、高并发情况下接口限流特技
简介:谷歌guava框架介绍,网关限流使用
对订单接口限流:
package net.xdclass.apigateway.filter; import com.google.common.util.concurrent.RateLimiter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE; /** * 订单限流 */ @Component public class OrderRateLimiterFilter extends ZuulFilter { //每秒产生1000个令牌 private static final RateLimiter RATE_LIMITER = RateLimiter.create(1000); @Override public String filterType() { return PRE_TYPE; } @Override public int filterOrder() { return -4; } @Override public boolean shouldFilter() { RequestContext requestContext = RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); //只对订单接口限流 if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())){ return true; } return false; } @Override public Object run() throws ZuulException { RequestContext requestContext = RequestContext.getCurrentContext(); if(!RATE_LIMITER.tryAcquire()){ requestContext.setSendZuulResponse(false); requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value()); } return null; } }
每秒1000个请求,超出则丢弃
6、Zuul微服务网关集群搭建
简介:微服务网关Zull集群搭建
1、nginx+lvs+keepalive 避免Nginx挂掉
https://www.cnblogs.com/liuyisai/p/5990645.html
启动另一个api-gateway,将1000读取从配置中心读取,2台api则为500
private static final RateLimiter RATE_LIMITER = RateLimiter.create(1000);