Architecture 什么';基于EJB3的应用程序的最佳通信模式是什么?
我正在启动一个JavaEE项目,它需要具有很强的可伸缩性。到目前为止,这一概念是:Architecture 什么';基于EJB3的应用程序的最佳通信模式是什么?,architecture,jakarta-ee,ejb-3.0,jms,message-driven-bean,Architecture,Jakarta Ee,Ejb 3.0,Jms,Message Driven Bean,我正在启动一个JavaEE项目,它需要具有很强的可伸缩性。到目前为止,这一概念是: 几个消息驱动bean,负责体系结构的不同部分 每个MDB都注入了一个会话Bean,用于处理业务逻辑 两个实体bean,提供对持久层的访问 通过JMS消息通过请求/应答概念在架构的不同部分之间进行通信: MDB接收包含活动请求的消息 使用其会话bean执行必要的业务逻辑 将消息中的响应对象返回给原始请求者 其思想是,通过消息总线将体系结构的各个部分彼此解耦,对可伸缩性没有限制。只需启动更多组件-只要它们连接
- 几个消息驱动bean,负责体系结构的不同部分
- 每个MDB都注入了一个会话Bean,用于处理业务逻辑
- 两个实体bean,提供对持久层的访问
- 通过JMS消息通过请求/应答概念在架构的不同部分之间进行通信:
- MDB接收包含活动请求的消息
- 使用其会话bean执行必要的业务逻辑
- 将消息中的响应对象返回给原始请求者
- MDB 1“TestController”将(本地)SLSB 1“TestService”用于业务逻辑
- onMessage()使TestService向队列XYZ发送消息并请求回复
- TestService使用Bean管理的事务
- TestService在初始化时通过联合连接工厂建立到JMS代理的连接和会话(@PostConstruct)
- TestService在发送后提交事务,然后开始另一个事务并等待10秒以等待响应
- 消息到达MDB 2“LocationController”,它将(本地)SLSB 2“LocationService”用于业务逻辑
- onMessage()使LocationService将消息发送回请求的JMSReplyTo队列
- 相同的BMT概念,相同的@PostConstruct概念
- 所有人都使用相同的连接工厂来访问代理
@Resource(name = "jms/mvs.MVSControllerFactory")
private javax.jms.ConnectionFactory connectionFactory;
@PostConstruct
public void initialize() {
try {
jmsConnection = connectionFactory.createConnection();
session = jmsConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
System.out.println("Connection to JMS Provider established");
} catch (Exception e) { }
}
public Serializable sendMessageWithResponse(Destination reqDest, Destination respDest, Serializable request) {
Serializable response = null;
try {
utx.begin();
Random rand = new Random();
String correlationId = rand.nextLong() + "-" + (new Date()).getTime();
// prepare the sending message object
ObjectMessage reqMsg = session.createObjectMessage();
reqMsg.setObject(request);
reqMsg.setJMSReplyTo(respDest);
reqMsg.setJMSCorrelationID(correlationId);
// prepare the publishers and subscribers
MessageProducer producer = session.createProducer(reqDest);
// send the message
producer.send(reqMsg);
System.out.println("Request Message has been sent!");
utx.commit();
// need to start second transaction, otherwise the first msg never gets sent
utx.begin();
MessageConsumer consumer = session.createConsumer(respDest, "JMSCorrelationID = '" + correlationId + "'");
jmsConnection.start();
ObjectMessage respMsg = (ObjectMessage) consumer.receive(10000L);
utx.commit();
if (respMsg != null) {
response = respMsg.getObject();
System.out.println("Response Message has been received!");
} else {
// timeout waiting for response
System.out.println("Timeout waiting for response!");
}
} catch (Exception e) { }
return response;
}
SLSB 2-LocationService.Java(只有reply方法,其余与上面相同)
sun-resources.xml
<admin-object-resource enabled="true" jndi-name="jms/mvs.LocationControllerRequest" res-type="javax.jms.Queue" res-adapter="jmsra">
<property name="Name" value="mvs.LocationControllerRequestQueue"/>
</admin-object-resource>
<admin-object-resource enabled="true" jndi-name="jms/mvs.LocationControllerResponse" res-type="javax.jms.Queue" res-adapter="jmsra">
<property name="Name" value="mvs.LocationControllerResponseQueue"/>
</admin-object-resource>
<connector-connection-pool name="jms/mvs.MVSControllerFactoryPool" connection-definition-name="javax.jms.QueueConnectionFactory" resource-adapter-name="jmsra"/>
<connector-resource enabled="true" jndi-name="jms/mvs.MVSControllerFactory" pool-name="jms/mvs.MVSControllerFactoryPool" />
请求/应答模式,即使使用JMS,本质上仍然是同步的。调用者发送一条消息,然后等待回复。这不仅因为分布式事务而变得复杂,还意味着在等待回复时,一个或多个资源(至少在本例中是线程)被分配和浪费。您不能这样扩展:您天生就受到线程数量的限制 要拥有真正可伸缩的JMS体系结构,所有内容都必须是异步的。换句话说,你永远不应该等待。发送和接收的消息应传递必要的信息以触发下一个活动 如果消息的大小太大,则只能存储标识符并将相应的数据存储在数据库中。但是,数据库再次成为一个争论点 如果不同的消息需要知道它们参与了哪个长期运行的进程,您也可以使用相关标识符。当收到消息时,接收方可以使用相关标识符“恢复”长时间运行的活动。这是BPEL的传统模式。同步请求/应答和具有相关标识符的异步消息之间的主要区别在于,可以在每个步骤之间释放资源。可以使用后一个进行缩放,但不能使用第一个 老实说,我对你的长篇大论感到困惑,不明白你的设计是不是相当异步(正确),还是与请求/回复同步(有问题)。但我希望我能提供一些答案
无论如何,去访问这个网站,它是一个有价值的信息来源 您使用的是哪种企业服务总线(ESB)?玻璃鱼?您如何在ESB中配置东西?请不要对您自己的问题发表评论。请用其他事实更新您的问题。然后删除你的评论。请详细描述您的glassfish配置,因为这听起来像是您的瓶颈。@Hank:“问题:第一条消息被发送(由SLSB 1)和接收(由MDB 2)ok。返回消息的发送(由SLSB 2)也可以。但是,SLSB 1从未收到任何消息-它只是超时。”所以这才是真正的问题?也许你应该修改标题,删除初步内容,只关注这个问题,让大家都清楚你的问题是什么。“@Steven:我的问题仍然是标题-大型可扩展JEE应用程序的最佳通信模式是什么。我很高兴删除代码部分(并将其移动到另一个线程),但您询问了详细信息…:)我很高兴听到您的建议。谢谢,明白了。如果是这样,我会让MDB收到响应消息(并确定请求是什么,然后从那里继续),对吗?不是在收到响应之前被阻止的会话bean。。。
<admin-object-resource enabled="true" jndi-name="jms/mvs.LocationControllerRequest" res-type="javax.jms.Queue" res-adapter="jmsra">
<property name="Name" value="mvs.LocationControllerRequestQueue"/>
</admin-object-resource>
<admin-object-resource enabled="true" jndi-name="jms/mvs.LocationControllerResponse" res-type="javax.jms.Queue" res-adapter="jmsra">
<property name="Name" value="mvs.LocationControllerResponseQueue"/>
</admin-object-resource>
<connector-connection-pool name="jms/mvs.MVSControllerFactoryPool" connection-definition-name="javax.jms.QueueConnectionFactory" resource-adapter-name="jmsra"/>
<connector-resource enabled="true" jndi-name="jms/mvs.MVSControllerFactory" pool-name="jms/mvs.MVSControllerFactoryPool" />