为什么微服务一定要有API网关?

Posted 四猿外

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么微服务一定要有API网关?相关的知识,希望对你有一定的参考价值。

微服务不能没有网关,就如同 Java 程序员不能没有IDEA、Eclipse。为什么呢?

之所以网关对微服务这么重要,主要有以下几点原因:

1. 解决 API 放哪里的问题

要知道,采用微服务架构的系统本身是由很多的独立服务单元组合起来的。而客户端要调用系统,则必须通过系统提供的各种对外开放的 API 来实现。

问题来了,这些 API 要放在哪里呢?直接放在组成系统的服务单元上行不行?

比如,在一套电商系统上,关于订单相关的 API ,放在组成订单服务的服务单元上;风控服务的 API ,放在组成风控服务的服务单元上。

好,咱们假设有这么一个场景,有一位用户想在这套电商系统上查看下商品详情。那么,这个查看商品详情的操作,就可能:

  • 调用商品服务的 API 获取商品描述
  • 调用评价服务的 API 获取相关评价
  • 调用商家服务的 API 获取商家信息
  • 调用礼券服务的 API 获取相关礼券
  • ……
  • 可以看到,就这么一个商品查看操作,就可能会调用许多服务的 API。

    那这些 API 如果全部分散到各个服务单元上,供客户端调用,像查看商品这么简单的一次操作,客户端就可能需要远程访问好几次甚至十几次服务器。

    微服务自己又讲究把 API 的粒度划分的很细,也就是说,可能从商品服务上调用商品信息,不止是调用一次商品服务就够了,很可能需要多次对商品服务的不同 API 进行调用,才能获取到足够的数据。

    这样一来,客户端需要访问服务器的次数就更多了,可能十几次都不够,得几十次。

    这种多次访问服务器的行为,会极大延迟客户端的界面响应时间,很不现实。

    所以,把 API 放到各个业务相关的服务单元上,看上去问题很大。

    那为什么引入网关就能解决这个问题呢?

    因为引入网关,就相当于在客户端和微服务之间加了一层隔离。通常,网关本身会和各个服务单元处于同一个机房,这样,客户端做业务操作的时候,只需要访问一次网关。然后剩下的事情,再由网关分别访问同在一个机房的不同的服务,再把拿到的数据统一在网关封装好,返回给客户端就好。

    2. 解决边缘功能集成的问题

    在一套微服务组成的系统里,除了必须的业务功能以外,还有为了系统自身的健壮与安全,以及微服务本身的管理,而必须引入的一些非业务功能。对于这些非业务又很重要的功能,我们统称为边缘功能。

    还是拿电商系统为例,我们来看一些重要的边缘功能。

    假设因为我们做了一次非常大的促销活动,导致流量过大,系统承载不了了。此时,为了保证系统本身的稳定,我们就需要把一些承载不了的流量给通过各种手段消化掉,一般的做法有三种:

  • 限流:通过令牌桶等算法,把一些额外的流量挡在系统外面,不让其访问。

  • 降级:由于系统可能已经过载了,此时,我们就放弃处理一些服务和页面的请求或者仅简单处理,比如直接返回一个报错。

  • 熔断:有些时候,系统过载过度或者上线出了 bug,降级都解决不了问题。比如,缓存失效了,导致大量请求频繁访问了数据库,而这种频繁访问数据库可能造成了大量的 IO 操作,结果又去影响了数据库所在的操作系统,同时,这个操作系统上又有着别的重要服务,直接也被影响了。对于这种连锁反应,我们称之为雪崩。而为了防止雪崩,我们就会坚决把缓存失效导致数据库被频繁访问的服务给停掉,这就是熔断。

  • 可以看到,像限流、降级、熔断这些系统保障策略,最合适的地方应该是有一个集中的请求入口点,就像古时候,老百姓进城需要过城门那样。

    当系统出现问题的时候,直接就在这个入口点做相应的操作即可。

  • 限流,就直接在这个入口点限制后续请求。

  • 降级,就直接在这个入口点判断请求想要访问的服务或者页面,直接报错返回。

  • 熔断,就直接在这个入口点,断开所有访问特定服务的请求连接,然后再把后继对特定服务的访问,也统统拦在门外。

  • 在电商系统里,有很多特殊场景的接口,需要受到严格的限制。

    比如,支付接口,访问它就需要认证和权限控制。又比如,对于系统的访问,有时候不能让国外的去访问国内的网站,这就需要限制客户端的访问 IP,所以系统还需要认证和授权功能。

    那这种认证和授权也最合适放在请求的一个集中入口点,统一实现。

    还记得上面咱们说过的网关的 API 统一存放吗?我们只需要对这些 API 做对应的权限设置,当请求访问特殊场景接口的时候,必定会通过 API 访问。所以,限制接口的访问,本质上就是对特定 API 的限制,那么,放在网关再合适不过了。

    现实里,我们有时候需要把线上的流量镜像出来,转发到灰度环境,利用这些镜像出来的流量既可以用于小范围测试,又可以更好的评估系统所能承载的最大吞吐量,也因此,系统需要有一个统一入口做分流。

    可以看到,无论是系统需要的保障策略,认证授权,还是流量分流等功能,都应该放到一个统一的请求入口处才能得到最好的实现。网关恰好就承担了这么个统一请求入口的角色。

    所以,对于微服务中,林林总总的边缘功能,往往会通过插件的形式,集成在 API 网关中。

    3. 解耦了客户端和后端微服务

    一套项目,在使用微服务模式的初期,往往后端变化是十分频繁的。

    频繁变化的原因有很多,像业务领域划分不合适啊,像某个业务模块急速膨胀啊,都可能导致后端微服务的剧烈变化。

    在这种情况下,如果没有网关,很可能就会出现客户端需要被迫随着后端的变化而变化的情况。

    比如,在电商系统里,初期我们很可能会把风控服务做的非常小。随着业务的发展,风控服务越来越庞大,此时,风控服务就可能被分解为决策引擎和分析中心等更多更细的服务。

    在电商里,风控往往是下单、支付等操作的必要前置操作。如果没有网关去分隔开客户端和微服务,客户端直接和风控服务打交道,那么风控服务拆分,API 必然不会稳定,API 的变化,自然会引发调用 API 客户端代码的变化。

    有了网关之后,情况就好了很多了。当风控服务本身频繁变化的时候,我们只需要改动网关的代码就好。而服务器代码的升级可是远远要比客户端代码的升级容易太多了。

    原创不易,看完有收获话,随手点个在看


    你好,我是四猿外。

    一家上市公司的技术总监,管理的技术团队一百余人。想了解我如何管理团队——我,管理100多人团队的二三事

    我从一名非计算机专业的毕业生,转行到程序员,一路打拼,一路成长。

    我会通过公众号,
    把自己的成长故事写成文章,
    把枯燥的技术文章写成故事。

    我建了一个读者交流群,里面大部分是程序员,一起聊技术、工作、八卦。欢迎加我微信,拉你入群。


    推荐阅读

    新年新气象,宣布个事情
    懵了,Kafka、RabbitMQ到底选哪个?

    为什么说微服务一定要有 API 网关?

    cnblogs.com/java-zhao/p/6716059.html

    一、什么是服务网关

    服务网关 = 路由转发 + 过滤器

    1、路由转发:接收一切外界请求,转发到后端的微服务上去;

    2、过滤器:在服务网关中可以完成一系列的横切功能,例如权限校验、限流以及监控等,这些都可以通过过滤器完成(其实路由转发也是通过过滤器实现的)。

    二、为什么需要服务网关

    上述所说的横切功能(以权限校验为例)可以写在三个位置:

    • 每个服务自己实现一遍
    • 写到一个公共的服务中,然后其他所有服务都依赖这个服务
    • 写到服务网关的前置过滤器中,所有请求过来进行权限校验

    第一种,缺点太明显,基本不用;

    第二种,相较于第一点好很多,代码开发不会冗余,但是有两个缺点:

    • 由于每个服务引入了这个公共服务,那么相当于在每个服务中都引入了相同的权限校验的代码,使得每个服务的jar包大小无故增加了一些,尤其是对于使用docker镜像进行部署的场景,jar越小越好;
    • 由于每个服务都引入了这个公共服务,那么我们后续升级这个服务可能就比较困难,而且公共服务的功能越多,升级就越难,而且假设我们改变了公共服务中的权限校验的方式,想让所有的服务都去使用新的权限校验方式,我们就需要将之前所有的服务都重新引包,编译部署。

    而服务网关恰好可以解决这样的问题:

    • 将权限校验的逻辑写在网关的过滤器中,后端服务不需要关注权限校验的代码,所以服务的jar包中也不会引入权限校验的逻辑,不会增加jar包大小;
    • 如果想修改权限校验的逻辑,只需要修改网关中的权限校验过滤器即可,而不需要升级所有已存在的微服务。

    所以,需要服务网关!!!

    三、

    引入服务网关后的微服务架构如上,总体包含三部分:、open-service和service。

    1、总体流程:

    • 服务网关、open-service和service启动时注册到注册中心上去;
    • 用户请求时直接请求网关,网关做智能路由转发(包括服务发现,负载均衡)到open-service,这其中包含权限校验、监控、限流等操作
    • open-service聚合内部service响应,返回给网关,网关再返回给用户

    2、引入网关的注意点

    • 增加了网关,多了一层转发(原本用户请求直接访问open-service即可),性能会下降一些(但是下降不大,通常,网关机器性能会很好,而且网关与open-service的访问通常是内网访问,速度很快);
    • 网关的单点问题:在整个网络调用过程中,一定会有一个单点,可能是网关、nginx、dns服务器等。防止网关单点,可以在网关层前边再挂一台nginx,nginx的性能极高,基本不会挂,这样之后,网关服务就可以不断的添加机器。但是这样一个请求就转发了两次,所以最好的方式是网关单点服务部署在一台牛逼的机器上(通过压测来估算机器的配置),而且nginx与zuul的性能比较,根据国外的一个哥们儿做的实验来看,其实相差不大,zuul是netflix开源的一个用来做网关的开源框架;
    • 网关要尽量轻。

    3、服务网关基本功能

    • 智能路由:接收外部一切请求,并转发到后端的对外服务open-service上去;
      • 注意:我们只转发外部请求,服务之间的请求不走网关,这就表示全链路追踪、内部服务API监控、内部服务之间调用的容错、智能路由不能在网关完成;当然,也可以将所有的服务调用都走网关,那么几乎所有的功能都可以集成到网关中,但是这样的话,网关的压力会很大,不堪重负。
    • 权限校验:只校验用户向open-service服务的请求,不校验服务内部的请求。服务内部的请求有必要校验吗?
    • API监控:只监控经过网关的请求,以及网关本身的一些性能指标(例如,gc等);
    • 限流:与监控配合,进行限流操作;
    • API :类似于一个aspect切面,记录接口的进入和出去时的相关日志
    • 。。。后续补充

    上述功能是网关的基本功能,网关还可以实现以下功能:

    • A|B测试:A|B测试时一块比较大的东西,包含后台实验配置、数据埋点(看转化率)以及分流引擎,在服务网关中,可以实现分流引擎,但是实际上分流引擎会调用内部服务,所以如果是按照上图的架构,分流引擎最好做在open-service中,不要做在服务网关中。
    • 。。。后续补充

    4、技术选型

    笔者准备自建一个轻量级的服务网关,技术选型如下:

    • 开发语言:java + groovy,groovy的好处是网关服务不需要重启就可以动态的添加filter来实现一些功能;
    • 微服务基础框架:springboot;
    • 网关基础组件:netflix zuul;
    • 服务注册中心:consul;
    • 权限校验:jwt;
    • API监控:prometheus + grafana;
    • API统一日志收集:logback + ELK;
    • 压力测试:Jmeter;
    • 。。。后续补充

    推荐好文


    以上是关于为什么微服务一定要有API网关?的主要内容,如果未能解决你的问题,请参考以下文章

    为什么微服务一定要有网关?

    SCG | 微服务网关一为什么要有网关生产环境如何选择网关

    微服务架构中为何要有网关

    微服务漫谈 | 自建API网关之架构设计篇

    对微服务API服务网关的理解

    Spring Cloud Zuul微服务网关的API限流