JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

代码实战SpringCloud服务网关Zuul

wys521 2024-10-17 15:48:37 精选教程 17 ℃ 0 评论

为什么需要网关服务

服务网关的要素

  • 稳定性,高可用
  • 性能、并发性
  • 安全性
  • 扩展性

常用的网关方案

  • nginx+lua
  • kong

基于nginx,商业软件付费

  • Tyk

开源的,轻量级服务网关,go语言开发

  • SpringCloud Zuul

Zuul的特点

  • 路由+过滤器=Zuul
  • 核心是一系列过滤器
  • zuul的四种过滤器
  1. 前置(pre)
  2. 后置(post)
  3. 路由(route)
  4. 错误(error)

请求生命周期

创建网关项目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:

典型应用场景

前置(Pre)

  • 限流
  • 鉴权
  • 参数校验调整

后置(Post)

  • 统计
  • 日志

Zuul的高可用

  • 多个Zuul节点注册到Eureka Server
  • Nginx和Zuul “混搭”

Zuul过滤器案例

  • 前置过滤器(Pre)

案例一:所有通过Zuul过滤器的请求都必须携带一个参数token且值不为空

/**
 * 需求:参数校验
 * 所有通过Zuul过滤器的请求都必须携带一个参数token且值不为空
 * */
@Component
public 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信息

@Component
public 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",UUID.randomUUID().toString());
 return null;
 }
}

Zuul:限流

Zuul作为服务网关每个请求都会到达Zuul,很适合在Zuul上对api做限流保护,防止网络攻击。比如,某个api是发送短信的,可能就需要限制客户端的请求速率,从而在一定程度上抵御短信轰炸攻击,降低损失。

Zuul的限流放在前置过滤器中,具体在请求被转发之前调用,如果前置过滤器有多个操作,限流应该前置。

限流的方案有很多,有一种叫令牌桶限流,如下图:

限流拦截器

public class RateLimiterFilter extends ZuulFilter {
 //每秒往令牌桶放100的令牌
 private static final RateLimiter rateLimiter=RateLimiter.create(100) ;
 @Override
 public String filterType() {
 return PRE_TYPE;
 }
 @Override
 public int filterOrder() {
 return SERVLET_DETECTION_FILTER_ORDER-1;
 }
 @Override
 public boolean shouldFilter() {
 return true;
 }
 @Override
 public Object run() throws ZuulException {
 boolean getToken= rateLimiter.tryAcquire();
 if(!getToken){ //没有获取到令牌
 //请求直接返回
 }
 return null;
 }
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表