本文共 4289 字,大约阅读时间需要 14 分钟。
Zuul是一种基于7层的应用程序网关,它提供了动态路由、监控、服务容错、安全等方面的保障,是微服务中的统一入口,由这个入口来管理所有请求调用的路径。
项目服务中各种各样的请求随时可能导致生产环境故障而没有预警,因此我们需要一个允许我们快速改变行为以对这些情况做出反应的系统。
Zuul使用了各种不同类型的过滤器,这使我们能够快速,灵活地将功能应用于边缘服务。这些过滤器帮助我们执行以下功能:
身份验证和安全性-识别每种资源的身份验证要求,并拒绝不满足要求的请求。
洞察和监控-在边缘跟踪有意义的数据和统计信息,以便为我们提供准确的生产视图。
动态路由-根据需要将请求动态路由到不同的后端群集。
压力测试-逐渐增加到群集的流量以评估性能。
减载-为每种类型的请求分配容量,并丢弃超出限制的请求。
静态响应处理-直接在边缘构建一些响应,而不是将其转发到内部集群
依赖jar包
org.springframework.cloud spring-cloud-starter-netflix-zuul org.springframework.cloud spring-cloud-starter-netflix-eureka-client
启动类,@EnableZuulProxy包含了eureka客户端注册
@SpringBootApplication@EnableZuulProxypublic class ZuulApplication { public static void main(String[] args) { SpringApplication.run(ZuulApplication.class, args); }}
配置文件,注册到注册中心,即可完成最简单的网关搭建。
server: port: 9000spring: application: name: myZuuleureka: client: service-url: defaultZone: http://eurekaServer1.com:18001/eureka/ instance: instance-id: ${ spring.cloud.client.ip-address}:${ server.port} prefer-ip-address: true
启动两个order微服务,一个接口返回getOrderInfo ok 1,一个接口返回getOrderInfo ok 2,通过zuul访问实现负载均衡。
order:19201
@GetMapping("/getOrderInfo") public String getOrderInfo() { return "getOrderInfo ok 1"; }
order:19202
@GetMapping("/getOrderInfo") public String getOrderInfo() { return "getOrderInfo ok 2"; }
查看注册中心服务列表,注册成功。
通过网关访问服务,因为没有任何网关配置,所以默认访问路径为:服务名+接口路径。
实现负载均衡。
zuul: routes: # 自定义名称 order-service: path: /order-service/** service-id: order
zuul: routes: # 自定义名称 order-service: path: /order-service/** service-id: order # 访问前缀 prefix: /api # 转到后台服务时移除前缀 strip-prefix: true
如果配置为false,url地址会拼接上api。
order服务新增一个接口,获取token。
@RequestMapping("/token") public String getToken(HttpServletRequest req){ String token = req.getHeader("token"); return "token:"+token; }
通过网关访问获得token
禁止传播token配置
zuul: routes: # 自定义名称 order-service: path: /order-service/** service-id: order prefix: /api strip-prefix: true # 不向微服务传播header中的token sensitive-headers: token
order服务获取不到token了。
Zuul的大部分功能都是通过过滤器实现。
Zuul中一共包含了4种过滤器,分别如下:
只演示一个前置拦截器,其他拦截器使用方式一样,通过一个FilterConstants.PRE_TYPE区分。
@Componentpublic class PreFilter extends ZuulFilter { /** * 过滤器是否生效 */ @Override public boolean shouldFilter() { //获取上下文 RequestContext requestContext = RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); String uri = request.getRequestURI(); System.out.println("PreFilter uri:" + uri); //只有此接口/api/order-service/userOrder/token才被拦截 String checkUri = "/api/order-service/userOrder/token"; if (checkUri.equalsIgnoreCase(uri)) { return true; } return false; } /** * 过滤器生效后执行逻辑 * @return */ @Override public Object run() { System.out.println("执行PreFilter拦截处理!"); //获取上下文 RequestContext requestContext = RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); String token = request.getHeader("token"); System.out.println("PreFilter 获取token:" + token); if (StringUtils.isEmpty(token)) { requestContext.setSendZuulResponse(false);// 过滤该请求,不对其进行路由 requestContext.setResponseStatusCode(401);// 返回错误码 requestContext.setResponseBody("token is empty");// 返回错误内容 } else { requestContext.setSendZuulResponse(true);// 对该请求进行路由 requestContext.setResponseStatusCode(200); } return null; } @Override public String filterType() { //前置过滤器 return FilterConstants.PRE_TYPE; } @Override public int filterOrder() { //优先级,数字越大,优先级越低 return 0; }}
调用普通接口,不走拦截器处理逻辑。
调用需要被拦截的接口:/api/order-service/userOrder/token
token为空时,请求不通过。
加入token后,请求通过。
转载地址:http://zmlrb.baihongyu.com/