2017-11-12 4 views
0

RabbitMQ 브로커가있는 클러스터 된 tomcat 환경에서 스프링 웹 소켓을 사용하여 응용 프로그램을 빌드하고 있습니다. 내가 듣기 위해 끝점을 등록해야하는 API 모듈이 있습니다. 나는 보통의 예를 따라이 설정 해낸이 작동하는 동안 따라서 수없는 다른 레이어를 떠나 모든 API 모듈에 번들로 제공하는 웹 소켓 및 릴레이 설정을 나타나는응용 프로그램의 다른 계층에서 STOMP 메시지 보내기

@Configuration 
@EnableWebSocketMessageBroker 
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer 
{ 
    @Override 
    public void configureMessageBroker(final MessageBrokerRegistry config) 
    { 
     config.enableStompBrokerRelay("/topic/") 
      .setRelayHost("localhost") 
      .setRelayPort(61613) 
      .setClientLogin("guest") 
      .setClientPasscode("guest"); 
    } 

    @Override 
    public void registerStompEndpoints(final StompEndpointRegistry registry) 
    { 
     registry.addEndpoint("/updates") 
      .setAllowedOrigins("*") 
      .withSockJS(); 
    } 
} 

, 그것은 내 문제가 해결되지 않습니다 브로커를 재사용합니다. 우리는 앱의 다른 모듈이 메시지를 RabbitMQ의 메시지로 푸시 할 수 있도록 서비스 계층에서 stomp 메시지 브로커 릴레이 구성을 필요로합니다. 그러면 RabbitMQ가 돌아 서서 API 모듈에 열려있는 모든 웹 소켓을 업데이트하도록 알립니다.

다음은 애플리케이션에서 관련 레이어의 샘플 다이어그램과 내가 수행하려고 시도한 것입니다. "Cron Message Sender"모듈이 다른 API 모듈을 통해 메시지 주제에 가입 한 모든 사용자에게 메시지를 전달하도록 허용해야합니다.

Sample Application Layers

+0

내가 바로 탐색하고 다른 가능한 아이디어 이 두 가지 요소를 완전히 분리 된 구성 요소로 분해해야합니다. 그 말은 각 API 모듈이 간단한 중개인 (릴레이 없음)을 사용하여 자체의 독립적 인 websocket 구성을 실행한다는 의미입니다. 그런 다음 서비스 계층에서 AMQP를 통해 rabbitmq과 직접 통신하여 각 서비스 인스턴스를 연결합니다. 그런 다음 각 API 모듈은 들어오는 AMQP 메시지를 수신하여 Stomp WS를 통해 해당 사용자에게 전달합니다. 나는 메시징에 익숙하지 않고 프로덕션 환경에서 성능면에서 좋든 나쁘 든 확실하지 않습니다. –

+0

이 접근 방식이 작동한다고 가정하면 RabbitMQ에서 AWS SQS와 같은 다른 메시지 브로커를 선호하여 더 유연하게 이동할 수 있도록 구성 요소를 분리 할 수 ​​있습니다. –

답변

1

그래서 두 번째 방법은 사실 일을했다. 웹 소켓을 독립적으로 (릴레이 없음) 실행하도록 구성한 다음 서비스 간 통신을 허용하기 위해 서비스 계층에서 별도의 AMQP 메시지 브로커 연결을 만들었습니다. API 모듈에서 간단히 AMQP 메시지 브로커를 청취 한 다음 해당 메시지를 수동으로 웹 메일 가입자에게 알린 SimpMessagingTemplate으로 전달했습니다. 이것이 기술적으로 "올바른"방법인지는 모르겠지만 훌륭하게 작동하는 것처럼 보이고 구현에 대한 문제가 아직 없습니다. 실제로, 나는 실제로 모든 서비스가 원래 웹 소켓에 필요한 것보다 많은 유형의 메시지로 서로 대화 할 수있는 능력을 부여했기 때문에 실제로이 접근법을 선호한다고 생각합니다. 여기

는 새로운 구성입니다 :

@Configuration 
@EnableWebSocketMessageBroker 
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer 
{ 
    @Override 
    public void configureMessageBroker(final MessageBrokerRegistry config) 
    { 
     config.enableSimpleBroker("/topic"); 
    } 

    @Override 
    public void registerStompEndpoints(final StompEndpointRegistry registry) 
    { 
     registry.addEndpoint("/updates") 
      .setAllowedOrigins("*") 
      .withSockJS(); 
    } 
} 

그리고 여기에 내가 메시지 브로커을 듣고 웹 소켓 가입자에게 메시지를 전달할 수있는 곳입니다 :

@Component 
public class SendWebSocketUpdates 
{ 
    private static final Logger logger = LoggerFactory.getLogger(SendWebSocketUpdates.class); 

    private final Gson gson; 

    @Autowired 
    private SimpMessagingTemplate messagingTemplate; 

    @Autowired 
    private MessageBrokerConsumer<String> messageBrokerConsumer; 

    public SendWebSocketUpdates() 
    { 
     this.gson = new Gson(); 
    } 

    @PostConstruct 
    public void init() 
    { 
     //listen for incoming AMQP messages from the rabbitmq server and forward them to the websocket subscribers 
     messageBrokerConsumer.addListener((message, topicName) -> { 
      final String destination = "/topic/" + topicName; 
      final String messageJson = gson.toJson(message.getBody()); 

      //check to see if trace logging is enabled 
      if (logger.isTraceEnabled()) 
      { 
       logger.trace("Sending Message to \"{}\": {}", destination, messageJson); 
      } 

      //broadcast the via a STOMP message to subscribers of this topic 
      messagingTemplate.convertAndSend(destination, messageJson); 
     }); 
    } 
}