springCloud学*4(Zuul服务路由)


镇博图
三笠

springcloud 总集:https://www.tapme.top/blog/detail/2019-02-28-11-33

本篇中 Zuul 版本为 1.x,目前最新的是 2.x,二者在过滤器的使用上有较大区别

超长警告

项目代码见文章结尾

一、背景

??微服务架构将一个应用拆分为很多个微小应用,这样会导致之前不是问题的问题出现,比如:

  1. 安全问题如何实现?
  2. 日志记录如何实现?
  3. 用户跟踪如何实现?

上面的问题在传统的单机应用很容易解决,只需要当作一个功能实现即可。但是在微服务中就行不通了,让每个服务都实现一份上述功能,那是相当不现实的,费时,费力还容易出问题。

??为了解决这个问题,需要将这些横切关注点(分布式系统级别的横切关注点和 spring 中的基本一个意思)抽象成一个独立的且作为应用程序中所有微服务调用的过滤器和路由器的服务。这样的服务被称为——服务网管(service gateway),服务客户端不再直接调用服务。取而代之的是,服务网关作为单个策略执行点(Policy Enforcement Point,PEP) , 所有调用都通过服务网管进行路由,然后送到目的地。

二、服务网关

1、什么是服务网关

??之前的几节中我们是通过 http 请求直接调用各个服务,通常在实际系统中不会直接调用。而是通过服务网关来进行服务调用。服务网关充当了服务客户端和被调用服务间的中介。服务客户端仅与服务网关管理的单个 url 进行对话。下图说了服务网关在一个系统中的作用:

服务网关

服务网关位于服务客户端和相应的服务实例之间。所有的服务调用(内部和外部)都应流经服务网关。

2、功能

??由于服务网关代理了所有的服务调用,因此它还能充当服务调用的中央策略执行点(PEP),通俗的说就能能够在此实现横切关注点,不用在各个微服务中实现。主要有以下几个:

  • 静态路由——服务网关将所有的服务调用放置在单个 URL 和 API 路由后,每个服务对应一个固定的服务端点,方便开发人员的服务调用。

  • 动态路由——服务网关可以检测传入的请求,根据请求数据和请求者执行职能路由。比如将一部分的调用路由到特定的服务实例上,比如测试版本。

  • 验证和授权——所有服务调用都经过服务网关,显然可以在此进行权限验证,确保系统安全。

  • 日志记录——当服务调用经过服务网关时,可以使用服务网关来收集数据和日志信息(比如服务调用次数,服务响应时间等)。还能确保在用户请求上提供关键信息以确保日志统计(比如给每个用户请求加一个 url 参数,每个服务中可通过该参数将关键信息对应到某个用户请求)。

看到这儿可能会有这样的疑问:所有调用都通过服务网关,难道服务网关不是单点故障和潜在瓶颈吗?

1. 在单独的服务器前,负载均衡器是很有用的。将负载均衡器放到多个服务网关前面是比较好的设计,确保服务网关可以实现伸缩。但是如果将负载均衡器置于所有服务前便不是一个好主意,会造成瓶颈。

2. 服务网关的代码应该是无状态的。有状态的应用实现伸缩性较为麻烦

3. 服务网关的代码应该轻量的。服务网关是服务调用的“阻塞点”,不易在服务网关处耽误较长的时间,比如进行同步数据库操作

三、实战

??使用 Netflix Zuul 来构建服务网关,配合之前的代码,让服务网关来管理服务调用。

在生产环境中不建议使用 zuul,该组件性能较弱,且已经停止更新

1、创建 zuulsvr 项目

??详细过程不赘述,和之前一样(注意 spring cloud 版本要和之前一致),主要 pom 依赖如下:


    org.springframework.cloud
    spring-cloud-starter-zuul


    org.springframework.cloud
    spring-cloud-starter-eureka

2、配置 zuul

??首先在启动加入注解开启 zuul 并注册到 eureka 中

开启zuul

??然后编写配置文件:

spring:
  application:
    name: zuulservice
#服务发现配置
eureka:
  instance:
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 5555

这样便以默认配置启动了 zuul 服务网关。

3、路由配置

??Zuul 核心就是一个反向代理。在微服务架构下,Zuul 从客户端接受微服务调用并将其转发给下游服务。要和下游服务进行沟通,Zuul 必须知道如何将进来的调用映射到下游路由中。Zuul 有一以下几种路由机制:

  • 通过服务发现自动映射路由
  • 通过服务发现手动映射路由
  • 使用静态 URL 手动映射

1)、服务发现自动映射

默认情况下,Zuul 根据服务 ID 来进行自动路由。先将组织服务中的延时去掉

注释延时代码

启动之前的所有服务实例,然后通过 postman 访问localhost:5555/apis/licensestatic/licensing/12。控制台打印如下:

控制台打印

请求响应如下:

请求响应

c、路由过滤器

??路由过滤器用起来有点复杂,这里不写具体的实际代码,只是写一个思路。具体代码可以参考spring 微服务

  1. 获取当前请求路径
  2. 判断是否需要进行特殊路由
  3. 如需要进行特殊路由,在此进行 http 调用
  4. 将 http 调用的 response 写入到当前请求的 response 中

结束

??终于写完了,微服务的基础学*又*了一步,加油!

本篇代码存放于:github

本篇原创发布于:FleyX 的个人博客