문제

나는 강력하게 확장 할 수있는 Java EE 프로젝트를 시작하고 있습니다. 지금까지 개념은 다음과 같습니다.

  • 건축의 여러 부분을 담당하는 여러 메시지 구동 콩
  • 각 MDB에는 세션 Bean이 주입되어 비즈니스 로직을 처리합니다.
  • 지속성 층에 대한 액세스를 제공하는 몇 개의 엔티티 콩
  • JMS 메시지를 통한 요청/응답 개념을 통해 아키텍처의 다른 부분 간의 통신 :
    • MDB는 활동 요청이 포함 된 MSG를받습니다
    • 세션 Bean을 사용하여 필요한 비즈니스 로직을 실행합니다
    • MSG의 응답 객체를 원래 요청자에게 반환합니다

아이디어는 메시지 버스를 통해 건축의 일부를 서로 연결함으로써 확장성에 제한이 없다는 것입니다. 더 많은 구성 요소를 시작하십시오. 같은 버스에 연결되어있는 한 우리는 성장하고 성장할 수 있습니다.

불행히도, 우리는 요청-상당한 개념에 큰 문제가 있습니다. 트랜잭션 MGMT는 우리의 방식으로 충분합니다. 세션 콩이 메시지를 소비하지 않아야한다는 것은 이음새가 있습니까?!

독서 http://blogs.oracle.com/fkieviet/entry/request_reply_from_an_ejb 그리고 http://forums.sun.com/message.jspa?messageid=10338789, 나는 사람들이 실제로 추천한다는 느낌을받습니다 에 맞서 EJBS의 요청/답변 개념.

이 경우 방법 하다 당신은 당신의 EJBS 사이에 의사 소통합니까? (확장 성이 내가 추구하는 것임을 기억하십시오)

내 현재 설정에 대한 세부 사항 :

  • MDB 1 'TestController', 사용 (로컬) SLSB 1 'Testservice'비즈니스 로직 용 사용
  • TestController.onMessage () TestService가 큐 XYZ에 메시지를 보내고 답장을 요청합니다.
    • Testservice는 Bean 관리 거래를 사용합니다
    • Testservice는 초기화시 JORN Connection Factory를 통해 JMS 브로커에 대한 연결 및 세션을 설정합니다 (@PostConstruct)
    • Testservice는 발송 후 거래를 저지른 다음 다른 거래를 시작하고 응답을 위해 10 초를 기다립니다.
  • 메시지가 MDB 2 'LocationController'로 가져온 (Local) SLSB 2 'LocationService'를 비즈니스 로직에 사용합니다.
  • LocationController.onMessage () LocationService가 메시지를 보냅니다 요청 된 jmsreplyto 대기열에
    • 동일한 BMT 개념, 동일한 @PostConstruct 개념
  • 모두 동일한 연결 공장을 사용하여 브로커에 액세스합니다.

문제 : 첫 번째 메시지는 (SLSB 1에 의해) 보내지고 (MDB 2) OK를받습니다. 반환 메시지 (SLSB 2)의 전송도 괜찮습니다. 하지만, SLSB 1은 아무것도받지 못합니다 - 그것은 단지 시간입니다.

나는 MessageSelector없이, 변경이없고, 여전히 수신 메시지가 없습니다.

세션 콩으로 메시지를 소비하는 것이 좋지 않습니까?

SLSB 1- testservice.java

@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 (답장 메소드 만, REST는 위와 동일합니다)

public boolean reply(Message origMsg, Serializable o) {
    boolean rc = false;

    try {
        // check if we have necessary correlationID and replyTo destination
        if (!origMsg.getJMSCorrelationID().equals("") && (origMsg.getJMSReplyTo() != null)) {
            // prepare the payload
            utx.begin();
            ObjectMessage msg = session.createObjectMessage();
            msg.setObject(o);

            // make it a response
            msg.setJMSCorrelationID(origMsg.getJMSCorrelationID());
            Destination dest = origMsg.getJMSReplyTo();

            // send it
            MessageProducer producer = session.createProducer(dest);
            producer.send(msg);
            producer.close();
            System.out.println("Reply Message has been sent");
            utx.commit();

            rc = true;
        }

    } catch (Exception e) {}

    return rc;
}

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의 전통적인 패턴입니다. 상관 식별자와의 동기 요청/답장과 비동기 메시지의 주요 차이점은 각 단계 사이에 리소스를 제거 할 수 있다는 것입니다. 나중에는 확장 할 수 있지만 첫 번째는 아닙니다.

솔직히 말해서, 나는 당신의 긴 게시물과 혼동되었고 당신의 디자인이 다소 비동기식 (그리고 올바른)이거나 요청/답장 (및 문제)과 동기인지 이해하지 못했습니다. 그러나 나는 답의 몇 가지 요소를 제공하기를 바랍니다.

어쨌든 웹 사이트를 방문하십시오 엔터프라이즈 통합 패턴, 그것은 귀중한 정보의 원천입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top