热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

接口调度者——API网关

image 背景 我们知道在微服务架构风格中,一个大应用被拆分成为了多个小的服务系统提供出来,这些小的服务他们自成体系,也就是说这些小系统可以拥有自己的数据库,框架甚至语言等,这些小系统通常
接口调度者——API 网关

image

背景

我们知道在微服务架构风格中,一个大应用被拆分成为了多个小的服务系统提供出来,这些小的服务他们自成体系,也就是说这些小系统可以拥有自己的数据库,框架甚至语言等,这些小系统通常以提供 Rest Api 风格的接口来被 H5, Android, IOS 以及第三方应用程序调用。
在《浅入浅出消息队列》这一篇文章中,我提到了消息队列是方便服务与服务之间的通信解耦,如下图所示:

接口调度者——API 网关

image.png

那么这时候问题来了,如果一个外部的应用(浏览器、App)要去访问这个大应用怎么办?
很简单啊,直接通过HTTP请求不就完了?

问题

真的这么简单吗?我们以淘宝的商品详情页为例:

接口调度者——API 网关

image

如上图所示,这个页面包含了视频、库存、商品价格、商品评价等内容,这些数据都来自不同的微服务中,所以没办法像传统单体应用一样依靠数据库的 join 查询来得到最终结果,因此就需要多次调用以检索数据,如下图所示:

接口调度者——API 网关

image.png

这就会引发几个严重的问题:

  • 不同的客户端设备可能需要不同的数据。Web,H5,APP,需要单独写一套API
  • 多次客户端请求导致用户体验不佳。移动网络相较于服务于服务间的局域网,有更低的带宽和更高的延时,如果可以同时执行请求倒也还好,但如果客户端要按照顺序执行请求,就会让用户体验变得异常糟糕。
  • 缺乏封装导致前后端不协调。过分的拆分API,会导致客户端和服务端过度耦合,再加上移动端APP的新版本迭代到每个手机用户时需要很久,这样会使后端很难更改服务的API。

这样显然是不好的设计,因此,本期的“天降猛男”就出现了——API网关。

API网关

再介绍API网关前,我们先来介绍一个设计模式——外观模式。
外观模式(Facade Pattern)它向现有的系统添加一个接口,来隐藏系统的复杂性。类图如下所示:

接口调度者——API 网关

image

之所以要在说API网关前说一下外观模式,是因为二者的设计理念是类似的。

和外观模式类似,API 网关封装了应用程序的内部架构,并为其客户端提供API,他还可能具有其他职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。下图展示了客户端、API网关和服务之间的关系。

接口调度者——API 网关

image

所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。其出现也是侧面贯彻了软件工程中“高内聚,低耦合”的思想。

核心作用

API 网关负责请求路由、API组合和协议转换。来自外部客户端的所有API请求首先会先转到API网关,后者再将请求路由到相应的服务。API网关使用API组合模式处理其他请求,调用多个服务并聚合结果。同时他还可以在客户端友好的协议(例如HTTP)与客户端不友好的协议之间进行转换。

请求路由

当API网关收到请求时,随机会查询路由映射,该映射将指定请求路由到哪个服务。例如,路由映射可以将HTTP方法和路径映射到服务的HTTP URL,这一点和Nginx提供的反向代理的功能是一样的,后面我们也会对其进行一个比较。
既然有路由映射,那存放在哪就是一个问题了,我们需要为API网关设置一个路由映射的存储位置,通过可能会用zookeeper等作为注册中心来使用,文末我们也会提一下弊端。

API组合

除去反向代理这个功能外,API网关还提供了API组合的操作。以上面的淘宝详情页为例,如果我们单独获取视频、商品价格、商品评论等信息,需要发多个请求(getVideo,getPrice,getComments)。有了API网关后我们就可以将API接口组合起来,通过一次请求(getItemDetail)来获取需要的信息,如下图所示,这样可以极大的改善由于网络延时导致的差用户体验。

接口调度者——API 网关

image

协议转换

API网关可以为外部客户端提供RESTful API,即使内部的服务使用混合的通信协议,例如REST、gRPC等。这样做的好处是,对于外部客户端而言,服务端更像是一个不可见的黑盒。

API网关和Nginx

本质上看API网关也是做了请求的转发,那既然Nginx也可以做请求转发,这两者有什么区别?
一张图就可以很好的理解了。

接口调度者——API 网关

image

Nginx做负载均衡时,考虑到API网关在系统中不止一个(以集群的方式做高可用),我们可以将Nginx至于API网关前,负责对API网关的负载均衡,然后再由网关决定进入到哪个真实的web 服务器。
这样就可以让两者的分工更加明确:API网关聚合服务,Nginx请求转发

API 网关的优缺点

API网关封装了应用程序的内部结构,使得客户端只需要同网关交互,而不必调用特定的服务。同时API 网关为每一类客户端提供了特定的 API ,从而减少客户端与应用程序间的交互次数,简化客户端代码的处理。
但就和所有中间件一样,他们都存在一个共同的问题,API网关的存在使系统增加了一个必须开发、部署和维护的高可用组件。如果这个组件没有处理好,那么 API 网关就会变成了应用的性能瓶颈。
而且为了暴露每个微服务,开发人员必须更新 API 网关,所以就有可能会搭配其他服务发现类的中间件使用,例如zookeeper,这样就又引入了新的中间件。所以我们需要保证API 网关的更新过程要尽可能地简单,否则为了更新网关,开发人员将不得不排队等待。
由此可见,API网关也并不是一颗”银弹”,我们在中间件的选择上还是需要结合项目的实际情况,万不可追求新颖就滥用中间件,适合自己的才是最好的。不过,API网关虽然仍有不足,但对于大多数现实世界的应用程序而言使用 API 网关是合理的。


推荐阅读
  • 本文介绍了OkHttp3的基本使用和特性,包括支持HTTP/2、连接池、GZIP压缩、缓存等功能。同时还提到了OkHttp3的适用平台和源码阅读计划。文章还介绍了OkHttp3的请求/响应API的设计和使用方式,包括阻塞式的同步请求和带回调的异步请求。 ... [详细]
  • 本文比较了eBPF和WebAssembly作为云原生VM的特点和应用领域。eBPF作为运行在Linux内核中的轻量级代码执行沙箱,适用于网络或安全相关的任务;而WebAssembly作为图灵完备的语言,在商业应用中具有优势。同时,介绍了WebAssembly在Linux内核中运行的尝试以及基于LLVM的云原生WebAssembly编译器WasmEdge Runtime的案例,展示了WebAssembly作为原生应用程序的潜力。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • 云原生应用最佳开发实践之十二原则(12factor)
    目录简介一、基准代码二、依赖三、配置四、后端配置五、构建、发布、运行六、进程七、端口绑定八、并发九、易处理十、开发与线上环境等价十一、日志十二、进程管理当 ... [详细]
  • [翻译]微服务设计模式5. 服务发现服务端服务发现
    服务之间需要互相调用,在单体架构中,服务之间的互相调用直接通过编程语言层面的方法调用就搞定了。在传统的分布式应用的部署中,服务地 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了在Oracle数据库中创建序列时如何选择cache或nocache参数。cache参数可以提高序列的存取速度,但可能会导致序列丢失;nocache参数可以避免序列丢失,但在高并发访问时可能导致性能问题。文章详细解释了两者的区别和使用场景。 ... [详细]
  • 本文主要介绍了MySQL中子查询的基本用法和三种用法,包括生成参考值、内层查询与外层查询的比较操作以及使用事件号在成绩表中找到学生的分数记录。通过详细解析子查询的实例,帮助读者更好地理解和应用子查询。 ... [详细]
  • 本文总结和分析了JDK核心源码(2)中lang包下的基础知识,包括常用的对象类型包和异常类型包。在对象类型包中,介绍了Object类、String类、StringBuilder类、StringBuffer类和基本元素的包装类。在异常类型包中,介绍了Throwable类、Error类型和Exception类型。这些基础知识对于理解和使用JDK核心源码具有重要意义。 ... [详细]
  • 使用Docker安装和运行Nexus
    本文介绍了使用Docker安装和运行Nexus的方法,包括docker-compose.yml配置和启动时可能出现的权限问题解决方法。同时提供了登录控制台验证安装的地址和登录信息。 ... [详细]
  • 熟练掌握Spring Cloud,终于成为Java工程师的面试门槛 ... [详细]
author-avatar
吾似梦蝴蝶_321
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有