赞
踩
本文内容基于《Spring Cloud微服务实战》,翟永超著。
通过上文所述的Spring Cloud Eureka实现高可用的服务注册中心以及实现微服务的注册与发现、Spring Cloud Ribbon或Spring Cloud Feign实现服务间负载均衡的接口调用、Spring Cloud Hystrix实现线程隔离并加入熔断机制,以避免在微服务架构中因个别服务出现异常而引起级联故障蔓延,此时能实现下图所示架构:
Open Service是一个对外的RESTful API服务,它通过F5、Nginx等网络设备或工具软件实现对各个微服务的路由与负载均衡,并公开给外部的客户端调用。
问题:
解决方案:
- package com.yeta.apigateway.filter;
-
- import com.netflix.zuul.ZuulFilter;
- import com.netflix.zuul.context.RequestContext;
- import com.netflix.zuul.exception.ZuulException;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
-
- import javax.servlet.http.HttpServletRequest;
-
- /**
- * 在请求被路由之前检查HttpServletRequest中是否有accessToken参数,若有就进行路由,若没有就拒绝访问,返回401 Unauthorized错误
- * @author YETA
- * @date 2019/03/15/17:54
- */
- public class AccessFilter extends ZuulFilter {
-
- private static Logger log = LoggerFactory.getLogger(ZuulFilter.class);
-
- /**
- * 过滤器的类型
- * pre表示在请求被路由之前执行
- * routing表示在路由请求时被调用
- * post表示在routing和error过滤器之后被调用
- * error表示处理请求时发生错误时被调用
- * @return
- */
- @Override
- public String filterType() {
- return "pre";
- }
-
- /**
- * 过滤器的执行顺序
- * 数字越小优先级越高
- * @return
- */
- @Override
- public int filterOrder() {
- return 0;
- }
-
- /**
- * 判断该过滤器是否需要被执行
- * @return
- */
- @Override
- public boolean shouldFilter() {
- return true;
- }
-
- /**
- * 过滤器的具体逻辑
- * @return
- * @throws ZuulException
- */
- @Override
- public Object run() throws ZuulException {
- RequestContext requestContext = RequestContext.getCurrentContext();
- HttpServletRequest request = requestContext.getRequest();
-
- log.info("send {} request to {}", request.getMethod(), request.getRequestURL().toString());
-
- Object accessToken = request.getParameter("accessToken");
- if (accessToken == null) {
- log.warn("access token is empty");
- requestContext.setSendZuulResponse(false); //不进行路由
- requestContext.setResponseStatusCode(401); //设置返回错误码
- requestContext.setResponseBody("access token is empty"); //设置返回内容
- return null;
- }
-
- log.info("access token is ok");
- return null;
- }
- }
单实例配置
多实例配置
当为Spring Cloud Zuul构建的API网关服务引入Spring Cloud Eureka之后,它为Eureka中的每个服务都自动创建一个默认路由规则,以服务名作为请求前缀。
系统在迭代过程中,有时候会需要为一组互相配合的微服务定义一个版本标识来方便管理它们的版本关系,根据这个标识可以很容易知道这些服务需要一起启动并配合使用。如类似命名:userservice-v1、orderservice-v1。
在Zuul中,路径匹配的路径表达式采用了Ant风格定义。
通配符 | 说明 |
? | 匹配任意单个字符 |
/user-service/? | 匹配/user-service/a、/user-service/b |
* | 匹配任意数量的字符 |
/user-service/* | 匹配/user-service/a、/user-service/aa、/user-service/bb |
** | 匹配任意数量的字符,支持多级目录 |
/user-service/** | 匹配/user-service/a/b |
如果需要考虑路由规则的顺序问题,参考用YAML文件来配置,properties文件无法保证有序。
默认情况下,Spring Cloud Zuul在请求路由时,会过滤掉HTTP请求头信息中的一些敏感信息,防止它们被传递到下游的外部服务器,包括Cookie、Set-Cookie、Authorization三个属性。
Zulul包含hystrix和ribbon的依赖,所以拥有现成隔离和断路器的自我保护功能,以及对服务调用的客户端负载均衡功能。当使用path与url的映射关系来配置路由规则的时候,对于路由转发的请求不会采用HystrixCommand来包装,所以这类路由请求没有线程隔离和断路器的保护,并且也不会有负载均衡的能力。
参考
https://blog.csdn.net/qq_31349087/article/details/79614184
https://www.jb51.net/article/138773.htm
- /**
- * 在自定义过滤器中处理异常
- * @author YETA
- * @date 2019/03/15/17:54
- */
- @Component
- public class ThrowExceptionFilter extends ZuulFilter {
-
- private static Logger log = LoggerFactory.getLogger(ZuulFilter.class);
-
- /**
- * 过滤器的类型
- * pre表示在请求被路由之前执行
- * routing表示在路由请求时被调用
- * post表示在routing和error过滤器之后被调用
- * error表示处理请求时发生错误时被调用
- * @return
- */
- @Override
- public String filterType() {
- return PRE_TYPE;
- }
-
- /**
- * 过滤器的执行顺序
- * 数字越小优先级越高
- * @return
- */
- @Override
- public int filterOrder() {
- return PRE_DECORATION_FILTER_ORDER - 1; // run before PreDecoration
- }
-
- /**
- * 判断该过滤器是否需要被执行
- * @return
- */
- @Override
- public boolean shouldFilter() {
- return true;
- }
-
- /**
- * 过滤器的具体逻辑
- * @return
- * @throws ZuulException
- */
- @Override
- public Object run() throws ZuulException {
- int a = 1 / 0;
- return null;
- }
- }
- /**
- * 异常处理接口
- * @author YETA
- * @date 2019/03/19/15:53
- */
- @RestController
- public class ErrorHandlerController implements ErrorController {
-
- @Override
- public String getErrorPath() {
- return "/error";
- }
-
- @GetMapping(value = "/error")
- public Object error(HttpServletRequest request) {
- Map<String, Object> result = new HashMap<>();
- result.put("status_code", request.getAttribute("javax.servlet.error.status_code"));
- StringBuffer sb = new StringBuffer(request.getAttribute("javax.servlet.error.message").toString());
- Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
- while (exception.getCause() != null) {
- sb.append(" ").append(exception.getCause().getMessage());
- exception = (Exception) exception.getCause();
- }
- result.put("message", sb);
-
- return result;
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。