微服务业务中,涉及到CMS系统,需要集成多个功能模块的配置功能。同时CMS系统也提供一些本系统的功能API,如鉴权接口等。
我们设想的实现是,业务模块的管理功能,由业务模块提供接口。CMS做一层鉴权和转发。我们在CMS中引入网关。
spring框架中比较流行的gateway框架有 Spring Cloud Gateway 和 zuul 。
由于spring-cloud-gateway 基于 webFlux进行开发,与springmvc不是一套体系,并且有冲突,必须排除掉web-stater的相关引用才能正常使用,因此使用了zuul来进行开发。
zuul
zuul网关启动
- 配置 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>1.5.18</version>
</dependency>
-
标记注解
给启动类打上注解 @EnableZuulProxy -
配置转发策略
详细的转发配置请参考官网。这里给出一个配置示例。
zuul.routes.users.path
: 匹配路径
zuul.routes.users.serviceId
:配置引用的服务id
zuul.routes.users.stripPrefix
:是否去除前缀,转发路径是否去除匹配路径上的前缀,如下例true时,/my/users/a 将被转发到 /a ,false时转发到 /my/users/a
ribbon.eureka.enabled
: 置位false取消eureka服务端依赖,直接使用本地转发地址配置
users.ribbon.listOfServers
:对应serviceId的转发地址配置。
一般来说,上面配置, users.ribbon.listOfServers配置在对应环境配置中,其他配置配置在统一配置文件中,解耦路由配置对对接环境的依赖
zuul:
routes:
users:
path: /myusers/**
serviceId: users
stripPrefix: false
ribbon:
eureka:
enabled: false
users:
ribbon:
listOfServers: example.com,google.com
集成过程中遇到的问题
java.lang.NoClassDefFoundError: com/netflix/hystrix/metric/consumer/HystrixDashboardStream
hystrix 版本问题,其他组件引用低版本,导致zuul依赖的高版本class找不到。可以显式指定hystrix-core版本与spring-cloud-starter-netflix-zuul版本匹配,如本文上面maven配置示例。
Zuul Filter:
分 preFilter、routeFilter、postFilter。
zuul filter中如果需要对请求进行拦截,可在重写run方法中调用 ctx.setSendZuulResponse(false); 进行设置取消转发。然后基于RequestContext 设置返回内容。代码如下所示
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
try {
try {
// 鉴权
cmsAuthService.checkOaReturnStaffName(request);
} catch (ExecutionException e) {
log.error("authorityFilter check not pass", e);
throw new IaskException(ResultCode.SYSTEM_ERROR, "oa whitelist check error");
}
//鉴权失败处理
} catch (Throwable t) {
//设置不返回
ctx.setSendZuulResponse(false);
//设置返回错误信息
ctx.setResponseStatusCode(HttpStatus.OK.value());
ctx.setResponseBody(JsonUtil.toJson(IaskExceptionHandler.handleException(t)));
HttpServletResponse response = ctx.getResponse();
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
}
return null;
}
异常处理:
暂略
详尽的配置请参考官方文档:
https://cloud.spring.io/spring-cloud-netflix/multi/multi__router_and_filter_zuul.html
网友评论