1 什么是网关
如果让客户端直接和各个微服务通信,可能会有很多问题:
(1)客户端会多次请求不同的微服务,增加了客户端的复杂性;
(2)存在跨域请求,在一定场景下处理相对复杂;
(3)认证复杂,每个微服务需要独立认证。
为了解决以上问题,需要在客户端和服务器端之间加一层(网关层),让所有的请求先经过网关,再打到微服务上。
网关实现方式:
Nginx+lua 一般为企业级的网关,zuul和spring cloud gateway 是业务级的网关,用于聚合微服务。
网关在服务架构中的作用:
2 zuul
(1)什么是Zuul
Zuul是Netflix开源的微服务网关。可以完成以下功能:身份认证与安全,审查与监控,动态路由,压力测试,负载分配,静态响应处理等。
zuul 目前有两个大的版本:Zuul1 和 Zuul2
Zuul1 是基于 Servlet 框架构建,采用的是阻塞和多线程方式,即一个线程处理一次连接请求,这种方式在内部延迟严重、设备故障较多情况下会引起存活的连接增多和线程增加的情况发生。
Zuul2 运行在异步和无阻塞框架上,每个 CPU 核一个线程,处理所有的请求和响应,请求和响应的生命周期是通过事件和回调来处理的,这种方式减少了线程数量,因此开销较小。
zuul GitHub:https://github.com/Netflix/zuul, 中文文档:https://www.springcloud.cc/spring-cloud-netflix.html
zuul包含了对请求的路由和过滤两个核心功能。其中路由负责将外部请求转发到具体的微服务上,是实现外部访问统一入口的基础。
而过滤功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础。
(2)路由
2.1 开启zuul
启动类上加上@EnableZuulProxy
2.2 配置路由规则
zuul:
routes:
provider-service: #路由id自定义
path: /provider-service/** #配置请求url的映射路径
#url: http://localhost:9090/ #映射路径对应的微服务地址
serviceId: provider-service #根据serviceId自动从注册中心获取地址并转发请求
#默认路由规则,路由id和微服务名称一致,path默认对应:微服务名称/**,以上可以简化不写。
zuul:
#路由排除
ignored-patterns: /**/provider/** #URL地址排除,排除所有包含/provider/的路径
#ignored-services: provider-service #服务名称排除
#路由前缀
prefix: /api
(3)过滤
默认类型:pre , routing, post, error
执行顺序:见上图;对于同类型,可以自定义执行顺序。
pre: 请求被路由到源服务器之前执行的过滤器;身份认证,选路由,请求日志
routing:处理将请求发送到源服务器的过滤器
post: 响应从源服务器返回时执行的过滤器;对响应增加HTTP头,收集统计和度量指标,将响应以流的方式发送给回客户端。
error: 上述阶段中出现错误时执行的过滤器。
自定义过滤器
案例:
@Component
public class CustomFilter extends ZuulFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(AccessFilter.class);
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
//获取请求上下文
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
//获取表单中的token
String token = request.getParameter("token");
//业务逻辑处理
if (token==null){
LOGGER.warn("token is null");
//请求结束,不再继续向下请求
rc.setSendZuulResponse(false);
//响应状态码,401,没有权限
rc.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
//响应类型
rc.getResponse().setContentType("application/json;charset=utf-8");
PrintWriter writer = null;
try {
writer = rc.getResponse().getWriter();
//响应内容
writer.print("{\"message\":\"" + org.springframework.http.HttpStatus.UNAUTHORIZED.getReasonPhrase() + "\"}");
}catch (IOException e){
LOGGER.error("异常");
}finally {
if (null != writer){
writer.close();
}
}
}else {
LOGGER.info("token is ok");
}
return null;
}
}
(4)限流
文档: https://github.com/marcosbarbero/spring-cloud-zuul-ratelimit
令牌桶算法:
参考:https://segmentfault.com/a/1190000020745218
3 spring cloud gateway
Spring Cloud Gateway 是Spring Cloud的一个全新的API网关项目,目的是为了替换掉Zuul1。Gateway可以与Spring Cloud Discovery Client(如Eureka)、Ribbon、Hystrix等组件配合使用,
实现路由转发、负载均衡、熔断等功能,并且Gateway还内置了限流过滤器,实现了限流的功能。
spring cloud gateway 官方文档:https://docs.spring.io/spring-cloud-gateway/docs/2.2.9.RELEASE/reference/html/
参考文献:
https://www.cnblogs.com/xuweiweiwoaini/p/13814388.html
https://zhuanlan.zhihu.com/p/101341556
https://zhuanlan.zhihu.com/p/91865256