挎斗模式
将应用程序的组件部署到单独的进程或容器中以提供隔离和封装。这种模式还支持异构组件和技术组成的应用程序。
这种模式叫做挎斗模式,因为它类似于三轮摩托车的挎斗。该模式下挎斗附加到父应用程序,并为应用程序提供支持功能。挎斗还拥有与父应用程序相同的生命周期,与父应用程序一起创建和退休。挎斗模式有时被称为助手模式,是一种解耦模式。
背景和问题
应用程序和服务通常需要如监视,日志记录,配置和网络服务等相关功能。这些外围的任务可以作为单独的组件或服务来实现。
如果将它们紧密集成到应用程序中,与应用程序在同一进程运行,从而可以有效地利用共享资源。然而,这也意味着它们没有很好的隔离,任何一个组件中断可能会影响其它组件或整个应用程序。而且,它们通常需要使用与父应用程序相同的语言来实现。因此,组件和应用程序之间存在着密切的相互依存关系。
如果将应用程序分解为服务,则可以使用不同的语言和技术构建每个服务。虽然这提供了更多的灵活性,但这意味着每个组件都有自己的依赖关系,并且需要特定语言的库来访问底层平台以及与父应用程序共享的任何资源。此外,将这些功能部署为单独的服务可能会增加应用程序的延迟。管理这些特定语言的接口的代码和依赖关系也会增加很大的复杂性,特别是托管,部署和管理方面。
解决方案
将主要应用程序的一组任务集中在一起,将它们运行在自己的进程或容器中,为跨语言的平台服务提供一个同构的接口。
挎斗服务不一定是应用程序的一部分,但与之相关。父应用程序在哪里它就在哪里。挎斗们是支持与主应用程序一起部署的进程或服务。 挎斗依附于摩托车上,每辆摩托车都可以有自己的挎斗。同样的,挎斗服务和父应用程序生死相依。对于应用程序的每个实例,旁边部署和托管了一个挎斗实例。
挎斗模式的优点:
- 挎斗在运行时环境和编程语言方面独立于其主要应用,因此不需要用每种语言开发一个挎斗。
- 挎斗可以访问与主应用程序相同的资源。例如,挎斗可以监视挎斗和主应用程序使用的系统资源。
- 由于与主要应用程序相邻,它们之间的通信没有明显的延迟。
- 即使对于不提供可扩展性机制的应用程序,也可以使用挎斗来扩展功能,将其作为主应用程序作为自己的进程附加在相同的主机或子容器中。
挎斗模式通常与容器一起使用,称为挎斗容器或助手容器。
问题和注意事项
- 考虑部署服务、进程或者容器的部署和打包格式。容器特别适用于挎斗模式。
- 设计挎斗服务时,请慎重决定进程间通信机制。尝试使用语言或框架无关的技术,除非性能要求。
- 在将功能放入挎斗之前,请考虑它作为单独的服务或更传统的守护进程运行方式更好。
- 还要考虑功能是否能以库或使用传统的扩展机制实现。特定语言的库可能具有更深层次的集成和更少的网络开销。
何时使用该模式
在以下场景使用该模式:
- 主要应用程序使用异构语言和框架。位于挎斗服务中的组件可以由使用不同框架的不同语言编写的应用程序使用。
- 远程团队或不同组织拥有组件。
- 组件或功能必须与应用程序位于同一主机上
- 需要一个共享主应用程序整体生命周期的服务,该服务可以独立更新。
- 需要对特定资源或组件的资源限制进行细粒度的控制。例如,限制特定组件使用的内存量。可以将组件部署为挎斗,独立于主应用程序管理内存使用。
该模式可能不适合以下场景:
- 当进程间通信需要优化时。父应用程序和挎斗服务之间的通信存在一些开销,特别是调用延迟。这恐怕不是聊天接口的能接受的折衷。
- 对于小型应用程序,为每个实例部署挎斗服务的资源开销超过了隔离的优势。
- 当服务需要与主应用程序独立或者使用不同方式进行扩展时。如果是这样,最好将功能部署为单独的服务。
案例
挎斗模式适用于许多场景。下面是一些常见的例子:
- 基础设施API。基础设施开发团队创建一个与每个应用程序一起部署的服务,而不是一个特定于语言的客户端库访问基础架构。该服务作为挎斗加载,并为基础架构服务提供了一个共同的层,包括日志记录,环境数据,配置存储,服务发现,健康检查和看门狗服务。挎斗还监视父应用程序的主机环境和进程(或容器),并将信息记录到集中式服务。
- 管理NGINX/HAProxy。用监控环境状态的挎斗服务一起部署NGINX,然后在需要更改状态时更新NGINX配置文件并回收进程。
- 大使挎斗。将大使服务部署以挎斗形式部署。该应用程序通过大使调用,该大使服务处理日志请求,路由,断路和其它连接相关功能。
- 卸载代理。将NGINX代理部署在node.js服务实例的前面,处理为服务提供的静态文件内容。