从 Java 应用部署方式看 IT 思潮——从开发和运维到开发自运维

前些日子,我还在西溪园区上班的时候,若是不是忙得不可开交,我都会在午餐的时候尽量选择一个离所在办公楼远一些的食堂吃饭。由于午饭和晚餐是一天的工做中可贵的两个「放风」时间,若是碰到了有趣的话题还能在路上和同事交流一二。java

有一次,同事问了我一个问题:「为何 Spring Boot 应用倾向于打 fat jar 直接启动,而集团的应用倾向于打 war 包从应用容器启动?」当时我从 IT 主流思潮的角度给了一个解释,大意为 Spring Boot 是 DevOps 时代的产物,集团大多数应用是 Dev 和 Ops 分离时代的产物。web

这种说法抽象程度略高,虽然也能作为一种解释,可是没能很好地把事情表达完整。因而我把当时的解释整理完善后,写下了如今这篇博文。算法

Java 应用部署于应用容器中,实际上是受到 J2EE 的影响,也算是 Java Web 有别于其余 Web 快速开发语言的一大特点。一般咱们在交付 Java Web 应用的时候,交付件是一个后缀为 war 的内部目录结构符合必定规则的 zip 压缩包,这个压缩包里(几乎)完整打包了 Web 页面(模板)、Web 站点描述、Java Web 的各个模块的 jar 以及依赖的第三方 jar。运维将这个 war 文件部署到应用容器中,站点就能被访问了。shell

在虚拟机在数据中内心开始流行之前,Java 应用是直接部署在物理机上的。可是单一的 Java Web 又很难将一个物理主机的所有资源有效利用,为了节省成本,咱们一般会将多个 Java Web 同时部署在一台物理机上,确切的说,是将多个 war 文件部署在一个应用容器里。数据库

在一个应用容器中部署多个 war 文件,就能实如今一个 Java 虚拟机进程中为多个站点提供服务,这能有效地节省内存资源,特别是在那个内存比较金贵的年代,这种特性意义重大,甚至应用容器还能动态地部署和卸载 war 文件而无需重启 Java 虚拟机。编程

刚才咱们说 war 文件是一个 zip 压缩包,其实咱们更常见的作法不是部署这个压缩包,而是部署 war 文件解压以后的目录。那是一个运维和开发分离的年代,开发交付 war,运维部署 war(解压以后的目录)。随着公司业务飞速发展,Java Web 承载了巨大的流量,应用容器开始暴露一些寻常难以发现的问题,甚至有时候这些问题会致使线上故障。因而渐渐的,开始有团队专门去维护开源的应用容器,修复漏洞,提高性能。设计模式

因为研发团队交付的是 war 文件,当应用容器须要更新的时候,运维团队可以在研发团队不须要介入的状况下完成 Java Web 的从新部署。甚至当一些经常使用的底层框架出现了安全漏洞的时候,运维团队也能扫描所有机器所有 war 解压出来的目录中的 jar,将有问题的依赖替换以后重启应用完成修复。缓存

随着硬件性能逐步提高,也随着虚拟机技术被数据中心普遍使用,以前一个物理机上混合部署的十几个 Java Web,摇身一变成了一个物理机上虚拟出来的十几个虚拟机,每一个虚拟机里部署一个应用容器和一个 Java Web。安全

虚拟机技术的普遍使用,给应用运维带来了极大的便利,不再用担忧机器环境被破坏,不再用担忧应用之间依赖冲突,只须要几行命令几个脚本,一个配置完善的开箱即用的 Linux Server 就唾手可得。不再用纠结哪些应用能够混合部署哪些应用须要独立部署,流量低峰期就超卖来压缩成本,流量高峰到来以前再将虚拟机飘到空闲主机上避免资源争抢。服务器

后来开发杀入运维领域,诞生了一种新的工种,DevOps。当开发和运维都是一个团队甚至一我的的时候,将应用和应用容器分开来部署,就显得十分繁琐了。由于不管是升级容器仍是升级应用,对于 DevOps 来讲,都是一次没什么明显差异的升级任务,最好能用一套统一的部署流程去完成。也许 embedded servlet containers 就是在这种需求背景下诞生的,应用容器再也不是独立于应用以外的容器,而是做为应用的一部分,伴随应用一块儿部署和升级。

Spring Boot 就诞生在 DevOps 盛行的这几年。借助 embedded servlet containers,使用 Spring Boot 开发的应用将一个 Jetty 或者 Tomcat 嵌入在它的交付件中,整个 Java Web 应用连同应用容器打包成一个 fat jar,只须要一行 java -jar webapp.jar 就能完成应用的启动,咱们甚至都感知不到应用容器的存在,仿佛只是在运行一个普通的 Java Application。因而升级容器的工做,就和升级一个第三方类库同样,修改 pom 文件,打包,发布,垂手可得。

再后来,伴随着以 Docker 为首的一众容器技术的兴起,咱们正在渐渐进入 Immutable Infrastructure 的时代。

不可变基础设施,是 Chad Fowler 于 2013 年提出的一个颇有前瞻性的构想:在这种模式中,任何基础设施的实例(包括服务器、容器等各类软硬件)一旦建立以后便成为一种只读状态,不可对其进行任何更改。若是须要修改或升级某些实例,惟一的方式就是建立一批新的实例以替换。

在容器时代到来以前,虽然咱们已经在 Spring Boot 之类的框架的引导下,将 Java 应用打成了一个 fat jar 来分发和部署,但实际上咱们分发到生产环境中的内容,远不止这个 fat jar。为了让应用代码可以在不一样环境中部署,咱们会将各个环境不一致的内容抽取出来,保存在配置文件中供 Java Web 应用启动时读取,好比数据库链接串、密码,好比 ZooKeeper 集群的 IP 列表。为了可以动态调节日志等级和格式,咱们还会单独为 logback 等日志器提供配置文件,还要监听这个日志配置的变化。

这些 fat jar 以外的配置,给应用的部署、扩容带来了外的负担。容器想要为咱们处理这一切。若是咱们将配置文件打包进容器镜像中,咱们就能获得一个随时能够部署的镜像,应用的部署和扩容变得简单起来。可是包含配置的镜像彻底没有对环境变化的适应能力,在集群 A 上跑的好好的镜像,也许就无法部署在集群 B 里头。因而咱们开始使用环境变量去描述各个环境不一致的内容,在启动 Java Web 以前先用环境变量渲染出一份适合当前环境的配置。因而,咱们又得使用一个配置管理数据库来管理这许多环境中的许多环境变量,用一个中心化的 CMDB 去取代以前散落在各个集群的应用配置。

Java Web 应用部署的方式,从最初的应用容器 + 物理机 + 多应用混合部署,到应用容器 + 虚拟机 + 独立部署,再到 fat jar + 虚拟机,最后是现在的 fat jar + Linux 容器,伴随着业界运维自动化智能化的浪潮一路走来,也让咱们看到了工程师从「术业有专攻」向 DevOps 乃至全栈工程师转变的趋势。经过提供随时随地轻松获取的 API 化的计算资源,云计算正在加速这一转变,云计算也让正处在转变过程当中的工程师的工做愈来愈轻松有趣。

创业去作云计算并无比以前任何一个时代轻松,真正变得容易的是基于云计算的创业

很幸运身处这样一个时代,可以参与到云的建设之中,为了没法计算的价值。据可靠消息,阿里云 ApsaraDB 管控团队近期正在招聘,加入团队就有机会在云计算环境下管理和自动化运维海量服务器,了解多机房容灾的原理,深度了解 MySQL、SQL Server、PostgreSQL、Redis 和 MongoDB 等各类数据库的原理和实战应用。咱们但愿你和咱们同样,具有以下能力:

  1. 掌握扎实的 Java/Python 基础,熟悉集合类,I/O 及多线程/协程编程,理解各类容器类的内部实现
  2. 三年以上 Java 进行 Web,API 或中间件的全流程开发经验,熟悉 Spring,iBatis,缓存,链接池等常见基础框架的使用、原理和实现
  3. 熟悉经常使用设计模式,熟悉基本 JVM 原理、参数及问题排查,掌握 JVM 性能调优的常见方法及故障排查方法
  4. 熟练掌握 SQL 和 MySQL,对 SQL 优化有必定经验,掌握事务的基本原理及实现
  5. 熟练掌握 Linux 下经常使用的 shell 命令,掌握 Linux 基础性能指标及线上问题排查与解决方法
  6. 对分布式系统及分布式存储理论,如 CAP,一致性哈希,MVCC 等原理及算法有必定了解
  7. 熟悉平常开发流程,熟悉经常使用开发、调试工具、代码管理工具,如 Git、Maven、Eclipse 等
  8. 思路清晰,良好的沟通能力与技术学习能力
  9. 有线上大规模分布式系统开发、部署或运维经验者优先
  10. 有 Python、Perl 等其它脚本语言开发经验者优先

若是你愿意和咱们一块儿打造最优秀的云数据库平台,请不要吝啬你的简历,发送邮件至 xile@alibaba-inc.com 尽情勾搭吧!

相关文章
相关标签/搜索