springcloud学习之路(二):网关路由服务

在上一篇服务注册中心的搭建中,为了提升项目的友好性,可以另加一个eureka监听器用于感知哪些服务注册了或是挂掉了,对于挂掉了的服务可选择由程序自动进行通知等等。在实际的环境中,这样处理是大有裨益的,具体的做法会在补充篇中涉及到,而对于学习而言并不必须。中心建立了,各个服务就能直接注册到中心,但是如何去访问这些服务呢?直接去单独访问各微服务的端口以获取其内容自然是可以的,但若是这样,那么微服务框架将毫无意义,而且也无法保障安全性。所以,我们需要一个门,通过门的验证后才能访问相应的服务,对于有问题的访问门便会把它阻挡在外,即网关。

如何去搭建一个网关服务呢,与任何一个springboot项目一样,“三步走”,添加项目所用到的依赖包,配置文件的配置,类文件的编码。与注册中心微服务一样,在父(顶级)项目名上右键新建一个Module,然后新建一个空的Maven项目,命名zuul-service,得到的便是一个空有结构的maven子项目。随后便进行“三步走”操作:

1、pom.xml文件配置
打开zuul-service项目的pom.xml文件,添加依赖项如下:

<dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-eurekaartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-zuulartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
dependencies>     

第一个依赖包声明其为一个微服务,与所有的非注册中心的依赖包一致,注册中心的多一段 -server ,很容易辨识。第二个带有zuul所代表的依赖包声明该微服务为网关微服务,第三个依赖包声明该服务可被发现。这三个是基本的依赖项,当然加入test依赖,web依赖都是不影响的。

2、配置文件的配置
由于建立的空maven项目只有结构,没有相应的内容,因此我们需要在resources下自己新建配置文件application.yml,并在该文件中写入内容如下:

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8000/eureka/
server:
  port: 8001
spring:
  application:
    name: zuul-service
zuul:
  prefix: /api
  routes:
#    api-a:
#      path: /a/**
#      serviceId: service-ribbon-1
    api-b:
      path: /b/**
      serviceId: feign-service
#      stripPrefix: false   #不移除前缀api-b,访问路径为/api/b/test --> user-center   /b/test(需要在对应函数RequestMapping前加/b)
#      默认时 /api/b/test --> user-center   /test

除了常见的feign,ribbon等专用的负载均衡服务,网关服务其实也是自带负载均衡功能的,只需要将上述的serviceId改成对应的消费服务的注册名,网关便会根据该服务名顺序循环的调用该注册名下的服务。

3、后台代码
首先,由于我们建立的是一个空的maven项目,因此启动类也需要我们自己去编写。在java文件夹下新建一个包com.springcloud.zuul,在该包名下,建一个类命名ZuulBootstrap作为启动类,改造成如下内容:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class ZuulBootstrap{
    public static void main(String[] args) {
        SpringApplication.run(ZuulBootstrap.class, args);
    }
}

三个注解的含义如字面意,分别为声明为网关,声明为服务而非注册中心,声明该类为一个springboot类的启动类。

作为一个网关服务,网关拥有的功能一般为路由功能与过滤功能,在示例中,我们只看到了在配置文件中设置的路由功能,并没有看到过滤功能。所以,为了增加其过滤功能,我们需要在包com.springcloud.zuul下新建一个包filter,一般过滤功能分为前置过滤与后置过滤,因此,在filter包下新建两个类,命名Prefilter与PostFilter以完善过滤功能。

(1) 前置过滤PreFilter

@Component
public class PreFilter extends ZuulFilter{

    private Logger logger = LoggerFactory.getLogger(PreFilter.class);
    public PreFilter() {
        super();
    }

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        logger.info("pre--模拟身份认证");
        // TODO: 2017/12/24  身份不通过,跟oauth,jwt
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.put("start",System.currentTimeMillis());
        return null;
    }
}   

前置过滤需要继承Zuulfilter过滤器,需要覆写的方法的含义如字面意,过滤类型,过滤顺序,是否过滤,过滤规则则是在run()方法在覆写,禁止非法访问,进行身份认证等都可以在这个方法在实现。@Component声明该类为一个自动加载的组件。

(2) 后置过滤PostFilter

@Component
public class PostFilter extends ZuulFilter {
    Logger log = LoggerFactory.getLogger(PostFilter.class);

    public PostFilter() {
        super();
    }

    @Override
    public String filterType() {
        return "post";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        log.info("post....");
        RequestContext ctx = RequestContext.getCurrentContext();
        long total = System.currentTimeMillis() - (long) ctx.get("start");
        log.info("the request use:total=" + total + "ms");
//        ctx.addZuulResponseHeader(); 增加反应的头
        return null;
   }
}

前置过滤是过滤进入的访问,后置过滤则是过滤返回的响应。

至此,网关服务的基本结构便搭建起来了,但是网关的内容远不止这些,随着内容的增加,笔者也会慢慢扩充网关的内容。需要看源码的东西可以移步这个系列的总览页springcloud学习之路总览查看源码。

你可能感兴趣的:(springcloud)