带有嵌入式或独立 tomcat 的 Java docker 容器?

Posted

技术标签:

【中文标题】带有嵌入式或独立 tomcat 的 Java docker 容器?【英文标题】:Java docker container with embedded or standalone tomcat? 【发布时间】:2020-03-16 04:53:18 【问题描述】:

目前我有一个 tomcat 网络服务器,它托管多个 .war 微服务(如果重要:spring-boot 应用程序)。升级应用程序时,我通过添加 myapp##005.warmyapp##006.war 等来使用 tomcat parallel deployment 功能,以实现零停机部署。

我想 dockerize 应用程序。但是什么最适合 java 应用 webservice 应用呢?

将war文件直接打包到容器中是否更好,这样每次重新部署都需要一个新的docker容器?或者 tomcat 应该作为没有应用程序的容器运行,并从共享的主机系统文件夹中挂载 war 文件(从而提供重新部署而无需重新部署 dockerimage)?

我能想到以下三种可能性:

将每个war文件作为jar运行,而不是使用嵌入式tomcat,每个作为自己的docker容器?然后每个应用程序被解耦,但我不能再使用并行部署功能,因为我必须在另一个可以取代它之前杀死 jar。如果这是最好的方法,那么问题是:如何使用 docker 容器实现零停机部署? 将每个war文件作为独立的tomcat运行,每个作为自己的docker容器?然后每个应用程序将被解耦,并且还可以使用并行部署。但是我必须在这里为每个 docker 容器中的每个应用程序启动一个显式的 tomcat 网络服务器,这可能会对主机系统性能产生负面影响? 作为docker运行一个独立的tomcat,并将所有*.war文件放在一个共享文件夹中进行部署?在这里,我仍然可以使用并行部署功能。但这不是与 docker 的想法背道而驰吗?战争应用程序不应该打包在容器内吗?性能和资源要求在这里可能是最好的,因为这只需要一个 tomcat。

哪种方法适合 java miroservices?

【问题讨论】:

我认为微服务需要“蓝绿色部署”,它允许以零停机时间重新部署容器。共享一个war文件不是一个好主意,因为你需要跟随docker容器,你所需要的必须是内部镜像,除了docker-compose文件。 虽然这是一个真正“主要基于意见”的问题,但它仍然是一个很好的问题。 【参考方案1】:

为每个 Docker 容器使用一个 Jar 部署绝对是最好的方法。正如您所提到的,低耦合是您希望从微服务中获得的东西。使用 Docker Swarm 和 Kubernetes 等容器编排工具可以轻松完成滚动部署/金丝雀发布等。

如果你想玩转这些概念,Docker Swarm 相当简单:

在您的撰写文件中:

version: '3'

services:
    example:
        build: .
        image: example-image:1.0
        ports:
            - 8080:8080
        networks:
            - mynet
        deploy:
            replicas: 6
            update_config:
                parallelism: 2
                delay: 10s
            restart_policy:
                condition: on-failure

您撰写文件中的部署部分是 Docker Swarm 所需要的。

replicas 告诉您,您的应用程序的 6 个实例将部署在 swarm 中 parallelism 会告诉您将同时更新 2 个实例(而不是 6 个) 更新之间会有 10 秒的宽限期(延迟

Lot's of other things you can do. Take a look at the documentation.

如果您更新服务,则不会出现停机,因为 Docker Swarm 将通过 4 个仍在运行的容器为所有请求提供服务。

我不推荐在生产环境中使用 Docker Swarm,但它是玩转容器编排概念的好方法。

Kubernetes 的学习曲线非常陡峭。如果您在云中,例如 AWS,EKS、Fargate 等服务可以为您消除很多复杂性。

【讨论】:

感谢您的示例和详细说明!对我来说,拥有 1 个正在运行的容器就足够了,并且只需热切换它们而无需停机。 docker swarm 也可以吗?除此之外,您是否知道运行嵌入式 tomcat 而不是专用的独立设备是否有任何缺点? 您需要暂时扩展到至少两个。在新实例启动时,旧版本仍需要启动以服务请求。我的意思是,如果在某个时间点不存在服务的实例,则服务在物理上不可能为请求提供服务。但是您可以使用一个额外的 docker 命令来执行此操作,因此它不需要是您在 docker-compose 文件中定义的永久内容。 至于你的第二个问题,我猜它不太稳定。如果你只是要部署一个容器,我真的看不出容器化的意义。您没有利用容器和容器编排可以为您提供的优势(负载平衡、可用性、自动重启崩溃的应用程序......) 我的全部目标是解耦应用程序。如果使用单个 jar,我需要 docker 来提供零停机时间部署。无论如何,我对单个实例很好。当然,如果将来需要,专业人士能够进行负载平衡和扩大规模。是否可以告诉 docker-swarm 启动第二个实例进行部署,然后只返回 1,杀死旧版本? "docker service scale exampleservice=2",就可以了。用于更新的“docker service update --image newexampleserviceimage”。默认情况下,docker swarm 将一一更新您的服务实例-我认为-如果不是,您可以在 compose-file 或使用 --update-parallelism 标签创建服务时指定它

以上是关于带有嵌入式或独立 tomcat 的 Java docker 容器?的主要内容,如果未能解决你的问题,请参考以下文章

微服务:嵌入式 tomcat 与独立 tomcat:差异

带有球衣的嵌入式 tomcat 上的 java.net.SocketTimeoutException

spring boot 嵌入式Tomcat的崩溃日志在哪里?

在独立 Java 应用程序中设置嵌入式 Derby 数据库

带有嵌入式 Tomcat 的 Jndi Mongodb Spring Boot,[重复]

部署在 Tomcat 上的 Spring Boot Rest API 提供 404 但独立工作一切正常