• 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. 简洁明了的插值音频重采样算法例子 (附完整C代码)

    近一段时间在图像算法以及音频算法之间来回游走. 经常有一些需求,需要将音频进行采样转码处理. 现有的知名开源库,诸如: webrtc , sox等, 代码阅读起来实在闹心. 而音频重采样其实也就是插值 ...

  2. 【Python】 文件和操作文件方法

    文件 ■ 基本的文件用法 f = open("path","mode") mode有a,w,r,b,+等.默认为r.模式与打开文件时的动作有关系,比如用w打开的 ...

  3. c++ --> 父类与子类间的继承关系

    父类与子类间的继承关系 一.父类与子类 父类与子类的相互转换 1.派生类的对象可以赋给基类,反之不行 2.基类的指针可以指向派生类,反之不行 3.基类的引用可以初始化为派生类的对象,反之不行 4.派生 ...

  4. oracle 常用select sql语句

    本人认为很实用的几条语句 1)select ... from ...into... 2)insert into ...select ... 3)select ...from ...left join ...

  5. spring学习笔记一 入门及配置

    Spring是一个开源框架,为了解决企业应用开发的复杂性而创建的.主要优势之一就是其分层架构.Spring的核心是控制反转和面向切面.简单来说,Spring是一个分层的一站式轻量级开源框架. 使用Sp ...

  6. vue小白快速入门

    一.vue是什么 Vue 是一套用于构建用户界面的渐进式框架. 压缩后仅有17kb 二.vue环境搭建 你直接下载并用 <script> 标签引入,Vue 会被注册为一个全局变量. 但在用 ...

  7. Go语言标准库_输入/输出

    Go语言标准库_输入/输出 转载节选自<Go语言标准库> Reader 接口 type Reader interface { Read(p []byte) (n int, err erro ...

  8. node初始

    ### 一.什么是node.js > Node是一个基于 Chrome V8 引擎的 JavaScript 运行环境 > > Node使用了一个事件驱动.非阻塞式 I/O 的模型,使 ...

  9. 想不到的:js中加号操作符

    研究js加号操作符的时候,无意中试验了一个 console.log({} + "str");//NaN 发现结果居然是NaN,这让我百思不得其解. 我查阅资料,js高级编程里是这样 ...

  10. 听翁恺老师mooc笔记(16)--程序设计与C语言

    问题1:计算机遍布生活的各个方面,若你需要一个功能可以下载APP,我们需要的大部分功能都可以找到对应的APP,如果没有可以自己写一个软件,但是很少人需要这么做,那么我们为什么学习计算机编程语言? 学习 ...