微服务学习笔记--Spring Zuul 微服务网关的构建

目录


前言

在学习完前面的知识后,微服务架构已经初具雏形。但还有一些问题:不同的微服务一般会有不同的网络地址,客户端在访问这些微服务时必须记住几十甚至几百个地址,这对于客户端方来说太复杂也难以维护。如下图:
请求多个服务
因此,我们需要一个微服务网关,介于客户端与服务器之间的中间层,所有的外部请求都会先经过微服务网关。客户端只需要与网关交互,只知道一个网关地址即可,这样简化了开发还有以下优点:
1、易于监控
2、易于认证
3、减少了客户端与各个微服务之间的交互次数
如下图:
微服务网关架构图

在Spring Cloud中 Zuul是Netflix的基于JVM的路由器和服务器端负载均衡器。Zuul可以和Eureka、Ribbon、Hystrix、等组件配合使用。

构建微服务网关

新建一个spring Boot项目microservice-gateway-zuul 。
Spring Boot :1.5.9.RELEASE
Spring Cloud:Edgware.RELEASE

引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

修改启动类

上面依赖中也加入了Eureka ,一般我们都会在启动类中添加上
@EnableDiscoveryClient 注解,但在ZUUL 中我们只需要添加一个
@EnableZuulProxy注解即可

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

添加配置

这里先使用最简单的配置,即配置应用名、端口、注册Eureka即可。后面再慢慢优化配置。

spring:
  application:
    name: microservice-gateway-zuul
server:
  port: 8040
eureka:
  client:
    service-url:
      defaultZone: http://user:admin@localhost:8761/eureka      

测试

完成配置后则可以分别启动Eureka、用户微服务、Config Server(如果使用了)、microservice-gateway-zuul 项目。这样一个简单的微服务网关就完成了。我们可以通过 microservice-gateway-zuul 的路径加 微服务应用名 来访问微服务。
如访问用户微服务:http://localhost:8040/microservice-provider-user/1
微服务网关测试
这样所有的微服务都可以通过 Zuul 进行访问。
前面提到Zuul 可以配合Ribbon使用,我们不用加任何配置和依赖,即可以实现负载均衡,可以再启动一个用户微服务进行测试。

优化配置

上一节使用 Zuul 实现了最简单的微服务网关,在实际环境中需要对Zuul 进行优化配置。

路由

1、转发
在Zuul的配置中可以为各微服务添加路由映射,如添加配置:

zuul:
  routes:
    microservice-provider-user: /user/**

表示HTTP调用将 /user 转发到microservice-provider-user服务,于是我们访问用户微服务的地址可以简化为:
http://localhost:8040/user/1

/user/* 表示匹配其下的一个级别的路径,/user/** 表示匹配其下多个级别的路径。

另外 还有一种方式也可以实现:

zuul:
  routes:
    user:
      path: /user/**
      serviceId: microservice-provider-user

这种写法与上面的效果相同。zuul.routes.user 这里的 user 是只该路由名称,可以自己随意命名。
2、正则表达式指定路由规则
Zuul中可以写正则来指定路由规则,如微服务名命名规则为:微服务名+版本。通过添加以下正则规则 ,我们可以通过 版本 + 微服务名 来访问。

@SpringBootApplication
@EnableZuulProxy
public class MicroserviceGatewayZuulApplication {
    //正则表达式指定路由规则
    @Bean
    public PatternServiceRouteMapper serviceRouteMapper() {
        return new PatternServiceRouteMapper(
                "(?<name>^.+)-(?<version>v.+$)",
                "${version}/${name}");
    }
    public static void main(String[] args) {
        SpringApplication.run(MicroserviceGatewayZuulApplication.class, args);
    }
}

添加PatternServiceRouteMapper 传入两个参数,第一个为微服务的命名规则正则表达式,第二个是需要转化成什么形式的正则表达式。
(?<name>^.+)-(?<version>v.+$)表示我们的微服务命名 为服务名+版本;
${version}/${name} 表示访问路径转化成版本+服务名
测试
为了测试方便,把用户微服务的spring.application.name 更改为 microservice-provider-user-v1 ,如果使用了Config Server 把git上的配置也记得更改。
我们重启下Zuul,再次访问用户微服务会我发现原来的访问路径不行了。需要使用以下方式:http://localhost:8040/v1/microservice-provider-user/1
正则匹配

3、前缀
添加如下配置:

zuul:
  prefix: /api

访问Zuul 的/api/microservice-provider-user/1会被映射到 /microservice-provider-user/1 即添加了前缀。
添加配置:

zuul:
  prefix: /api
  strip-prefix: false

配置 strip-prefix后,访问Zuul 的api/microservice-provider-user/1会被转发到 microservice-provider-user/api/1
strip-prefix需与prefix配合使用。

4、忽略微服务或路径
在有些情况下我们不想微服务网关去代理某个微服务,或者想保护某个微服务下了敏感路径可以使用以下配置:

zuul:
    ignored-services: microservice-config-server

zuul.ignored-services 表示忽略指定的微服务,则通过Zuul不能访问到该微服务。

zuul:
    ignored-patterns: /**/getProfile/**

zuul.ignored-patterns 表示忽略所以包含 /getProfile/的路径,上一篇笔记中我们为用户微服务添加了 /getProfile/ 现在可以测试已无法访问了,但其它路径则正常,这种方式常可以用来屏蔽 /admin/等比较敏感的路径。

Zuul 过滤器

Zuul 过滤器是Zuul的核心组件,Zuul中已经实现了一些过滤器,同时我们也可以自己定义过滤器。在Zuul中定义过滤器很简单,只需要继承 ZuulFilter 类。

自定义过滤器

在上面构建的 microservice-gateway-zuul中新建类 并继承 ZuulFilter 如下:

public class MyFilter extends ZuulFilter {
    /**
     * 过滤器类型
     */
    @Override
    public String filterType() {
        return "pre";
    }
    /**
     * 过滤器的优先级,数字越大顺序越后
     */
    @Override
    public int filterOrder() {
        return 1;
    }
    /**
     * 是否使用该过滤器
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }
    /**
     * 具体实现
     */
    @Override
    public Object run() {
        System.out.println("这里是通过ZuulFilter中打印出来的!");
        return null;
    }
}

继承 ZuulFilter后实现它的四个方法,作用可看上面的注释。
过滤器类型有如下几种:

PRE:这种过滤器在请求被路由之前调用,可以利用这种过滤器实现身份认证,记录调用信息等。
ROUTING:这种过滤器将请求路由到微服务。
POST:这种过滤器在路由到微服务后执行。
ERROR:在其他阶段发生错误时执行该过滤器。

在启动类中添加Bean

@SpringBootApplication
@EnableZuulProxy
public class MicroserviceGatewayZuulApplication {
    @Bean
    public MyFilter myFilter(){
        return new MyFilter();
    }
    public static void main(String[] args) {
    SpringApplication.run(MicroserviceGatewayZuulApplication.class, args);
    }
}

重新启动Zuul,随意访问一个微服务,可以在Zuul控制台看到打印了过滤器run方法中输出的内容:
过滤器输出内容

禁用过滤器

Zuul默认启用了一些过滤器,这些过滤器存放在spring-cloud-netflix-core包中的com.netflix.zuul.filters中,在发某些场景下,我们想禁用一些过滤器可以直接在配置文件中设置:
zuul.<SimpleClassName>.<filterType>.disable=true

SimpleClassName:是指过滤器类名
filterType:是过滤器类型
如禁用我们上面自定义过滤器可以这样写:

zuul:
  MyFilter:
    pre:
      disable: true

重启Zuul再次通过Zuul访问微服务,会发现Zuul的控制台不会再打印run方法中的内容,说明已经被禁用了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值