微服务路由解决方案: "Zuul" 服务搭建;以及自定义Zuul过滤器的代码编写。
微服务架构有一个问题,那就是客户端如何访问各个微服务。
总不能在客户端APP/HTML写很多个不同的地址来请求吧?这样维护及其困难、开发不易。
这时候就需要一个网关,客户端的请求都发给这个网关, 然后由他来给你路由到别的微服务里边。
netflix 就开源了一个微服务网关:Zuul ,可以和 SpringCloudNetflix 全家桶(Eureka、Ribbon、Hystrix等)完美集成。
废话不多说.代码撸起来。
首先,项目创建,当然,创建的还是我那个Gradle搭的SpringCloudFinchley项目的子模块。
这回不用加什么依赖,只需要一个Zuul的依赖和Eureka Client的依赖就够了。
而且Zuul自己本身就集成了Ribbon和Hystrix,非常强大。
build.gradle:
dependencies { compile("org.springframework.cloud:spring-cloud-starter-netflix-zuul") compile("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client") // compile("org.springframework.cloud:spring-cloud-starter-netflix-ribbon") // compile("org.springframework.cloud:spring-cloud-starter-netflix-hystrix") }
然后在Application启动类上边加上@EnableZuulProxy 用以声明zuul代理
最主要的: 配置类yml文件
既然这个 zuul 是提供一个服务路由的功能,又已知 zuul 完美的集成了 Eureka。可以从Eureka Server中得到所有注册进去的服务。
那么,最需要进行配置的。自然是访问路径所对应的服务啦, 在zuul这个服务的配置文件里,专门有个地方给你写这个路由规则( zuul.routes )
我的配置文件:
server: port: 8060 spring: application: name: sc-demo-microservice-zuul #这个名字会注册到 Eureka 里去 #Actuato 配置 management: endpoint: # 暴露shutdown功能 # shutdown: # enabled: true endpoints: web: exposure: include: '*' #暴露哪些端点 exclude: #隐藏哪些端点 #Eureka client端配置 eureka: client: service-url: defaultZone: http://user:614@localhost:8080/eureka/,http://user:614@localhost:8081/eureka/ instance: prefer-ip-address: true #将自己ip注册到Eureka Server zuul: ribbon-isolation-strategy: thread #hystrix隔离策略改为线程 (默认是信号量 thread-pool: use-separate-thread-pools: true #让每个路由使用它独立的线程池 thread-pool-key-prefix: myprefix- #前缀 routes: #路由配置 local-router: url: local/test #本地转发 path: forward:/local/test aggregate-router: url: aggregate/** path: forward:/aggregate/** user-router: sensitive-headers: Cookie,Set-Cookie,Authorization #指定敏感header service-id: sc-demo-microservice-user path: /zuul_user/** movie-router: service-id: sc-demo-microservice-movie path: /zuul_movie/** # ignored-services 指定微服务忽略它,不对它进行路由,使用"*" 忽略所有,只路由指定了的 ignored-services: sc-demo-microservice-eureka_1,sc-demo-microservice-eureka_2
虽然我这个配置文件里注释已经写得挺详细了,但还是简单的解释一下:
zuul.routes 这个属性树下面第一级节点,即我写的local-router、user-router 等,这一级只是让你写个路由规则的名字。 瞎写就行。
再下一级,大致可以分为两种:
1、路由到其余微服务的 指定好 service-id(即服务注册进Eureka的服务名) 和对应的访问路径就行了 ( 例如: 我用户微服务有个API请求路径是 user/{id},我现在就可以通过 ZUUL_ADDRESS:ZUUL_PORT/zuul_user/user/{id} 来访问我sc-demo-microservice-user中的API)。
2、路由到本地由Zuul自己进行处理的 指定好客户端访问路径,和对应的本地API地址( forward: +本地API的地址) 就行
到这步,其实Zuul这个服务就搭建完毕了, 已经可以使用了。而且,不但可以帮你进行服务路由,还会用自带的Ribbon给你的请求进行负载均衡。
搭建完了,当然还不够,还能让这个 zuul 服务更加强大
zuul的路由功能是基于他自己编写的一大堆过滤器实现的,这里先简单说下他的过滤器类型
他主要有四大标准过滤器类型,这四种是最主要的
1、PRE 在请求被路由之前调用这个过滤器
2、ROUTING 这个过滤器将请求路由到微服务
3、POST 这个过滤器在路由到对应微服务之后再执行
4、ERROR 出错时进的
zuul 他自己有这几个过滤器的实现,当然,他写的我不动他,我可以自己额外写过滤器来实现自己的功能嘛。
zuul过滤器的实现非常简单,只要继承 ZuulFilter 这个类就完事了。
我写了个日志记录的过滤器:
package com.skypyb.sc.config; 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 org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.servlet.http.HttpServletRequest; @Configuration public class ZuulFilterConfig { /** * 用起这个过滤器来 * @return */ @Bean public PreRequestLogFilter preRequestLogFilter() { return new PreRequestLogFilter(); } /** * 请求在路由之前的过滤器 */ public class PreRequestLogFilter extends ZuulFilter { private Logger logger = LoggerFactory.getLogger(PreRequestLogFilter.class); @Override public String filterType() { return FilterConstants.PRE_TYPE; } @Override public int filterOrder() { return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); logger.info("send {} request to {}.", request.getMethod(), request.getRequestURI()); return null; } }//internal class end... }
这几个方法不多说,看下ZuulFilter源码的注释就知道具体是什么意思了。反正就是关于你写的过滤器的设置(类型、执行顺序、是否执行、具体逻辑)
我这过滤器很简单,就记录一下请求方法、地址,是个PRE类型的过滤器,会在路由之前调用。过滤器能干的事情很多,认证啊、加密啊啥的都行,看业务需求了。
2 COMMENTS