27

微服务路由解决方案: “Zuul” 服务搭建;以及自定义Zuul过滤器的代码编写。

 3 years ago
source link: https://www.skypyb.com/2019/06/jishu/896/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

微服务路由解决方案: “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:
      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类型的过滤器,会在路由之前调用。过滤器能干的事情很多,认证啊、加密啊啥的都行,看业务需求了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK