本文改编自 Chris Stetson 发表在 nginx.conf 上的一个有关如今的微服务以及如何使用 Nginx 构建一个快速的, 安全的网络系统的演讲,
自我介绍
Chris Stetson:Hi, 我的名字是 Chris Stetson, 我在 Nginx 带领专业服务部门, 同时也领导微服务实践.
今天我们要谈论微服务以及如何使用 Nginx 构建一个快速的, 安全的网络系统. 在我们谈话的最后, 我们将与我们在 Zokets 的合作伙伴向您展示一个使用 Fabric 模式如何非常快速和轻松地构建一个微服务的 demo.
在我们探讨 Fabric 模式之前, 我想谈一谈微服务并且从 Nginx 的角度来看这意味着什么.
0:56 - 大转变
微服务已经引起了应用程序架构的重大转变.
当我第一次开始构建应用程序时, 他们都是差不多的. 幻灯片中所展示的单体架构也象征了应用程序的构造方式.
目前存在着某种类型的虚拟机 (VM), 对我来说, 就是通常的 Java. 在虚拟机中应用的功能组件以对象的形式存在, 这些对象是在内存中相互通讯的, 它们将来来回回处理并进行方法调用. 偶尔, 你会采用诸如通知等机制来接触到其他系统以便获取数据或传递信息.
有了微服务之后, 应用程序如何构建的范式是完全不同的了. 你的功能组件会从在同一个主机的内存中通过虚拟机相互通讯转变到部署在容器中, 并且使用 Restful API 调用通过 HTTP 来相互连接.
这是非常强大的, 因为它赋予了你功能隔离. 它为您提供了更细粒度的可伸缩性, 并且你可以获得更好地处理故障的弹性. 很多情况下这是简单的事实, 你只需要使用 HTTP 进行跨网络调用.
现在, 这种方法也有一些缺点.
一件轶事
我有一个暗黑的秘密, 我是一个微软的员工并且从事. Net 开发已经很多年了. 当我在那儿的时候, 我搭建了一个他们的名为 Showcase 的视频发布平台.
Showcase 是一个用来将微软内部发布的所有视频发布到网上的工具. 人们可以观看这些视频并进行学习, 比如 Microsoft Word 的使用提示和技巧. 这是一个非常受欢迎的平台, 我们有很多人使用它, 并且其中很多人都会在我们发布的视频上发表评论.
Showcase 从一开始就是一个. Net 单体应用, 随着它日益受欢迎, 我们决定应该将它更换为 SOA 架构. 转换是相对容易的. Visual Studio 提供了本质上的翻转开关的能力, 也就是将你的 DLL 调用转变为 Restful API 调用. 随着一些小的重构, 我们能够让我们的代码运行得相当好. 我们也为这些评论和应用内的社区功能使用智能社区服务.
紧密的回路问题
看起来我们是 SOA 可行的, 在我们的首次测试中, 一切都工作正常, 直到我们将系统切换到我们的 Staging 环境并开始使用生产环境数据时, 我们就会看到一些严重的问题. 这些问题在在页面上有很多评论.
这是一个非常受欢迎的平台, 其中的一些页面已经有多达 2000 条评论了. 当我们深入这些问题时, 我们意识到这些页面需要花费一分钟进行渲染的原因是因为智能社区服务首先需要填充用户名, 然后对每一个用户名都需要发起一个对于用户数据库的网络调用来获得用户详细信息并且填充在渲染页面上. 这是非常低效的, 需要一到两分钟来渲染页面, 而在内存中进行通常只需要 5 到 6 秒钟.
缓解
当我们经历了发现和解决问题的过程后, 我们最终通过一些措施来调整优化系统, 比如对所有的请求进行分组. 我们缓存了一些数据, 最终我们优化了网络来真正的提高性能.
所以, 这与微服务有什么关系呢? 对的, 借助于微服务, 你基本上是采用 SOA 架构的, 并且会将其放入超光速引擎中. 在 SOA 架构中所有的对象都是包含在单个虚拟机中并且在其内部管理, 在内存中相互通讯, 而现在微服务中是使用 HTTP 进行数据交换的.
当这样做没有问题时, 你会获得很好的性能和线性可伸缩性.
Nginx 能够很好地与微服务工作
Nginx 是一个你可以用来过渡到微服务的最佳工具之一.
关于 Nginx 和微服务的一些历史. 我们从一开始就参与了微服务运动, 还是第一个从 Docker Hub 下载应用的, 我们的客户以及那些拥有一些世界上最大的微服务安装量的最终用户广泛地在他们的基础设施使用 Nginx.
原因是 Nginx 很小, 很快并且很可靠.
Nginx 微服务参考架构
我们还致力于在 Nginx 内部使用微服务工作已经有一段时间了. 这是一个我们已经搭建的程式化的 Nginx 微服务参考架构, 目前正在 AWS 上运行.
我们拥有 6 个核心的微服务, 它们都运行在 Docker 容器里. 我们决定建立一个多语种的应用, 所以每个容器都可以运行不同的语言, 我们目前使用了 Ruby,Python,PHP,Java 和 Node.js.
我们搭建了这个使用十二要素应用的系统, 稍加修改, 就会使其更好地为微服务工作从而可以替代 Roku 平台. 稍后, 我们将向您展示一个实际上运行在 demo 里的应用.
MRA 的价值
为什么我们要建立这样一个参考的微服务架构呢?
我们建立这个参考架构是因为我们需要给我们的客户提供构建微服务的蓝图, 我们也想在微服务上下文中测试 Nginx 和 Nginx Plus 的功能, 弄清楚如何才能更好地利用它的优势. 最后, 我们要确保我们对于微服务生态系统以及其可以给我们提供什么有一个深入的理解.
网络问题
让我们回到我们讨论的大转变.
从将运行在内存里并且被虚拟机管理的你的应用的所有功能组件迁移到通过网络进行工作并且相互通讯的方式, 你会本质上引入一系列为了应用有效工作需要你解决的问题.
第一你需要服务发现, 第二, 你需要在架构中为所有不同的实例进行负载均衡, 然后还有第三个, 你需要操心性能和安全.
无论是好是坏, 这些问题密不可分, 你必须做权衡, 有希望的是我们有一个可以解决所有这些问题的解决方案.
让我们更深入地看待每一个问题.
服务发现
让我们来谈谈服务发现. 在单体应用中, APP 引擎会管理所有的对象关系, 你永远不必担心一个对象与另一个对象的相对位置, 你只需要简单的调用一个方法, 虚拟机会连接到对象实例, 然后在调用完毕后销毁.
然后有了微服务, 你需要考虑那些服务的位置. 不幸的是, 这不是一个普遍的标准流程. 您正在使用的各种服务注册中心, 无论是 Zookeeper,Consul,etcd 或者其它的, 都会以不同的方式进行工作. 在这个过程中, 你需要注册你的服务, 还需要能够读取这些服务在哪里并且可以被连接.
负载均衡
第二个问题是关于负载均衡的. 当您拥有多个服务实例时, 您希望能够轻松地连接到它们, 将您的请求在它们中高效地分发, 并以最快的方式执行, 所以不同实例之间的负载均衡是非常重要的问题.
不幸的是, 最简单形式的负载均衡是非常低效的. 当你开始使用不同的更加复杂的方案做负载均衡时, 它也变得更加复杂并且不易于管理. 理想情况下, 您希望您的开发人员能够基于他们的应用程序的需求决定何种负载均衡方案. 例如, 如果你连接到一个有状态的应用程序, 你需要拥有持久化, 这样可以确保你的 Session 信息会被保留.
安全和快速通讯
也许微服务最令人生畏的领域是性能和安全.
当在内存中运行时, 一切都很快. 现在, 运行在网络上就会慢了一个数量级.
被安全地包含在一个系统中的信息, 通常是二进制格式的, 现在会被用文本格式在网络上传输. 现在是比较容易在网络上布置嗅探器并能够监听你的应用正在被移动的所有数据.
如果要在传输层加密数据, 那么会在连接速率和 CPU 使用率方面引入显著的开销. SSL/TLS 在其全面实施阶段需要九个步骤来初始化一个请求. 当你的系统每天需要处理成千上万, 几万, 数十万或数百万的请求时, 这就成为性能的一个重要障碍了.
一个解决方案
我们已经在 Nginx 开发的一些解决方案, 我们认为, 会解决所有的这些问题, 它赋予你健壮的服务发现, 非常棒的用户可配置负载均衡以及安全和快速加密.
网络架构
让我们来谈谈你可以安装和配置你的网络架构的各种方法.
我们提出了三种网络模型, 它们本身并不相互排斥, 但我们认为它们属于多种格式的. 这三种模式是 Proxy 模式, Router Mesh 模式和 Fabric 模式 -- 这是最复杂的, 并在许多方面在其头部进行负载均衡.
Proxy 模式
Proxy 模式完全聚焦于你的微服务应用的入站流量, 并且事实上忽略内部通讯.
你会获得 Nginx 提供的所有的 HTTP 流量管理方面的福利. 你可以有 SSL/TLS 终止, 流量整形和安全, 并且借助于最新版本的 Nginx Plus 和 ModSecurity, 你可以获得 WAF 能力.
你也可以缓存, 你可以将 Nginx 提供给你的单体应用的所有东西添加到你的微服务系统里, 并且借助于 Nginx Plus, 你可以实现服务发现. 当你的 API 实例上下浮动时, Nginx Plus 可以在负载均衡工具里动态地添加和减去它们.
Router Mesh 模式
Router Mesh 模式类似于 Proxy 模式, 在其中我们有一个前端代理服务来管理接入流量, 但它也在服务之间添加了集中式的负载均衡.
每个服务连接到集中式的 Router Mesh, 它管理不同服务之间的连接分发. Router Mesh 模式还允许你在熔断器模式中搭建, 以便可以对你的应用添加弹性并允许你采取措施来监控和拉回你的失效的服务实例.
不幸的是, 因为该模式增加了一个额外的环节, 如果你不得不进行 SSL/TLS 加密, 它事实上加剧了性能问题. 这就是引入 Fabric 模式的原因.
Fabric 模式
Fabric 模式是将其头部的所有东西翻转的模式.
就像之前的另外两个模式一样, 在前面会有一个代理服务器来管理流入流量, 但与 Router Mesh 模式不同的地方就是你用运行在每个容器里的 Nginx Plus 来替代了集中式的 Router.
这个 Nginx Plus 实例对于所有的 HTTP 流量作为反向和正向代理, 使用这个系统, 你可以获得服务发现, 健壮的负载均衡和最重要的高性能加密网络.
我们将探讨这是如何发生的, 以及我们如何处理这项工作. 让我们先来看看一个服务如何连接和分发他们的请求结构的正常流程.
正常的流程
在这个图中, 你可以看到投资管理器需要跟用户管理器通讯来获取信息. 投资管理器创建了一个 HTTP 客户端, 该客户端针对服务注册中心发起了一个 DNS 请求并获得返回的一个 IP 地址, 接着初始化了一个到用户管理器的 SSL/TLS 连接, 该连接需要通过九阶段的协商或者是 "握手" 过程. 一旦数据传输完毕, 虚拟机会关闭连接并进行 HTTP 客户端的垃圾回收.
整个过程就是这样. 这是相当简单和易于理解的. 当你把它分解成这些步骤时, 您可以看到该模式是如何真正完成请求和响应过程的.
在 Fabric 模式中, 我们已经改变了这一点.
Fabric 模式的细节
你会注意到的第一件事是 Nginx Plus 是运行在每一个服务里的, 并且应用程序代码是在本地与 Nginx Plus 通信的. 因为这些是本地连接, 你不需要担心加密问题. 它们可以是从 Java 或者 PHP 代码到 Nginx Plus 实例的 HTTP 请求, 并且都是在容器内的本地 HTTP 请求.
你也注意到 Nginx Plus 会管理到服务注册中心的连接, 我们有一个解析器, 通过异步查询注册中心的 DNS 实例来获取所有的用户管理器实例, 并且预先建立连接, 这样当 Java 服务需要从用户管理器请求一些数据的时候, 可以使用预先建立的连接.
持久的 SSL/TLS 连接
微服务之间的有状态的, 持久化的并且可以加密的连接是真正的益处.
记得在第一个图中服务实例是如何通过一些流程的吧, 比如创建 HTTP 客户端, 协商 SSL/TLS 连接, 发起请求并关闭的吗? 在这里, Nginx 预先建立了微服务之间的连接, 并使用 Keepalive 特性, 保持调用之间的持续连接, 这样你就不必为每一个请求处理 SSL/TLS 协商了.
本质上, 我们创建了一个迷你的从服务到服务的 VPN 连接. 在我们最初的测试中, 我们发现连接速度增加了 77%.
熔断器 Plus
在 Fabric 模式以及 Router Mesh 模式中, 你也可以从创建和使用熔断器模式中获得好处.
本质上, 您定义了一个在服务内部的活跃的健康检查, 并设置缓存, 以便在服务不可用的情况下保留数据, 从而获得完整的熔断器功能.
所以, 现在我可以确定你认为 Fabirc 模式听起来很酷, 并且想在实际环境中跃跃欲试.
Zokets Demo
我们已经和 Zokets 的合作伙伴一起工作了, 他们帮助我们搭建了一个系统可以轻松地可视化, 控制并且自动化那些构建基于微服务的 Fabric 模式应用的流程.
我想介绍 Zokets 的 CTO Sehyo Chang, 他将帮助我们在他们的平台上展示 Fabric 模式.
结论
对于那些有兴趣学习更多关于如何构建这些类型的网络架构的小伙伴, 我强烈推荐我们的博客系列文章, 上面讨论了微服务参考架构, 涵盖了每一个模式: Proxu 模式, Router Mesh 模式和 Fabric 模式.
来源: http://www.roncoo.com/article/detail/132712