微服务组件:路由网关zuul
1. zuul介绍
zuul是在微服务中提供动态路由、监控、弹性和安全等边缘服务的框架。实现了开放服务的控制权限机制,而不去破坏微服务无状态的特点。
zuul主要功能:
① zuul URL映射
② zuul serviceId映射;
③ zuul过滤器;
2. zuul使用
2-1 启动服务提供端
java -jar -Dserver.port=8071 microservice-provider-user-0.0.1-SNAPSHOT.jar java -jar -Dserver.port=8072 microservice-provider-user-0.0.1-SNAPSHOT.jar
2-2 URL映射
所有/user1/**的访问都映射到http://127.0.0.1:8071/上
zuul: routes: movie: path: /user1/** # 想要映射到的路径 url: http://127.0.0.1:8071/ # 服务地址
启动API Gateway,@EnableZuulProxy启用zuul
@SpringBootApplication @EnableZuulProxy @EnableAutoConfiguration public class ZuulApiGatewayApplication { public static void main(String[] args) { SpringApplication.run(ZuulApiGatewayApplication.class, args); } }
访问:
http://127.0.0.1:8050/user1/1
2-3 serviceId映射
zuul查询eureka服务注册信息,将所有/user/**的访问都映射到microservice-provider-user服务提供端
eureka: instance: hostname: gateway client: serviceUrl: defaultZone: http://localhost:8762/eureka/,http://localhost:8761/eureka/ zuul: routes: movie: path: /user/** # 想要映射到的路径 service-id: microservice-provider-user # Eureka中的serviceId
访问:
http://127.0.0.1:8050/user/1
2-3 过滤器
利用zuul过滤器,可以实现对外服务的安全机制,通过安全措施保护客户端只能访问它应该访问到的资源;
/** * 校验请求的token参数 * * @author mengka * @date 2017/07/15. */ @Slf4j public class AccessFilter extends ZuulFilter { /** * 返回一个字符串代表过滤器的类型,在zuul中定义了四种不同的生命周期过滤器类型 * 1)pre:在请求被路由之前调用; * 2)route:在路由请求时候被调用; * 3)post:在routing和error过滤器之后被调用; * 4)error:处理请求时发生错误时被调用; * * @return */ @Override public String filterType() { return ZuulFilterTypeEnums.PRE.getName(); } /** * 通过int值来定义过滤器的执行顺序 * * @return */ @Override public int filterOrder() { return 50000; } /** * 返回一个boolean类型来判断该过滤器是否要执行 * * @return */ @Override public boolean shouldFilter() { return RequestContext.getCurrentContext().getRequest().getRequestURI().matches("/user/.*"); } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString())); Object accessToken = request.getParameter("accessToken"); if (accessToken == null) { log.warn("access token is empty"); ctx.setSendZuulResponse(false);//令zuul过滤该请求,不对其进行路由 ctx.setResponseStatusCode(401);//返回的错误码 return null; } log.info("access token ok"); return null; } }
@Configuration public class AppConfig { @Bean public AccessFilter accessFilter() { return new AccessFilter(); } }
测试token校验:
@Test public void test_zuul_token_filter_02() { log.info("test_zuul_token_filter_02.."); Response response = RestAssured.get("http://127.0.0.1:8050/user/2"); assertEquals(401, response.getStatusCode()); } @Test public void test_zuul_token_filter_01() { log.info("test_zuul_token_filter_01.."); Response response = RestAssured.get("http://127.0.0.1:8050/user/2?orgCode=123456&accessToken=123456"); assertEquals(200, response.getStatusCode()); String result = response.getBody().asString(); JSONObject jsonObject = JSON.parseObject(result); assertEquals("Tom", jsonObject.getString("username")); }