正文
更深入一点看我们的架构,网关的所有特性和平台基础架构需要运行在异步环境里。Netflix的所有平台基础架构,包括Zuul过滤器,都是基于同一个假设而构建的,那就是它们会被运行在阻塞式的环境里。跟请求相关的线程变量在我们的支持包和平台代码里无处不在。使用阻塞式I/O是这个平台的第二大特点。这些设计概念在异步非阻塞的架构里无法正常工作。识别出这些陷阱,并构建出基于异步非阻塞架构的可行方案是很耗费时间的,有时候会变得很困难。
作为Netflix网关的构成角色之一,尝试理解我们所看到的一切也是这个旅程的一部分。简单地说,这个角色主要负责路由、观察和规范化那些进入Netflix的请求。我们使用迂回的方式构建Zuul 2,我们先移除Zuul 1的大部分业务逻辑,再把新的逻辑填充进原先的系统。除了让Zuul 2在网关里的角色更加明确之外,也简化了阻塞式代码的迁移工作,因为我们移除了大量代码。
创建Zuul过滤器和过滤解析异步化也一直是这次转型的另一个重大挑战。正如博文里所讲的那样,在Zuul 2之前我们就做了这方面的工作,所以我们可以在Zuul 1和Zuul 2上运行之前创建的Zuul过滤器(异步代码可以在同步环境里运行,反之则不行)。这样我们就可以基于这些过滤器继续开发网关的其它功能特性。不过在迭代过程中还是会对Zuul过滤器接口进行修改,并把这些过滤器串联起来。我们使用RxJava来串联Zuul过滤器。通过对100多个Zuul过滤器进行串联,我们发现这真是一个重注细节、耗费时间的任务。
最后,我们使用几个迭代来构建可以让Zuul 2运行起来的框架。我们从使用早期版本的Netty转到使用RxNetty项目。在构建Zuul 2的过程中,我们发现有些地方仍需要Netty的核心功能,而RxNetty却把它们移除了,所以在这些地方我们仍然使用Netty。一路走来,伴随着学习和纠错,我们构建了一个越来越健壮的产品。
InfoQ:你在博客里提到,除了后端延迟、错误重试,多线程系统能够应对大部分场景。是否还有其它原因促使你转向新的架构?