java Spring MVC with JBoss vs Tomcat - 优势/实践

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15277356/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 19:04:06  来源:igfitidea点击:

Spring MVC with JBoss vs Tomcat - Advantages / Practice

javaspringjbossapplication-serverweb-container

提问by Kevin Rave

Okay. This is again a question of industry practice.

好的。这又是一个行业惯例的问题。

  • Tomcat = Web Container
  • JBoss, WebLogic, etc = Application Servers that have Web Container within (for JBoss, its forked Tomcat)
  • Tomcat = Web 容器
  • JBoss、WebLogic 等 = 内部具有 Web 容器的应用服务器(对于 JBoss,其分叉的 Tomcat)

Spring does not need Application Server like JBoss. If we use enterprise services like JMS, etc we can use independent systems like RabbitMQ, ApacheMQ, etc.

Spring 不需要像 JBoss 那样的应用服务器。如果我们使用 JMS 等企业服务,我们可以使用 RabbitMQ、ApacheMQ 等独立系统。

  1. Question is why do people still use JBoss and other Application Serves for purely spring based applications?
  2. What are the advantages Spring can make use of, by using Application Servers? Like object pooling? What specific advantages does Application Server offers? How are those configured?
  3. If not for spring, for what other purposes Application Servers are used for Spring/Hibernate, etc stack? (Use cases)
  1. 问题是为什么人们仍然将 JBoss 和其他应用程序服务用于纯粹基于 spring 的应用程序?
  2. 通过使用应用服务器,Spring 可以利用哪些优势?像对象池?Application Server 提供哪些具体优势?那些是怎么配置的?
  3. 如果不是用于 spring,应用服务器用于 Spring/Hibernate 等堆栈的其他目的是什么?(用例)

采纳答案by Philippe Marschall

Actually I would say listening for JMS is probably the best reason for an application server. A stand alone message broker does not fix the problem since you still need a component that's listening for messages. The best way to do this is to use a MDB. In theory you can use Springs MessageListenerContainer. However this has several disadvantages like JMS only supports blocking reads and Spring therefore needs to spin up it's own threads which is totally unsupported (even in Tomcat) and can break transactions, security, naming (JNDI) and class loading (which in turn can break remoting). A JCA resource adapter is free to do whatever it wants including spinning up threads via WorkManager. Likely a database is used besides JMS (or another destination) at which point you need XA-transactions and JTA, in other words an application server. Yes you can patch this into servlet container but that this point it becomes indistinguishable from an application server.

实际上我会说监听 JMS 可能是应用服务器的最佳理由。独立的消息代理不能解决问题,因为您仍然需要一个侦听消息的组件。执行此操作的最佳方法是使用 MDB。理论上你可以使用 Springs MessageListenerContainer。然而,这有几个缺点,比如 JMS 只支持阻塞读取,因此 Spring 需要启动它自己的线程,这是完全不受支持的(即使在 Tomcat 中)并且可以破坏事务、安全性、命名(JNDI)和类加载(反过来又可以破坏远程)。JCA 资源适配器可以自由地做任何它想做的事情,包括通过 WorkManager 启动线程。除了 JMS(或其他目标)之外,可能还使用了一个数据库,此时您需要 XA 事务和 JTA,换句话说,一个应用程序服务器。

IMHO the biggest reason against application servers is that it takes years after a spec is published (which in turn takes years as well) until severs implement the spec and have ironed out the worst bugs. Only now, right before EE 7 is about to be published do we have are EE 6 servers starting to appear that are not totally riddled with bugs. It gets comical to the point where some vendors do no longer fix bugs in their EE 6 line because they're already busy with the upcoming EE 7 line.

恕我直言,反对应用服务器的最大原因是规范发布后需要数年时间(反过来也需要数年时间),直到服务器实施该规范并解决最严重的错误。直到现在,就在 EE 7 即将发布之前,我们是否有 EE 6 服务器开始出现,但并没有完全充满错误。可笑的是,一些供应商不再修复他们的 EE 6 系列中的错误,因为他们已经忙于即将推出的 EE 7 系列。

Edit

编辑

Long explanation of the last paragraph:

最后一段的详细解释:

Java EE in a lot of places relies on what's called contextual information. Information that's not explicitly passed as an argument from the server/container to the application but implicitly "there". For example the current user for security checks. The current transaction or connection. The current application for looking up classes to lazily load code or deserialize objects. Or the current component (servlet, EJB, …) for doing JNDI look ups. All this information is in thread locals that the server/container sets before calling a component (servlet, EJB, …). If you create your own threads then the server/container doesn't know about them and all the features relying on this information don't work anymore. You might get away with this by just not using any of those features in threads you spawn.

Java EE 在很多地方都依赖于所谓的上下文信息。没有作为参数从服务器/容器显式传递到应用程序但隐式“在那里”的信息。例如当前用户进行安全检查。当前事务或连接。当前用于查找类以延迟加载代码或反序列化对象的应用程序。或者用于执行 JNDI 查找的当前组件(servlet、EJB 等)。所有这些信息都在服务器/容器在调用组件(servlet、EJB 等)之前设置的线程局部变量中。如果您创建自己的线程,则服务器/容器不知道它们,并且所有依赖此信息的功能都不再起作用。您可以通过在您生成的线程中不使用任何这些功能来摆脱这一点。

Some links

一些链接

http://www.oracle.com/technetwork/java/restrictions-142267.html#threadshttp://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html#spring-4

http://www.oracle.com/technetwork/java/restrictions-142267.html#threads http://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html#spring-4

If we check the Servlet 3.0 specification we find:

如果我们检查 Servlet 3.0 规范,我们会发现:

2.3.3.3 Asynchronous processing

Java Enterprise Edition features such as Section 15.2.2, “Web Application Environment” on page 15-174 and Section 15.3.1, “Propagation of Security Identity in EJBTM Calls” on page 15-176 are available only to threads executing the initial request or when the request is dispatched to the container via the AsyncContext.dispatch method. Java Enterprise Edition features may be available to other threads operating directly on the response object via the AsyncContext.start(Runnable) method.

2.3.3.3 异步处理

Java Enterprise Edition 功能,例如第 15-174 页上的第 15.2.2 节“Web 应用程序环境”和第 15.3.1 节“EJBTM 调用中安全标识的传播”第 15-176 页仅可用于执行初始请求的线程或者当请求通过 AsyncContext.dispatch 方法分派到容器时。通过 AsyncContext.start(Runnable) 方法直接在响应对象上运行的其他线程可以使用 Java Enterprise Edition 功能。

This is about asynchronous processing but the same restrictions apply for custom threads.

这是关于异步处理,但同样的限制适用于自定义线程。

public void start(Runnable r) - This method causes the container to dispatch a thread, possibly from a managed thread pool, to run the specified Runnable. The container may propagate appropriate contextual information to the Runnable.

public void start(Runnable r) - 此方法使容器分派一个线程(可能来自托管线程池)来运行指定的 Runnable。容器可以将适当的上下文信息传播到 Runnable。

Again, asynchronous processing but the same restrictions apply for custom threads.

同样,异步处理但同样的限制也适用于自定义线程。

15.2.2 ?Web Application Environment

This type of servlet container should support this behavior when performed on threads created by the developer, but are not currently required to do so. Such a requirement will be added in the next version of this specification. Developers are cautioned that depending on this capability for application-created threads is not recommended, as it is non-portable.

15.2.2 ?Web 应用环境

这种类型的 servlet 容器在开发人员创建的线程上执行时应该支持这种行为,但目前不需要这样做。这样的要求将在本规范的下一个版本中添加。开发人员需要注意的是,不建议依赖于应用程序创建的线程的此功能,因为它是不可移植的。

Non-portable means it can may in one server but not in an other.

不可移植意味着它可以在一台服务器中但不能在另一台服务器中。

When you want do receive messages with JMS outside of an MDB you can use four methods on javax.jms.MessageConsumer:

当您想在 MDB 之外使用 JMS 接收消息时,您可以使用以下四种方法javax.jms.MessageConsumer

  • #receiveNoWait()you can to this in a container thread, it doesn't block, but it's like peeking. If no message is present it just returns null. This isn't very well suited for listening to messages.
  • #receive(long)you can to this in a container thread, it does block. You generally don't wan't to do blocking waits in a container thread. Again not very well suited for listening to messages.
  • #receive(), this blocks possibly indefinitely. Again not very well suited for listening to messages.
  • #setMessageListener()this is what you want, your get a callback when a message arrives. However unless the library can hook into the application server this won't be a container thread. The hooks into the application server are only available via JCA to resource adapters.
  • #receiveNoWait()您可以在容器线程中查看它,它不会阻塞,但就像偷看一样。如果没有消息存在,它只返回null。这不太适合收听消息。
  • #receive(long)您可以在容器线程中执行此操作,它确实会阻塞。您通常不想在容器线程中进行阻塞等待。再次不太适合收听消息。
  • #receive(),这可能会无限期地阻塞。再次不太适合收听消息。
  • #setMessageListener()这就是你想要的,当消息到达时你会得到一个回调。但是,除非库可以挂接到应用程序服务器,否则这不会是容器线程。应用程序服务器的钩子只能通过 JCA 用于资源适配器。

So yes, it may work, but it's not guaranteed and there are a lot of things that may break.

所以是的,它可能会起作用,但不能保证并且有很多东西可能会损坏。

回答by Adam Gent

You are right that you don't really need a true application server (implementing all Java EE specs) to use Spring. The biggest reason people don't use true Java EE apps like JBoss is that then have been slow as #$@#% on cold start up time making development a pain (hot deploy still doesn't work that well).

您确实不需要真正的应用程序服务器(实现所有 Java EE 规范)来使用 Spring,这是对的。人们不使用像 JBoss 这样真正的 Java EE 应用程序的最大原因是,冷启动时的速度慢到 #$@#%,这让开发变得痛苦(热部署仍然不能很好地工作)。

You see there are two camps:

你看有两个阵营:

  • Java EE
  • Spring Framework.
  • Java EE
  • 弹簧框架。

One of the camps believes in the spec/committee process and the other believes in benevolent dictator / organic OSS process. Both have people with their "agendas".

一个阵营相信规范/委员会流程,另一个阵营相信仁慈的独裁者/有机 OSS 流程。两者都有他们的“议程”。

Your probably not going to get a very good unbiased answer as these two camps are much like the Emacs vs VIM war.

您可能不会得到一个很好的公正答案,因为这两个阵营很像 Emacs 与 VIM 之战

Answer your questions w/ a Spring bias

用弹簧偏差回答你的问题

  1. Because it in theory buys your less vendor lock-in (albeit I have found this to be the opposite).
  2. Spring's biggest advantage is AspectJ AOP. By far.
  3. I guess see Philippe's answer.
  1. 因为理论上它可以减少您的供应商锁定(尽管我发现这是相反的)。
  2. Spring最大的优势是AspectJ AOP。到目前为止。
  3. 我想看到菲利普的回答。

(start of rant)

(吐槽开始)

Since @PhilippeMarschall defended Java EE I will say that I have done the Tomcat+RabbitMQ+Spring route and it works quite well. @PhilippeMarschall discussion is valid if you want proper JTA+JMS but with proper setup with Sprig AMQP and an a good transactional database like Postgresql this is less of an issue. Also he is incorrect about the message queue transactions not being bound/synchronized to the platform transactions as Spring supports this (and IMHO much more elegantly with @Transactional AOP). Also AMQPis just plain superior to JMS.

自从@PhilippeMarschall 为 Java EE 辩护后,我会说我已经完成了 Tomcat+RabbitMQ+Spring 的路线,而且效果很好。如果您想要适当的 JTA+JMS,@PhilippeMarschall 的讨论是有效的,但如果使用 Sprig AMQP 进行适当的设置和像 Postgresql 这样的好的事务数据库,这不是什么问题。此外,他对消息队列事务未绑定/同步到平台事务的看法不正确,因为 Spring 支持这一点(恕我直言,@Transactional AOP 更优雅)。此外,AMQP只是明显优于 JMS。

(end of rant)

(吐槽结束)

回答by JohnNY

We are using JBoss over tomcat for the JNDI data sources and pooling.. It makes it so the programmer don't have to know anything about the database but its JNDI name

我们使用 JBoss 而不是 tomcat 作为 JNDI 数据源和池。这使得程序员不必知道任何关于数据库的信息,但它的 JNDI 名称