导读

我们知道在基于Spring Cloud的微服务体系中,各个微服务除了在内部提供服务外,有些服务接口还需要直接提供给客户端,如Andirod、IOS、H5等等。

而一个很尴尬的境地是,如果直接将提供外部接口的微服务暴露给公网,那么意味着为了增强这个微服务的安全性,需要做很多额外的安全性措施,如报文数字签名、加密等;而大部分场景下,微服务本身又是提供给内部其他微服务调用的,即便所有的微服务都会不同程度地直接面向App客户端提供公网服务,那么为了这确保这些微服务的安全性,涉及的微服务也都需要实现接口的安全性,这样不仅会造成重复开发,也会增加微服务体系的复杂性。所以,我们通常会在微服务体系的外部边界架设一个网关服务,俗称Gateway

Gateway这个服务本身不做任何具体的业务逻辑,业务逻辑还是由相应地微服务去实现。因为在微服务开发中,为了简化内部服务之间调用的繁琐程度,大部分实践是不会在微服务内部设防,如微服务本身是不会做报文层面的签名、加密。而在面向外部提供服务时,则由Gateway服务进行统一的安全认证,认证通过后才会把请求路由到具体的微服务

在这种模式下,微服务之间的调用因为都在内部网络,而不直接向外暴露服务接口及IP,所以微服务的安全问题都依赖于内部网络安全。(PS:如果网络被攻破,那么微服务就会直接暴露在攻击者面前,此时调用微服务的接口是可以直接影响业务的,如进行盗刷等,这个问题我们在下一篇文章中讨论!)

当然Gateway除了支持做简单的安全认证,如会话认证外,还具有服务限流,接口监控数据统一上报等其他功能和用途。在基于Spring Cloud的微服务架构体系中,目前提供了两套方案供我们实现Gateway,分别是Netflix的Zuul以及Spring Cloud自身提供的 Spring Cloud Gateway(构建在Spring 5以及Spring Boot 2.0基础之上)。本篇文章的主要内容是基于Zuul来介绍Api Gateway的搭建。

GateWay的位置

在我们具体分析基于Zuul的Gateway实现原理之前,我们先从整体架构上来了解下Gateway在整体微服务体系中所处的位置吧,这样会有利于我们更深刻的理解Gateway在微服务架构体系中的作用。如下图所示:

Gateway是一个处于内部微服务与外部公网请求之间的衔接性服务,它需要通过域名接收到用户客户端通过公网发出的服务请求,然后再路由至内部对应的微服务。因此Gateway本身既处于服务注册中心的管理之下,如注册到Consul,通过Consul来获取其他微服务的地址列表,并进行请求路由转发;又需要在被外部访问的过程中,被诸如Nginx这样的反向代理服务器进行服务代理,从而实现Gateway的负载均衡及高可用。

这里的一个技术细节是,Gateway大部分情况下是通过容器动态进行部署的,这一点与其他Spring Cloud微服务一样是扁平的,但是又因为网关服务的特殊性,其IP端口需要被Nginx识别从而进行反向代理及负载均衡。这里的问题是Nginx如何能够从茫茫的微服务中识别到那些是需要被外部访问,从而进行反向代理的呢?

毕竟如果将Gateway直接部署到固定的IP及端口机器的话,会失去一定的弹性,从架构层面来说会有些蹩脚。作者之前所在的公司是通过将Gateway服务打tag,如需要被外部访问的Gateway服务将其tag标签打成api,这样就可以借助一些工具如consul-template的方式,就可以做一些自动识别的流程来自动进行反向代理了!如果你有更好的实现方式,也欢迎给我留言哦!

到这里,相信你应该对Gateway在微服务架构体系中的位置有一个足够清晰地认识和了解了,下面我们就将重点介绍Zuul的功能与实现原理。

Zuul简介

Zuul是Neflix开源的Api Gateway服务器,它本质上是一个Servlet应用,其核心是通过一系列filters的实现来为整个微服务体系提供路由、安全、监控等边界服务。Zuul目前分为两个大版本Zuul1和Zuul2,它们的区别在于Zuul1的IO模型还是BIO的方式,而Zuul2则是使用NIO对Zuul1进行了重构,所以性能上要优于Zuul1。

正因为Zuul1的IO采用的是BIO,所以在Spring Cloud基于Spring Boot2.0的版本中才自己推出了基于NIO模型的Spring Cloud Gateway来取代Zuul,此时虽然Zuul2已经发布,但是因为发布的时间太晚,所以Spring Cloud对其已经不再默认集成了!

因此如果要升级Zuul的版本至Zuul2的话,你需要将Spring Cloud对应的版本升级到基于Spring Boot2.0的版本,并单独引入Zuul2的版本依赖。而在这种情况下,直接选用Spring Cloud Gateway作为网关服务可能会是一个更合适的选择。以下为基于Spring boot2.0的Spring Cloud版本依赖:

<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Finchley.SR3</version>
<relativePath />
</parent>

而考虑到历史项目原因,目前不少基于Spring Cloud的项目还是构建在基于Spring boot1.0的版本之上,所以在本篇文章中对Zuul的分析还是基于Zuul1的版本,这一点请大家知悉!

Zuul原理

在前面我们提到过Zuul本质上是一个Servlet应用,其核心就是通过定义一系列的filters来对用户的请求进行过滤处理,从而实现一些定制化的边缘服务功能如安全认证,打点监控等。类似于Servlet的Filter,只不过Zuul是提供了一个框架,来实现定义不同类型的filter,并对这些filter进行加载、编译、运行。下面我们来看一下Zuul的核心类图:

因为Zuul本身就是一个Servlet应用,而其要做的事情就是拦截所有用户请求来进行过滤,在Zuul框架中ZuulServlet就是这样一个类型,它类似于SpringMvc的DispatcherServlet,所有最终需要路由到微服务的请求,都会由它进行处理。

ZuulServlet中有3个核心的方法,它们分别是:preRoute(),route(), postRoute()。Zuul对所有request的处理逻辑都在这三个方法里面,而这些方法分别对应了Zuul中定义的几种标准过滤器类型:

  • PRE:这种过滤器会在请求被路由之前调用。我们可以利用这种过滤器类型实现身份认证等前置逻辑;

  • ROUTE:这种过滤器将请求路由到微服务,用于构建发送给微服务的请求。这种类型的过滤器Zuul已经帮我们实现,用于实现Gateway到内部微服务调用的路由、负载均衡、限流等功能;

  • POST:这种过滤器在路由到微服务以后执行。可以用来为响应添加标准的Http Header、收集统计信息和指标,并将响应从微服务发送给客户端;

  • ERROR:在请求处理阶段发生错误时执行该过滤器;

从代码层面看,以上方法的实际执行则是由具体实现了ZuulFilter接口的过滤器来实现的,这些过滤器会返回自身定义的类型如"pre",这样通过Zuul框架相应的设计就会最终调用到过滤器的对应方法了。(PS:篇幅有限,更细节的实现,需要大家去阅读源码)

Zuul实践示例

使用Zuul搭建一个Gateway非常简单,只需要基于Spring Boot项目,在主类加上注解@EnableZuulProxy即可。如:

@EnableZuulProxy
@SpringBootApplication
@EnableAutoConfiguration(exclude = {RedisAutoConfiguration.class,
RedisRepositoriesAutoConfiguration.class, DataSourceAutoConfiguration.class,
MongoAutoConfiguration.class, MongoRepositoriesAutoConfiguration.class})
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}

而在具体定制相应的Filter时只需要实现ZuulFilter接口,确定滤器类型后实现run方法就可以了。

public class LoginFilter extends ZuulFilter {
@Autowired
private GatewayLoginFilterConfig loginFilterConfig; @Override
public String filterType() {
return "pre"; //pre在请求真实url之前做处理
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest req = ctx.getRequest();
...
return null;
}

以上就是本文的基本内容了,希望能够让您能有所收获,欢迎转发+点赞!

参考资料:

https://github.com/Netflix/zuul

https://github.com/Netflix/zuul/wiki

http://www.sohu.com/a/221110905_467759

https://www.jianshu.com/p/af1554553b5c



Spring Cloud微服务中网关服务是如何实现的?(Zuul篇)的更多相关文章

  1. spring cloud学习笔记五 网关服务zuul

    网关服务是指,客户端发送的请求不用直接访问特定的微服务接口,而且是经过网关服务的接口进行交互,网关服务再去到特定的微服务中进行调用.   网关服务的路由功能和Nginx的反向代理一样,所有的服务都先会 ...

  2. Spring Cloud 微服务三: API网关Spring cloud gateway

    前言:前面介绍了一款API网关组件zuul,不过发现spring cloud自己开发了一个新网关gateway,貌似要取代zuul,spring官网上也已经没有zuul的组件了(虽然在仓库中可以更新到 ...

  3. Spring Cloud 微服务二:API网关spring cloud zuul

    前言:本章将继续上一章Spring Cloud微服务,本章主要内容是API 网关,相关代码将延续上一章,如需了解请参考:Spring Cloud 微服务一:Consul注册中心 Spring clou ...

  4. 在eclipse中使用maven构建spring cloud微服务

    使用eclipse中使用maven构建spring cloud微服务,springcloud通过maven构建项目.springcloud项目搭建. 工具/原料   eclipse maven spr ...

  5. Spring Cloud 微服务架构学习笔记与示例

    本文示例基于Spring Boot 1.5.x实现,如对Spring Boot不熟悉,可以先学习我的这一篇:<Spring Boot 1.5.x 基础学习示例>.关于微服务基本概念不了解的 ...

  6. Spring Cloud 微服务

    https://mp.weixin.qq.com/s?__biz=MzU0OTE4MzYzMw==&mid=2247486301&idx=2&sn=f6d45860269b61 ...

  7. Spring Cloud 微服务架构的五脏六腑,统统晒一晒!

    Spring Cloud 是一个基于 Spring Boot 实现的微服务框架,它包含了实现微服务架构所需的各种组件. 注:Spring Boot 简单理解就是简化 Spring 项目的搭建.配置.组 ...

  8. 浅谈现公司的Spring Cloud微服务框架

    目录 说在前面 服务注册与发现 服务网关及熔断 配置中心 消息中心.服务链路追踪 小言 说在前面 本文偏小白,大佬慎入,若有错误或者质疑,欢迎留言提问,谢谢,祝大家新年快乐. spring cloud ...

  9. 一张图了解Spring Cloud微服务架构

    Spring Cloud作为当下主流的微服务框架,可以让我们更简单快捷地实现微服务架构.Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟.经得起实际考验的服务框架组合起来 ...

随机推荐

  1. GUI学习之八——QToolButton的学习总结

    QToolButton提供一个快速的访问按钮,通常在工具栏内使用,一般不显示文本标签而显示图标. 一.按钮的样式风格设置 可以按照下面的风格对按钮进行样式设置 从左到右依次是仅显示图标.仅显示文字.图 ...

  2. abp 设置默认语言为中文

    abp 设置默认语言为中文 abp的默认语言设置,存放于数据库表AbpSettings中,这样配置可使默认语言为中文: name: Abp.Localization.DefaultLanguageNa ...

  3. 关于微信小程序切换获取不到元素的问题

    1.由于公司要实现微信小程序的自动化,所以开始学习python + appium 实现微信小程序自动化.在学习过程中遇到在切换webview后获取不到页面元素的问题,导致无法继续.今天在网上看到一篇关 ...

  4. js生成tree形组织机构下拉框

    1.首先我们正常数据是如下所示: [ { id: 1, pid: 0, name: '公司组织' }, { id: 2, pid: 1, name: '总经办' }, { id: 3, pid: 1, ...

  5. 2T以上磁盘格式化

    1.安装软件 对于 Debian/Ubuntu 用户, 使用 APT-GET 命令或者 APT 命令来安装 parted #apt-get install -y parted 对于 RHEL/Cent ...

  6. 关于管理,你可能一直有 3 个误解zz

    很多管理者认为,下属绩效低是由于其能力不行.其实,下属的绩效是由管理者决定的.一个好的管理者,必须对管理有正确的认知,才能形成有效的管理行为,让下属拥有绩效,并获得成长.来源丨春暖花开(ID:CCH_ ...

  7. 将Paul替换成Ringo

    <!DOCTYPE html><html><head lang="en">  <meta charset="UTF-8" ...

  8. 浅析列表页请求优化(history API)

    最近搞了下列表页请求的功能,并做了一下调研整理,记此文备忘. 列表页请求的功能到处可见,比如在博客园. 点击相应的页码,页面返回相应的内容,看上去似乎大同小异,但是一些小的细节还是可以区分优劣. fu ...

  9. 20145232韩文浩 《网络对抗技术》 Web基础

    Apache 因为端口号80已经被占用(上次实验设置的),所以先修改/etc/apache2/ports.conf里的端口为5232后重新开启 可以在浏览器中输入localhost:5208来检查是否 ...

  10. 07arguments对象.html

    07arguments对象.html <!DOCTYPE html> <html lang="en"> <head> <meta char ...