阅读更多
【编者的话】随着Docker的发展,越来越多的应用开发者开始使用Docker。James Strachan写了一篇有关Java开发者如何使用Docker进行轻量级快速开发的文章。他告诉我们,使用Docker和服务发现的机制,可以有效减轻Java运维人员的负担,进行项目的快速启动和持续迭代。

多年来,Java生态系统一直在使用应用服务器。Java应用服务器(如Servlet Engine、JEE或OSGi)是一个可以作为最小部署单元(如jar/war/ear/bundle等)进行部署和卸载Java代码的JVM(Java虚拟机)进程。所以一个JVM进程可以在运行的过程中更换运行在其上的代码。通常Java应用服务器提供存放文件的目录或者REST/JMX 接口來修改正在运行的部署单元(Java代码)。

由于内存资源在过去是相当宝贵的,所以把所有的Java代码放到同一个JVM中去运行来减少多个进程带来的内存碎片具有重要的意义。

多年来,在Java生产环境中,通常没有人真正在运行着的JVM中卸载Java代码,因为这样做很容易造成内存泄漏(线程、内存、数据库链接、socket、正在运行的代码等导致)。所以在生产环境中升级应用的较好做法是并行地在一个新的应用服务器中启动应用程序;把流量从旧的应用实例迁移到新的应用实例上,当旧的应用实例结束正在处理的请求时,就可以被停止。

从概念上说是卸载了旧的程序,部署了新的程序;但是实际上是启动了一个新的进程,并把流量迁移到新的进程上,然后结束那个旧进程。

目前,有向微服务发展的趋势,每个进程做好一件事。多年来,使用应用服务器的最佳实践方式,一直都是在每一个JVM中部署尽量少的部署单元。假如你把所有的服务(部署单元)部署到同一个JVM中;如果要升级这些服务中的一个,你就要关闭这个JVM进程,这就会影响到其它的服务。所以把每个应用单独部署在不同的JVM进程中更安全和敏捷,这样在任何时候升级一个服务都不会影响到其他的服务。

多个独立的进程比一个庞大的进程更容易监控,也更容易了解哪个服务使用了多少内存、网络、硬盘和CPU等。
Docker如何带来改变

Docker容器提供了一种理想的方式来打包应用,使得应用在Linux机器上部署更加方便;对不同的操作环境和不同的程序都可以使用同一个Docker镜像而不需要改变;容器之间彼此隔离,并且通过cgroups对IO、内存、CPU等的用量进行限制。所有在Linux上可以使用的技术(Java、python、ruby、nodejs、golang等)都可以在Docker容器中很好的运行。

Docker容器最大的优点之一就是你可以以重复的方式在任何机器上同时启动多个实例,因为这些实例都是基于同一个不变的、可重复使用的镜像。每个容器实例都可以把自己的持久状态挂在在卷上,但是它们的代码(甚至配置)都来自同一个不变的镜像。

所以在Docker上使用Java应用服务器的方式是为应用服务器和你想在生产环境中运行的部署单元创建一个镜像。

在升级服务的时候不再需要在webapps/deploy目录下删除掉一个WAR包或者调用 REST/JMX接口,或者任何其它方式,你只需要创建一个包含新的部署单元的镜像,并且运行这个镜像。

此外,Java应用服务器不再需要在运行时部署和卸载新的代码;不再需要监控部署目录的变化或者监听来自REST/JMX接口的更改部署的请求;只需要在启动的时候启动镜像中的代码。

所以在Docker的世界中,Java应用服务器的理念(可以部署和卸载程序的动态JVM)正在逐渐消亡。

在Docker中使用应用服务的最好方式是把它们当作不可变的镜像;运行在进程中的Java代码就不再需要经常变动。新版本容器的滚动升级就可以在应用服务器之外完成(例如,通过kubernetes滚动升级,然后在容器前使用负载均衡)。
配置管理

自采用应用服务器以后,在Java生态环境中,应用被创建成一个不可变的二进制部署单元(jars、wars、ears、bundles等),发布一次就可以在不同的环境中使用。为了做到在不同的环境中运行,我们通常通过应用服务来查找资源(例如,在JEE环境下使用JNDI查找)比如查找数据库的位置或者消息代理。所以就会有单独的配置好的应用服务器集群来部署你的程序(假设应用服务器都配置正确)。

尽管在不同的操作系统,Java版本,应用服务器版本或者不匹配的配置等不同环境下容易混乱,在初步阶段程序可能还正常运行,但是如果不够仔细的话,生产环境下可能会运行出错。

而采用Docker的方法,就是把镜像不变的理念延伸到操作系统和应用服务器上;所以根据操作系统、java环境,应用服务器和部署单元制定的同一个二进制镜像可以在每一个特定环境下运行。所以在一个特定环境下不存在应用服务器配置错误的问题,因为同一个二进制镜像可以在所有环境下运行。

为了做到这一点,在每一个环境下都有服务发现就显得极其有用,这使得同一个镜像在每个环境下都使用正确的配置并且准确无误地运行变得简单。例如,像kubernetes服务发现让在所有环境使用同一个二进制镜像并且使用服务发现连接数据库、消息中间件变得可行。
总结

所以,这就意味着Java应用服务器没用了吗?在Docker的世界里,确实再也没有必要在生产环境中运行着的Java进程中热部署Java代码了。但是在开发过程中,有能力在运行的实例中热部署一份代码依旧非常有用。(尽管公平的说,你可以使用像JRebel这样的工具在Java应用做到同样的事情,大多数使用IDE调试的用户就用这种方法)

所以我想说,Java应用服务器渐渐变得更像烧录到固定镜像中的一个框架,然后在外部云中进行管理(比如通过Kubernetes)。云(如Kubernetes和Docker)在许多方面接管了很多Java应用服务器原先做的功能,并且新镜像的滚动升级对所有技术来说都是需要的(包括java/golang/nodejs/python/ruby等等)。

尽管Java用户仍然想要Java应用服务器提供的一些服务,如servlet引擎、依赖代码注入、事务处理、消息处理等等。但是你再也无需动态的在一个运行着的Java虚拟机中清理原先部署上去的代码了,这样你就可以轻易的在Java应用中植入一个servlet引擎。像Spring Boot这样的方法向你展示了如何只通过依赖代码注入和一个扁平化的类载入器,就足以胜任大多数应用服务器的功能。

作为一个开发者,在用Java应用服务器工作时遇到最大问题之一就在于载入Java类时的复杂性,我相信在这一点上我们都讨厌Java的类载入器问题。

尽管你可以通过使用BOM文件在项目中导入一个maven构建的依赖关系来修复这些问题,但是为JEE服务开发者们屏蔽jar包的具体实现依然有一定的价值,你无需再搞清复杂的类载入器的树关系或者图关系。就算类路径关系简单,你还有可能面临版本冲突问题。所以如果有办法隔离类载入器会非常有用。不过有时候使用一个jar包的不同版本也意味着编码上可能有些问题,是不是意外着是时候把代码重构一下,变成两个独立的服务,这样就可以有一个简洁漂亮扁平的类载入器?

如果一个Java应用服务器进程现在只启动了一个静态已知的Java代码集合,应用服务器的想法会变成一个帮助你进行代码注入以及包含你所需模块服务的方法,这就听起来更像是一个框架而非我们原本意外的一个Java 应用服务器。

许多Java开发者学会了如何使用应用服务器,并且在Docker的世界中仍会继续使用,这一点很好。但是与此同时我也看到,他们对此的使用真在消减,因为许多应用服务器本来在过去帮我们完成的事情,现在Docker、Kubernetes及相关框架可以用一种更简单、更高效的方式帮我们完成。

Docker和云给我们带来的一个巨大的好处就是,开发者可以选择他们想要使用的技术,他们可以为合适的工作选择适当的工具,并且可以把他们的技术用同样的方法进行管理和提高给用户,无论使用的是何种语言何种框架。你可以在最初使用你知道的技术,随着时代的变化迁移到更轻量级的替代中。

fabric8项目中,我们确实不知道你想要使用何种应用服务器或者框架,所以Camel Boot、CDI 、Spring Boot 、 Karaf 、Tomcat 、 Vertx、Wildfly这些我们在quickstarts中都支持。感谢Kubernetes,我们可以提高同样的供应、管理以及工具化经验,无论你选择的应用服务器或框架到底是什么。举个例子,如果你使用fabric8 V2开始一个新的Camel项目,我们强烈建议你使用Camel Boot工具或者尝试使用Spring Boot Quickstarts。

我越来越多的看见Java用户选择像Camel Boot、CDI、Dropwizard、Vertx或者Spring Boot 这些更轻量级的框架,并且随着时间越来越少使用Java应用服务器。尽管我们依然需要使用依赖注入和框架。

原文链接:the decline of Java application servers when using docker containers
来自: dockerone
6
4
评论 共 5 条 请登录后发表评论
5 楼 shinestmt 2015-04-10 13:54
Spring Boot 把tomcat或jetty嵌入包中,直接java -jar运行
4 楼 Foxswily 2015-03-30 09:27
docker的运行方式和tomcat不是很搭,jetty更适合点,毕竟还在发展中,关注吧
3 楼 lz958942 2015-03-30 08:43
部署一个试试,感觉有点炒概念的嫌疑
2 楼 junfengcode 2015-03-29 17:51
可以作为servlet容器?
1 楼 josico 2015-03-29 13:48
就是说 用这个 可以不用tomcat?

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • 使用Docker-Compose部署MySQL一主二从同步高可用MHA集群

    使用Docker-Compose部署MySQL一主二从同步高可用MHA集群,图文视频结合。

  • 减少使用Java应用服务器,迎接Docker容器(还没怎么看懂)

    随着Docker的发展,越来越多的应用开发者开始使用Docker。James Strachan写了一篇有关Java开发者如何使用Docker...多年来,Java生态系统一直在使用应用服务器。Java应用服务器(如Servlet Engine、JEE或OSGi)是一个可

  • Docker容器

    Reference 1. DaoCloud 2. Hub Docker 3. Docker

  • java启动mysq服务_启动java服务器

    Servlet是位于Web 服务器内部的服务器端的Java应用程序,与传统的从命令行启动的Java应用程序不同,Servlet由Web服务器进行加载,该Web服务器必须...文章哈沙给2013-02-28562浏览量Derby开发选项Derby软件分发包...

  • Azure云新趋势:无服务器、容器化

    企业用户越来越多地寻求新的服务来简化和增强他们的云使用体验,而作为众多基础设施即服务供应商中一员的Azure已经加紧了迎接这一挑战的脚步。 从降低人工任务的云新技术到诸如无服务器计算、人工智能以及容器等...

  • 在WIN7中用maven将spring boot项目远程部署到Linux虚拟机的docker容器

    2、docker容器在Linux虚拟机中 3、在WIN7里将直接将spring boot项目发布到该远程docker 4、发布工具是maven 据说docker最好部署在Linux。部署在windows也可以的,但要求操作系统是WIN10或以上。我机器老旧,只有WIN...

  • Spring Boot 4.0:构建云原生Java应用的前沿工具

    它采用"约定优于配置"的原则,通过自动化配置和快速开发功能,减少了开发者的工作量,使得构建高质量的Java应用程序变得更加容易。快速启动:Spring Boot提供了一个快速启动的方式,只需少量的配置即可启动一个Web...

  • 1期:理解Docker容器的进程管理(原云栖速递)

    云栖头条 理解Docker容器的进程管理 ...Docker在进程管理上有一些特殊之处,如果不...同时,在Docker容器中运行多进程应用也将给开发者带来更多挑战。本文着重分析Docker中进程管理的一些细节,并介绍一些...

  • Docker入门(程序员和运维必备)

    首先来简单说下什么是DockerDocker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互...

  • 极智开发 | 华为昇腾 docker 内配置 MindStudio

    本教程详细记录了在华为昇腾服务器上,桌面化docker内配置 MindStudio 的方法,让你可以实现一机多用户同时使用 MindStudio 愉快的进行开发。

  • 首批学习Java的人,如今怎么样了?

    互联网大厂每一次的动作都会带来一股网络热浪,前不久的“反996”如此,最近腾讯推出员工退休待遇方案,亦是如此。...比如在10多年前便不被看好的Java开发工程师,如今依旧是各大互联网厂的香饽饽岗位!虽然在很多程序

  • 使用 AWS、k3s、Rancher、Vault 和 ArgoCD 在 Kubernetes 上集成 GitOps

    随着 Kubernetes 将自己打造为容器编排的工业标准以来,为你的应用和工具寻找一条能够高效使用声明式模型的途径是成功的关键因素。这篇文章中,我将带领大家在 AWS 上设置一个 k3s Kubernetes 集群,然后集成 Argo...

  • 容器十年:一部软件交付编年史

    2019 年,全世界的开发人员都开始习惯用容器来测试自己的软件,用容器做线上发布,开始对容器化的软件构建和交付流程习以为常。在“云”已经成为了大众基础设施的今天,我们已经习惯了把“容器“当做现代软件基础...

  • 云原生实践1-Asp.NET(!Asp.NET Core) 容器化实践

    目前基于云原生理念构建应用已是主流,然而有些同仁手上可能还有在维护的项目或者产品使用的是基于 .NET Framework 的 Asp.NET 而非 .NET Core。 那么为了迎接云原生是否需要全部把现有程序重写为Java或者Golang呢,...

  • 干掉 Jenkins?顶级 DevOps 工具链大盘点

    你使用谷歌提供的云计算服务来迎接业务方面的挑战,包括数据管理、混合和多云、人工智能和机器学习。 Pivotal Cloud Foundry Pivotal Cloud Foundry (PCF) 是一个开源的多云应用平台即服务 (PaaS),由 501 组织 ...

  • 阿里秋招面试真题解析:java递归求阶乘原理

    再过一周,马上将迎来新的一年,希望大家在2021年“牛气冲天,牛年大吉”,一起迎接春暖花开之时。 金三银四马上就到了,很多粉丝朋友私信希望我出一篇面试专题或者分享面试相关的笔记来学习,小编还是相当宠粉的,...

  • Java整理总结

    通知器:连接切点和通知结合起来,可以让我们知道那个通知应用于哪个结点之上,这个结合为应用使用Ioc容器配置AoP应用 开始我们使用AOP的时候是用得java编写的切面通知使用XML配置,后面我们摒弃了采用@AspectJ...

  • tornado-6.4.1-cp38-abi3-musllinux_1_2_i686.whl

    tornado-6.4.1-cp38-abi3-musllinux_1_2_i686.whl

  • tornado-6.1-cp36-cp36m-manylinux2014_aarch64.whl

    tornado-6.1-cp36-cp36m-manylinux2014_aarch64.whl

Global site tag (gtag.js) - Google Analytics