Spring Cloud学习系列第五篇【API网关服务】

  这篇随笔接着学习微服务中一个比较重要的组件API网关服务。当我们微服务架构完成后最终是要提供给外部访问的,于是我们需要一个统一的访问入口,能隐藏我们内部服务URL细节,这就有点像局域网里那个网关的概念了,这是API网关服务就应运而生了。API网关作用有能为实现请求路由、负载均衡、校验过滤等基础功能,还能实现请求转发的熔断机制、服务集合等高级功能。补充下通常我们对外服务统一入口可以采用F5、Nginx等方式也能实现前面的请求路由与负载均衡,但是要实现后面功能了F5、Nginx就无能为力了吧,这就是API网关服务强大之处。在Spring Cloud体系中我们可以采用Spring Cloud Zuul搭建我们的API网关服务,Zuul能与Spring Cloud全家桶这些组件整合,通过这样的设计也就能更好的实现无论是请求路由、负载均衡还是熔断、服务机制了。

  接着以API网关的请求路由、过滤器、服务容错三个方面学习,API网关的搭建就跳过了,因为它和Eureka一样都是非常简单即可搭建好的,可自行了解下。

一、请求路由

  服务路由配置

  由于Zuul与Eureka整合便可知道每个服务的请求地址,因此可通过zuul.routes.<service-name>=<path>配置路由,当访问地址如http://127.0.0.1:7001/api-a/user/1,将会配置该路由股则并向对应服务转发。

#凡是以/api-a/开头的URL都转发到服务名为service-a的应用
zuul.routes.service-a=/api-a/**

  默认路由规则

  Zuul在不配置的情况下是有默认路由规则的,可以免去我们逐一配置的麻烦。默认情况都会以服务名作为path配置对应的服务。比方说我们有个服务叫service-a,那Zuul默认就会创建如下的路由规则。

zuul.routes.service-a=/service-a/**

#如果不希望使用默认路由规则,我们可以使用zuul.ignored-servies=*取消zuul的默认路由

  自定义路由规则

  如果觉得默认路由规则不符合自己业务需求还可以通过自定义路由规则定义自己路由规则,还是举个例子:服务名为service-a,默认路由规则是/service-a/**,但如果希望把默认路由规则变成/service/a/**可以在启动类添加PatternServiceRouteMapper类,并且采用正则表达式命名分组去匹配服务名称和定制自己的路由规则,如下例子,当服务名称符合PatternServiceRouteMapper构造函数的第一个参数(?<part1>^.+)-(?<part2>.+$)这个正则表达式,并且获取了命名分组part1和part2,然后就可以通过第二个参数去定义路由。当然如果不符合第一个参数的正则表达式则走默认路由规则。

package com.pumpkin;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.netflix.zuul.filters.discovery.PatternServiceRouteMapper;
import org.springframework.context.annotation.Bean;

@EnableZuulProxy
@SpringCloudApplication
public class Application {

    public static void main(String[] args){
        new SpringApplicationBuilder(Application.class).web(true).run(args);
    }

    @Bean
    public PatternServiceRouteMapper serviceRouteMapper() {
        return new PatternServiceRouteMapper(
                "(?<part1>^.+)-(?<part2>.+$)",
                "${part1}/${part2}");
    }

}

  路径匹配

  在定义路由是通常需要使用通配符的,Zuul的通配符采用了Ant风格定义,具体如下。需要注意的是Zuul的路由配置是根据顺序配置而不是最长配置路径匹配。也就是说一个URL区配置路由的时候,并且有多个路由可以匹配到,一旦找到第一个可以匹配上的路由就会结束下面的匹配了。

  

  除此之外zuul还提供了忽略表达式用于忽略不希望被API网关进行路由的URL表达式,比方说service-a服务的/hello.do接口不希望被路由到,可以添加如下配置。

zuul.ignored-patterns=/**/hello.do/**

  本地跳转

  在Zuul实现的API网关路由功能中,还支持forward形式的服务器端跳转配置,就是说可以设置一个路由规则,符合该路由规则的讲会转发到zuul网关自身去处理,当然使用本地跳转时,Zuul网关也有实现相应的接口。

#本地跳转#当我访问http://127.0.0.1:7001/api-b-url/hello,将会转发给给Zuul自身去处理
zuul.routes.api-b-url.path=/api-b-url/**
zuul.routes.api-b-url.url=forward:/local

  Cookie与头信息

  默认情况下Zuul在处理请求时会过滤掉一些HTTP请求头信息,默认的敏感头信息通过zuul.sensitiveHeaders参数定义,包括Cookie、Set-Cookie、Authoriztion三个属性,所以Web项目常用的Cookie默认情况下是不会传递的,为了解决这个问题,有如下几个配置方法。

#通过设置全局参数为空覆盖默认值
#zuul.sensitiveHeaders=
#对指定路由开启自定义敏感头
#zuul.routers.<router>.customSensitiveHeaders=true
#讲指定路由的敏感头设置为空
#zuul.routers.<router>.sensitiveHeaders=

  除了Cookie问题外,还有一个重定向问题需要了解的。由于Zuul没有正确的处理HTTP请求头信息中的Host,在某些需要重定向场景下会出现如下问题:比方说向zuul网关发送一个登录请求,登录成功后后端服务返回一个302重新定向响应,该响应的host头信息可能是具体实例的IP和端口,此时浏览器可能看到的就是实例的IP而不是网关的IP了,如下图。需要解决这个问题在Camden版本之后可以通过属性zuul.add-host-header=true得到处理,不过基于目前我学习的这个版本的话是没有提供直接的解决办法的,需要自行参考Camden版本的PreDecorationFilter过滤器去处理。

二、过滤器

  Zuul过滤器应该可以说是Zuul最精华的一部分了,它主要提供了四种类型的过滤器,这四种过滤器基础的的抽象类(ZuulFilter)是一样的,但不同的过滤器在Zuul中作用不一样,生命周期也是不一样的,下面先看看ZuulFilter接抽象类几个重要抽象方法。

   #这个属性有四种类型对应不同的过滤器分别是pre、routing、posting、error
    public abstract java.lang.String filterType();
   #决定过滤器执行顺序,数值越小优先级越高
    public abstract int filterOrder();
  #判断过滤器是否要执行
    boolean shouldFilter();
  #过滤器执行逻辑
    java.lang.Object run();

  介绍四种过滤器

  通过ZuulFilter介绍基本就了解过滤器是怎么个使用了吧,直接编写一个类继承ZuulFilter,指明该过滤器的类型、优先级、逻辑等然后被Spring去加载便可,那么不同类型的过滤器生命周期和作用是什么?下面一张官方大图展示的比较清楚了。

  pre过滤器:在请求路由前被调用,大家都熟知的这个阶段适合做一些校验逻辑

  routing过滤器:在路由请求时被调用

  post过滤器:在routing和error过滤器之后被调用,这个类型的过期就一般用于对请求响应结果做一些加工

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

  在Spring Cloud Zuul中已经是有一批默认的实现了的核心过滤器了,它们会在Zuul启动的时候自动加载和启用,从图中可以看到一个有趣的路径是error过滤器在任一类型的过滤器发生异常时都会进入,但它最终也还是会进入到post过滤器返回请求给客户端。

 

  禁用过滤器

  有时我们需要禁用zuul某些默认过滤器或自定义过滤器的需求,那么可以如下

#其中<SimpleClassName>为简单类名,<filterType>为过滤器#类型
zuul.<SimpleClassName>.<filterType>.disable=true
eg:
zuul.AccessFilter.pre.disable=true

  处理异常信息

  这是开发中常见需求,在<<Spring Cloud微服务实战>>一书以及永超大神博客中有比较详细的介绍,跳过~~

三、服务容错

  既然是Spring Cloud的一员,那么在服务容错方面当然有Hystrix和Ribbon良好的支持啦。也就是Zuul天生就拥有线程隔离、断路器、客户端负载均衡的能力了,不过在设置路由的时候需要以zuul.routes.service-a=/api-a/**这种服务路由的方式设置,否则将不具备服务容错能力。而Hystrix和Ribbon的配置还是和原本一样,简单介绍下。

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds - 设置路由转发请求执行总时间,超时会返回TIMEOUT错误

ribbon.ConnectTimeout - 设置请求创建连接时间

ribbon.ReadTimeout - 设置请求超时时间

ribbon.ConnectTimeout和ribbon.ReadTimeout 设置时间小于hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 时出现请求创建连接超时或者请求超时,ribbon都会进行重试路由请求的,如果我们不希望有这个重试机制可以通过
zuul.retryable=false - 全局关闭
或者
zuul.routers.<route>.retryable=false - 指定路由关闭

四、总结

  Api网关可以说是微服务闭环中不可或缺的一部分,今天对Spring Cloud Zuul相关内容进行了学习最大感受是Zuul其实是具有“微服务”特色的一个服务代理工具,正是这个特点使得它与Nginx和F5这些服务代理工具不一样,要做的事情更多,例如检验、服务容错、对请求结果进行加工等等,才能保证微服务可以得到稳定运行。

六、参考资料

Spring Cloud微服务实战-翟永超。本系列的学习都是参考该书籍学习的,同时源码使用的Spring Boot和Spring Cloud的版本也与该书保持一致。

七、源码

码云地址:[email protected]:pumpkingg/Spring-Cloud-Study.git 该篇随笔对应的代码是master分支下命名为blog4的Tag

原文地址:https://www.cnblogs.com/yipaihushuo/p/9281935.html

时间: 2024-10-09 10:00:38

Spring Cloud学习系列第五篇【API网关服务】的相关文章

Spring Cloud(五):API网关服务——Spring Cloud Zuul

通过前面的介绍,我们可以使用Spring Boot进行微服务开发,使用Spring Cloud Eureka实现注册中心以及微服务的注册和发现,使用Spring Cloud Ribbon实现服务间的负载均衡,使用Spring Cloud Hystrix实现线程隔离以及断路器功能.但是实际应用中这样的架构无疑增加了开发成本以及运维难度,而且后期重构难度也很大.为了解决以上各种问题,需要使用API 网关的方式.API 网关是一个服务器,它是进入一个系统的唯一节点,封装了内部系统的架构,并且提供了AP

互联网神经学系列第五篇:研究大脑中的谷歌,脸书和华为思科路由,脑互联网生理学

本文是互联网神经学系列第五篇-"大脑中的类互联网应用和结构,脑互联网生理学" 一.人类大脑研究的困境 大脑的秘密一直是科学皇冠上最明亮的宝石之一,但在两千年前,人们确连它的重要意义还不知道,例如著名的亚里士多德(Aristotle,公元前384-前322)认为神智在心,是心控制着我们的思想,情绪.大约公元前5世纪,地中海科斯岛上托名希波克拉底(Hippocrates)的一群医生被认为是最早发现了脑是神智的载体,在希波克拉底著作中有如下一段话."人们应当认识到:我们的愉悦.欢乐

Spring Cloud学习--配置中心(Config)

Spring Cloud学习--配置中心(Config) 一 Spring Cloud Config简介 二 编写 Config Server 三 编写Config Client 四 使用refresh端点手动刷新配置 五 Spring Config Server与Eurelka配合使用 六 Config Server的高可用 一. Spring Cloud Config简介 微服务要实现集中管理微服务配置.不同环境不同配置.运行期间也可动态调整.配置修改后可以自动更新的需求,Spring Cl

spring cloud 学习(4) - hystrix 服务熔断处理

hystrix 是一个专用于服务熔断处理的开源项目,当依赖的服务方出现故障不可用时,hystrix有一个所谓的断路器,一但打开,就会直接拦截掉对故障服务的调用,从而防止故障进一步扩大(类似中电路中的跳闸,保护家用电器). 使用步骤:(仍然在之前的示例代码上加以改造) 一.添加hystrix依赖 compile 'org.springframework.cloud:spring-cloud-starter-hystrix' 二.在需要熔断的方法上添加注解 package com.cnblogs.y

Intelli IDEA学习系列之快捷键篇

Intelli IDEA学习系列之快捷键篇 IDEA简介: IDEA 全称IntelliJ IDEA,是java语言开发的集成环境,IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手.代码自动提示.重构.J2EE支持.Ant.JUnit.CVS整合.代码审查. 创新的GUI设计等方面的功能可以说是超常的.IDEA是JetBrains公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主. 在学习过程中会慢慢补充..... [1.查找] 1

前端工程师技能之photoshop巧用系列第五篇——雪碧图

显示目录 目录 [1]定义 [2]应用场景 [3]合并[4]实现[5]维护 前面的话 前面已经介绍过,描述性图片最终要合并为雪碧图.本文是photoshop巧用系列第五篇--雪碧图 定义 css雪碧图(sprite)是一种网页图片应用处理方式,它允许将一个页面涉及到的所有零星图片都包含到一张大图中.使用雪碧图的处理方式可以实现两个优点: [1]减少http请求次数 [2]减少图片大小,提升网页加载速度 (多张图片加载速度小于拼合成的图片的加载速度) 凡事都不完美,实现优点的同时也带来了缺点,即提

spring cloud 学习(5) - config server

分布式环境下的统一配置框架,已经有不少了,比如百度的disconf,阿里的diamand.今天来看下spring cloud对应的解决方案: 如上图,从架构上就可以看出与disconf之类的有很大不同,主要区别在于: 配置的存储方式不同 disconf是把配置信息保存在mysql.zookeeper中,而spring cloud config是将配置保存在git/svn上 (即:配置当成源代码一样管理) 配置的管理方式不同 spring cloud config没有类似disconf的统一管理界

python学习记录第五篇--遍历目录

#coding=utf-8'''@author: 简单遍历目录删除文件的小程序'''import os#查找文件操作def findFile(path): fileList=[] for rootPath,subRoot,fileName in os.walk(path): for sub in fileName: if os.path.isfile(os.path.join(rootPath,sub)): k=os.path.splitext(sub)[1].lower() if k in (

Python学习系列(五)(文件操作及其字典)

Python学习系列(五)(文件操作及其字典) Python学习系列(四)(列表及其函数) 一.文件操作 1,读文件 在以'r'读模式打开文件以后可以调用read函数一次性将文件内容全部读出,也可以指定每次read读多少字节,例如: 1 #coding:utf-8 2 fn='test1.py' 3 fp=open(fn,'r') #以读的方式打开文件,文件必须首先存在和,.文件在同一目录下py 4 print 'reading pos:',fp.tell() 5 r=fp.read(20) #