为什么需要网关服务
![6e3407dacc05fb940ca5894066e8f014.png](https://img-blog.csdnimg.cn/img_convert/6e3407dacc05fb940ca5894066e8f014.png)
服务网关的要素
- 稳定性,高可用
- 性能、并发性
- 安全性
- 扩展性
常用的网关方案
- nginx+lua
- kong
基于nginx,商业软件付费
- Tyk
开源的,轻量级服务网关,go语言开发
- SpringCloud Zuul
Zuul的特点
- 路由+过滤器=Zuul
- 核心是一系列过滤器
- zuul的四种过滤器
- 前置(pre)
- 后置(post)
- 路由(route)
- 错误(error)
![6c1832cd330cd9d7ef7ff720bf2e0268.png](https://img-blog.csdnimg.cn/img_convert/6c1832cd330cd9d7ef7ff720bf2e0268.png)
请求生命周期
![b38d0bc884f5d8ef0e940f68672ee8af.png](https://img-blog.csdnimg.cn/img_convert/b38d0bc884f5d8ef0e940f68672ee8af.png)
创建网关项目api-gateway
Cloud Routing-->Zuul
Cloud Discovery->eureka Discovery
主类添加注解:@EnableZuulProxy
需求:通过网关访问product服务的/msg接口
http://localhost:9000/product/msg
9000:代表网关服务的端口号
product:代表要访问的服务名
msg:代表访问product服务的接口地址
自定义路由
zuul:
routes:
myProduct:(自定义名称)
path:/myProduct/** (浏览器访问路径)
serviceId:PRODUCT
简洁写法:
PRODUCT:/myProduct/**
查看所有路由
配置:
management:
security:
enabled: false
访问: localhost:port/application/routes
权限问题: management.security.enabled=false
排除某些路由
不希望某些接口被外部访问
ignored-patterns:
- 要排除的url
zuul: ignored-patterns: - /order/order/send - /myorder/order/send
通配符写法:
zuul: ignored-patterns: - /**/order/send
Cookie
通过网关获取cookie,sensitive-headers设置为空
zuul: sensitive-headers:
典型应用场景
![573802ea8cdb86a73b43af5506cd901b.png](https://img-blog.csdnimg.cn/img_convert/573802ea8cdb86a73b43af5506cd901b.png)
前置(Pre)
- 限流
- 鉴权
- 参数校验调整
后置(Post)
- 统计
- 日志
Zuul的高可用
- 多个Zuul节点注册到Eureka Server
- Nginx和Zuul “混搭”
Zuul过滤器案例
- 前置过滤器(Pre)
案例一:所有通过Zuul过滤器的请求都必须携带一个参数token且值不为空
/** * 需求:参数校验 * 所有通过Zuul过滤器的请求都必须携带一个参数token且值不为空 * */@Componentpublic class TokenFilter extends ZuulFilter { //定义过滤器类型 @Override public String filterType() { return PRE_TYPE; } //定义过滤器顺序,值越小越靠前 @Override public int filterOrder() { return PRE_DECORATION_FILTER_ORDER-1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { //所有通过Zuul过滤器的请求都必须携带一个参数token且值不为空 HttpServletRequest RequestContext requestContext= RequestContext.getCurrentContext(); HttpServletRequest request= requestContext.getRequest(); String token=request.getParameter("token"); if(StringUtils.isEmpty(token)){ requestContext.setSendZuulResponse(false); requestContext.setResponseStatusCode(401); } return null; }}
- 后置过滤器
需求:请求的响应头加入一段header信息
@Componentpublic class AddResponseHeaderFilter extends ZuulFilter { @Override public String filterType() { return POST_TYPE; } @Override public int filterOrder() { return SEND_RESPONSE_FILTER_ORDER-1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { RequestContext requestContext= RequestContext.getCurrentContext(); HttpServletResponse response= requestContext.getResponse(); response.addHeader("open