• API网关服务:Spring Cloud Zuul

  API网关是一个更为智能的应用服务器,它的定义类似于面向对象设计模式中的Façade模式,它的存在就像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要经过它来进行调度和过滤。它除了要实现请求路由、负载均衡、校验过滤等功能之外,还需要更多能力,比如与服务治理框架的结合、请求转发时的熔断机制、服务的聚合等一系列高级功能。

  在Spring Cloud中提供了基于Netflix Zuul实现的API网关组件——Spring Cloud Zuul。

  首先,对于路由规则与服务实例的维护问题。Spring Cloud Zuul通过与Spring Cloud Eureka进行整合,将自身注册为Eureka服务治理下的应用,同时从Eureka中获得了所有其他微服务的实例信息。这样的设计非常巧妙地将服务治理体系中维护的实例信息利用起来,将维护服务实例的工作交给了服务治理框架自动完成,不再需要人工介入。而对于路由规则的维护,Zuul默认会将通过以服务名作为ContextPath的方式来创建路由映射,大部分情况下,这样的默认设置已经可以实现我们大部分的路由需求,除了一些特殊情况(比如兼容一些老的URL)还需要做一些特别的配置。但是相比于之前架构下的运维工作量,通过引入Spring Cloud Zuul实现API网关后,已经能够大大减少了。

  其次,对于类似签名校验、登录校验在微服务架构中冗余问题。理论上来说,这些校验逻辑在本质上与微服务应用自身的业务并没有多大的关系,所以它们完全可以独立成一个单独的服务存在,只是它们被剥离和独立出来之后,并不是给各个微服务调用,而是在API网关服务上进行统一调用来对微服务接口做前置过滤,以实现对微服务接口的拦截和校验。

1. 首先,搭建几个用于路由和过滤使用的微服务应用,可是使用之前的注册中心和demo-member、demo-customer-feign,分别启动三个应用。

2. 创建maven工程,骨架选择quickstart,命名为:demo-api-gateway。

3. 在pom.xml文件中引入相关依赖:

4. 创建启动类:

5. 在src\main\resources目录下创建application.yml文件:

6. 进入注册中心,观察启动的服务:

7. 在demo-api-gateway的pom.xml文件中添加Eureka依赖,并在application.yml文件中指定Eureka位置和进行路由的配置:

8. 启动demo-api-gateway服务,分别向网关发起下面请求:

  ◆http://localhost:5217/api-a/member:该url符合/api-a/**规则,由api-a路由负责转发,该路由映射的serviceId为member-service,所有最终/member请求会被发送到member-service服务的某个实例上去。

  ◆http://localhost:5217/api-b/getMember:该url符合/api-b/**规则,由api-b路由负责转发,该路由映射的serviceId为customer-service-feign,所有最终/getMember请求会被发送到customer-service-feign服务的某个实例上去。

  通过面向服务的路由配置方式,我们不需要再为各个路由维护微服务应用的具体实例的位置,而是通过简单的path与serviceId的映射组合,使得维护工作变得非常简单。这完全归功于Spring Cloud Eureka的服务发现机制,它使得API网关服务可以自动化完成服务实例清单的维护,完美地解决了对路由映射实例的维护问题。

  • 请求过滤

  Zuul允许开发者在API网关上通过定义过滤器来实现对请求的拦截与过滤,只需要继承ZuulFilter抽象类并实现它定义的4个抽象方法就可以完成对请求的拦截和过滤了。

  下面实现一个简单的Zuul过滤器,它实现了再请求被路由之前检查HttpServletRequest中是否有token参数,若有就进行路由,若没有就拒绝访问,返回401 Unauthorized错误。

1. 定义AccessFilter类,集成ZuulFilter:

名词解释:

◆filterType:该方法需要返回一个字符串来代表过滤的类型,而这个类型就是在HTTP请求过程中定义的各个阶段。在Zuul中默认定义了4种不同的生命周期的过滤器类型:

  ■pre:可以在请求被路由之前调用。

  ■routing:在路由请求时被调用。

  ■post:在routing和error过滤器之后被调用。

  ■error:处理请求时发生错误时被调用。

◆filterOrder:通过int值来定义过滤器的执行顺序,数值越小优先级越高。

◆shouldFilter:返回一个boolea值来判断该过滤器是否要执行。可以通过此方法来指定过滤器的有效范围。

◆run:过滤器的具体逻辑,在该方法中,可以实现自定义的过滤逻辑,来确定是否要拦截当前的请求,不对其进行后续的路由,或是在请求路由返回结果之后,对处理结果做一些加工等。

2. 实现了自定义过滤器之后,并不会直接生效,还需要为其创建具体的Bean才能启动该过滤器,在启动类中添加如下内容:

3. 重启网关项目,并发起如下请求,对上述定义的过滤器做一个验证:

  ◆http://localhost:5217/api-a/member:返回401错误。

  ◆http://localhost:5217/api-a/member?token=123:正确路由到member-service的/member接口,并返回相应内容。

  • 其他

  通过Eureka与Zuul的整合已经省去了维护服务实例清单的大量配置工作,剩下只需要再维护请求路径的匹配表达式与服务名的映射关系即可。但是在实际运用过程中会发现,大部分的路由配置规则几乎都会采用服务名作为外部请求的前缀,例如上述的member-seriver,而对应的服务名称也是member-service

  对于这样具有规则性的配置内容,我们总是希望可以自动化地完成。Zuul正好默认实现了这样的功能,当Spring Cloud Zuul构建API网关服务引入Spring Cloud Eureka之后,它为Eureka中的每个服务都自动创建一个默认路由规则,这些默认规则的path会使用serviceId配置的服务名作为请求前缀,如上述的路由配置规则,可以直接注释掉:

  重启网关服务,就可以使用服务名作为前缀进行服务的调用:

  对于版本的管理,当微服务有不同的版本的时候,例如memberservice-v1,当然可以通过微服务名称来区分不同的版本,从而调用各个版本的服务,但是这样生成出来的表达式规则较为单一,不利于通过路径规则来进行管理。通常的做法是为这些不同版本的微服务应用生成以版本代号作为路由前缀定义的路由规则,比如/v1/meberservie/。这时候,通过这样具有版本号前缀的URL路径,我们就可以很容易地通过路径表达式来归类和管理这些具有版本新的微服务了。

  具体操作方法是,首先停止member-service服务,并将其服务名称改为memberservice-v1,然后启动该服务。在网关服务的启动类中,添加如下代码:

  重新启动网关服务,在浏览器中访问测试:

  • 网关总结

◆它作为系统的统一入口,屏蔽了系统内部各个微服务的细节。

◆它可以与服务治理框架结合,实现自动化的服务实例维护以及负载均衡的路由转发。

它可以实现接口权限校验与微服务业务逻辑的解耦。

◆通过服务网关中的过滤器,在各生命周期中去校验请求的内容,将原本在对外服务层做的校验前移,保证了微服务的无状态性,同时降低了微服务的测试难度,让服务本身更集中关注业务逻辑的处理。

Spring Cloud学习笔记-009的更多相关文章

  1. Spring Cloud学习笔记--Spring Boot初次搭建

    1. Spring Boot简介 初次接触Spring的时候,我感觉这是一个很难接触的框架,因为其庞杂的配置文件,我最不喜欢的就是xml文件,这种文件的可读性很不好.所以很久以来我的Spring学习都 ...

  2. Spring Cloud 学习笔记 (一)-- Eureka 服务器

    开局一张图,截取了本人学习资料中的一张图,很好地展示了Eureka的架构. Eureka服务器 管理服务的作用.细分为服务注册,服务发现. 所有的客户端在Eureka服务器上注册服务,再从Eureka ...

  3. Spring Cloud 学习笔记(二)——Netflix

    4 Spring Cloud Netflix Spring Cloud 通过自动配置和绑定到Spring环境和其他Spring编程模型惯例,为Spring Boot应用程序提供Netflix OSS集 ...

  4. Spring Cloud 学习笔记(一)——入门、特征、配置

    [TOC] 0 放在前面 0.1 参考文档 http://cloud.spring.io/spring-cloud-static/Brixton.SR7/ https://springcloud.cc ...

  5. Spring Cloud学习笔记-006

    服务容错保护:Spring Cloud Hystrix 在微服务架构中,我们将系统拆分成了很多服务单元,各单元的应用间通过服务注册与订阅的方式互相依赖.由于每个单元都在不同的进程中运行,依赖通过远程调 ...

  6. Spring Cloud学习笔记-005

    服务消费者 之前已经搭建好了微服务中的核心组件——服务注册中心(包括单节点模式和高可用模式).也有了服务提供者,接下来搭建一个服务消费者,它主要完成两个目标,发现服务以及消费服务.其中,服务发现的任务 ...

  7. Spring Cloud学习笔记-002

    搭建Spring Cloud注册中心:Eureka 服务注册:在服务治理框架中,通常都会构建一个注册中心,每个服务单元向注册中心登记自己提供的服务,将主机与端口号.版本号.通信协议等一些附加信息告诉注 ...

  8. Spring Cloud学习笔记-007

    声明式服务调用:Spring Cloud Feign Feign基于Netflix Feign实现,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供这两 ...

  9. Spring Cloud学习笔记-008

    继承特性 通过上节的示例实践,当使用Spring MVC的注解来绑定服务接口时,几乎完全可以从服务提供方的Controller中依靠复制操作,构建出相应的服务客户端绑定接口.既然存在这么多复制操作,自 ...

随机推荐

  1. 在RE了16次之后,没想到还可以这样Runtime error

    这是POJ: RE的原因: 比如: int b=2147483647; for(int i=0;i<=b;++i){ .... } 应该懂了吧, 2147483647是int能表示的最大整数 解 ...

  2. 【译】Java、Kotlin、RN、Flutter 开发出来的 App 大小,你了解过吗?

    现在开发 App 的方式非常多,原生.ReactNative.Flutter 都是不错的选择.那你有没有关注过,使用不同的方式,编译生成的 Apk ,大小是否会有什么影响呢?本文就以一个最简单的 He ...

  3. SpringBoot12 QueryDSL01之QueryDSL介绍、springBoot项目中集成QueryDSL

    1 QueryDSL介绍 1.1 背景 QueryDSL的诞生解决了HQL查询类型安全方面的缺陷:HQL查询的扩展需要用字符串拼接的方式进行,这往往会导致代码的阅读困难:通过字符串对域类型和属性的不安 ...

  4. C++中输出流的刷新问题和 endl和 \n的区别

    <C++ Primer>第5版 P6中提到endl具有换行和刷新输出流两个作用,那么没有 endl是否还会将输出流中的内容输出到设备中,再刷新输出流呢? cout << &qu ...

  5. 跨平台原生AR/VR应用研发引擎-NVisionXR开放内测

      NVisionXR引擎正式开放内测.现在,对原生AR/VR应用开发有兴趣的企业和开发者均可通过NVisionXR官网(www.nvisionxr.com)申请试用. NVisionXR引擎介绍视频 ...

  6. Eclipse+Pydev环境搭建

    1,准备好Eclipse和JAVA,x64 2,安装JDK,配置JAVA环境变量,假设安装路径为 C:\Program Files\Java\jdk1.8.0_161 在系统变量中,新建CLASSPA ...

  7. python 面向对象的程序设计

    一:什么是编程范式? 编程是程序员用特定的语法 + 数据结构 + 算法组成的代码来告诉计算机如何执行任务的过程. 如果把编程的过程比喻为练习武功,那么编程范式指的就是武林中的各种流派,而在编程的世界里 ...

  8. C++布隆过滤器

    布隆过滤器 这名词有没有听着好像很 挺高大上的,的确,它也是一种很重要的结构,下面一起看看: 一:说说历史: (Bloom Filter)是由布隆(Burton Howard Bloom)在1970年 ...

  9. Flask学习 二 模板

    jinja2模版 from flask import Flask,render_template app = Flask (__name__) @app.route ('/<name>') ...

  10. 国内maven仓库地址 || 某个pom或者jar找不到的解决方法

    解决方法 建议在maven仓库中新建settings.xml,然后把如下内容粘贴进去即可.也可以找到maven的安装目录中的conf/settings.xml,把如下的mirrors节复制到对应部分. ...