用于生产的外部容器中的 Spring Boot 嵌入式容器或 war 文件

Posted

技术标签:

【中文标题】用于生产的外部容器中的 Spring Boot 嵌入式容器或 war 文件【英文标题】:Spring boot embedded container or war file in an external container for production 【发布时间】:2017-01-30 06:39:30 【问题描述】:

我完全能够在这两种情况下配置 spring boot,这里的问题是它们中的哪一个更健壮并且更推荐,因为我没有在 spring boot 文档中找到推荐的部署方式在生产环境中,我对使用嵌入式容器的担忧是:

    如果我想将其设置为 Windows 或 Linux 服务,jar 文件是最佳选择吗? 如果我使用 jar 文件,我将无权重新启动服务器。 也许将来我需要在同一个容器中使用更多应用程序。 如果我重新启动机器,我必须再次执行 java -jar。

一般的问题是哪个更好地使用 jar 文件并在生产中将其作为 java -jar jarname.jar 执行,或者将包装更改为 war 设置提供的 tomcat 并将生成的 war 设置为空 tomcat。

希望你能帮助我。

---编辑---

很多时候答案取决于,这适用于普通的 Web 应用程序或 REST Web 服务。

【问题讨论】:

我也有同样的问题,我认为最好让它在 tomcat 服务器上运行。但取决于你的项目使用什么类型的操作。我也认为 tomcat 提供了一些安全性来运行它。 “我认为 tomcat 提供了一些安全性来运行它”是什么意思? 我认为他在谈论例如 jdbc 领域 好点。我们通过将参数--spring.config.location 添加到启动应用程序的脚本中解决了这个问题。参数指定替代配置文件。这种方式我们将包括访问数据在内的 DB-Config 外部化,但它也是在升级应用程序时保留配置的一种方式。 寻找以下问题:Spring boot project publish to production environment choose war(standalone tomcat) or jar(embedded tomcat)? 【参考方案1】:

jar 打包非常适合生产环境,您宁愿仅在确实需要时才回退到 war - 这通常是您无法控制部署环境的情况(在大型企业中经常出现这种情况)。

Spring Boot 参考中有一个章节介绍了将基于 Spring Boot 的应用程序设置为 Unix/Linux/Windows 服务:Installing Spring Boot applications。

关于您的担忧:

也许将来我需要在同一个容器中使用更多应用程序。

使用嵌入式容器,如果您需要在同一台机器上运行更多应用程序,您应该分别启动两个应用程序,每个应用程序运行在不同的端口上,并且实际上您最终会运行两个容器 - 这很好,应用程序更好地与每个应用程序隔离其他。

【讨论】:

jar部署的问题是,如果你有N个应用程序,你就会有N个嵌入式服务器。如果从隔离的角度来看它很好,它将使应用程序服务器消耗的内存乘以 N。如果 N 很大,这可能是一个问题。不是吗?【参考方案2】:

大约一个月前,我遇到了像你这样的问题。 让我分享一下我的结论:

1) 罐子:

您可以使用不同的端口独立运行每个应用程序(在 linux 中,java -jar ... > app_logs.log &),并且可以路由它(例如 nginx)。请注意,重新启动不是问题。您可以编写自定义 bash 脚本(例如:ps aux | grep appname 并按 PID 杀死) 但是在配置生产应用程序时存在一些问题。属性文件将归档到 jar 中。

2) 战争

您可以部署到容器中并运行它。在服务器上轻松管理。如果要重新配置应用程序,请从容器内的未归档文件夹中打开属性文件,根据需要进行更改并重新启动容器。因此,管理和配置将变得很容易。 但是,如果您想在此服务器上使用另一个端口运行另一个应用程序,那么您必须安装另一个容器副本并对其进行配置。

所以,在我的实践中,使用war app比jar更容易管理和重新配置。

【讨论】:

我不同意战争与罐子的结论。将带有嵌入式 Tomcat 的 Spring Boot 作为可执行 jar 文件运行是一种更容易的做法。通过使用配置文件并在启动时指定配置文件,可以轻松解决多个实例运行和对不同端口的需求的问题,例如:--spring.profiles.active=prodconfig1 等。甚至更好,只需传入所需的Tomcat 端口作为 VM 参数:-Dserver.port=9090 产生输出:(TomcatEmbeddedServletContainer) - Tomcat 在端口上启动:9090 (http) 经过这么长时间,我同意你的想法。【参考方案3】:

    我对 Windows 服务了解不多,但在 Linux 上,您可以将 jar 的执行添加到 RC 脚本(从而使应用程序在某个运行级别启动)。对于 Spring Boot 应用程序,您只需对 jar 进行符号链接,就可以像任何其他服务一样启动/停止/等,请参阅:Spring Boot application as a Service

    重启机器还是JVM? spring boot 中内置了关闭机制,您只需激活它(并且您应该启用安全机制,这样任何人都无法做到),请参阅:How to shutdown a Spring Boot Application in a correct way?

    Spring-Boot 支持微服务 - 因此我们的想法是为每个 webapp/微服务拥有一个嵌入式 webapp-container。这样可以降低在只有一项服务出现故障时丢失所有服务的风险。

    是的。并且您必须在每次重新启动后执行catalina.sh|bat start。或者您添加适当的启动脚本(参见 1.)

我感觉你宁愿用老式的方式来做。尽管有“口味问题”的答案,但有一个论据 pro-jar:唯一的依赖是 JVM!其余部分(web-app-container、db-drivers、其他库)都是您交付的软件包的一部分。如果您决定为下一个版本更改容器,那么它也会如此。

【讨论】:

不不不,我真的很喜欢将 spring boot 与 fat jar 一起使用jar 即服务,因为没有太多关于如何在生产中部署 jar 的文档,这是因为在生产中我使用外部容器。 我也不知道,但它比我想象的要简单得多:***.com/questions/21503883/…【参考方案4】:

在生产中使用“war”文件的另一个原因。 Springboot 掩盖了 Jetty 抛出的错误,而部署在 Jetty 中的 WAR 正确捕获了它(尽管下面的问题仍在审查中)

https://github.com/spring-projects/spring-boot/issues/8917#issuecomment-294673487

【讨论】:

【参考方案5】:

我对服务器类的东西不太了解,但我的建议是

如果您使用的是Monolithic应用程序,最好使用war 外部tomcat。

如果您使用的是 微服务 应用程序,请使用嵌入式 具有不同端口的tomcat。而每一个微服务应用都是 相互独立。

【讨论】:

以上是关于用于生产的外部容器中的 Spring Boot 嵌入式容器或 war 文件的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 内嵌容器Undertow参数设置

Spring Boot 内嵌容器Undertow取代tomcat

spring boot 2

spring boot 使用application.properties 进行外部配置

Spring Boot,测试容器以测试发送到外部数据库的查询

Spring BootSpring Boot项目部署到外部Tomcat容器