BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

你的应用什么时候该拆分到多个容器中?

| 作者 金灵杰 关注 5 他的粉丝 发布于 2016年3月22日. 估计阅读时间: 5 分钟 | GMTC大前端的下一站,PWA、Web框架、Node等最新最热的大前端话题邀你一起共同探讨。

Docker的最佳实践提出了“一个容器内只运行一个进程”之后,是否需要将应用拆分到多个容器中就成了一个热门话题。本文以一个普通的Java应用作为讨论,从软件设计的角度来介绍为什么要将其拆分到多个容器中。

假设一个标准的Java Web应用包含以下两部分:

  1. 基于Struts框架的前端应用;
  2. 基于Java EE的后端REST API服务;

这两部分通常运行在同一个容器(如Tomcat)中,相互之间基于REST接口进行交互。类似这种应用,我们应该将其拆分到不同的容器中运行吗?

简单的回答:我们应该将其拆分到不同的容器中,但这需要经过谨慎的考虑。

抛开一些“普适”的原则(如“一个容器只运行一个进程”),我们主要从应用本身和部署策略上进行考虑。

首先,我们抛开具体业务场景,做一些设计思考(Design Thinking):

  1. JVM本身支持多线程,因此通常的Java应用程序都运行在一个进程中,以多线程的方式进行并行处理。类似Tomcat这样的容器本身也支持将多个Java应用程序运行在一个Java进程中。
  2. 事实上,很多已经容器化的应用,在容器中实际运行时也是多进程的,例如Apache的prefork模块。同时,当前流行的网络应用(如Nginx)大量使用事件驱动和反应器模式,这些设计的方向,都是将IO操作交给内核,将业务逻辑处理交给子进程(线程)。Linux内核非常善于调度子进程,但是这不是诸如Kubernetes、Swarm等容器调度工具擅长的地方。进程(线程)侧重于内核资源的划分,而容器侧重于集群资源的划分。
  3. “一个容器只运行一个进程”的原则,更像一种哲学。作为工程师,我们应该从实际出发考虑技术架构和应用逻辑。同时这个“最佳实践”甚至没有获得广泛的赞同,它的传播可能是因为对Unix运作原理缺乏了解导致的。
  4. Linux容器(LXC)历史上有很多种形式,其中很多是建议在一个容器中运行多个进程的。Linux容器实质上是clone系统调用、SELinux、cgroup等技术的组合,上层使用LXC或者Docker(libcontainer)对于这些底层技术是不相关的,因为最终都依赖于内核的隔离技术。
  5. 进程间交互有多种形式,如套接字、文件、网络等,每种方式都有自己的优缺点。如果考虑将应用拆分到不同容器中,对应用程序内部组件之间的通信方式会有很大影响。
  6. 代码、配置和数据的独立性,也对是否能够拆分到不同容器的重要考量。如果应用程序的代码、配置和数据相互独立性比较强,就能够方便的将其拆分成独立的组件,放置到独立的容器中;反之,如果应用内部分层不清,拆分成本会非常高。值得注意的是,我们没有必要为了容器化而对应用做过多的改造,只要能够按照Docker镜像的格式制作成镜像,我们仍然能够享受到Docker带来的便利:方便的分发(利用Docker注册中心)和运行(使用docker run命令)。

上面总结了一些从系统层面看是否需要拆分到多个容器,回到我们的例子:

  1. 这两个Java组件功能上相互独立。一个是web前端,一个是API服务。由于它们是完全不同的服务,是否运行在一个JVM(Java进程)中对性能损耗非常小(当然,这只是相对的,因为它们将无法公用堆内存和垃圾回收)。
  2. 这两个组件之间使用REST API进行交互,没有使用传统的进程间交互方式(套接字、共享内存等)。
  3. web前端和API服务的使用场景不同,针对不同的场景,在运维层面可能需要独立的进行扩容。例如除了web前端之外,API服务还能提供给其他组件使用,因此API服务可能会因为接入方的变化需要独立扩容和缩容。这时候就是充分利用容器编排框架(如Kubernetes、Mesos、Swarm等)能力的时候了。

基于上述三点考虑,我会将这个Java应用的两个组件拆分到独立的容器中。同时建议配合使用诸如Kubernetes的容器编排框架,将两个服务关联到一起。

总结一下我们的“最佳实践”:

如果你的应用代码、配置和数据相对独立,并且有清晰的交互形式,将应用组件拆分到多个容器中是有意义的。


感谢郭蕾对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ@丁晓昀),微信(微信号:InfoQChina)关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入InfoQ读者交流群InfoQ好读者(已满),InfoQ读者交流群(#2)InfoQ好读者)。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

看完感觉貌似什么都没说。。 by 孙 庚泽

也许是我看不懂,感觉作者也没说什么嘛。。

Re: 看完感觉貌似什么都没说。。 by 强 黄

确实没说什么

Re: 看完感觉貌似什么都没说。。 by Bruce Lee

同感

太没有营养了。这种也会放出来; by zhu chao

太没有营养了。这种也会放出来;

主要表达Docker拆分应用的一点建议 by feng wang

主要想表达Docker容器拆分应用服务原则不要以偏概全,应该结合应用系统实际情况去做
1、如果应用系统中应用足够的组件化、服务化,根据容器拆分应用独立部署是值得的。
2、如果应用系统中应用还没有足够的组件化、服务化,引入容器也不一定非要坚持“单进程单容器”原则去实施拆分应用服务方案,那样对应用改造代价大,可以先上容器解决开发、测试、发布环境一体的问题

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

5 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT