Skip to content

Allow configuring custom executor with WebSocket message broker [SPR-12272] #16877

@spring-projects-issues

Description

@spring-projects-issues

Brian Gadwell opened SPR-12272 and commented

First a little background:
One way to achieve this is to configure the ThreadPoolTaskExecutor to only use 1 thread. This does indeed work, but at the expense of scalability and performance.
As suggested in the stackoverflow link, this may be able to be handled by using an interceptor to add some type of ordering data to the message header and then using that data to try an re-order the messages when they arrive at the destination. This seems difficult to do correctly.

Now for my solution:
I was able to solve the issue by using an extension of ThreadPoolTaskExecutor that I created that allows for affinity based processing of tasks submitted to the executor. What I mean by this is that handlers can be registered with the executor and the handlers have an opportunity to determine if there is an affinity for the task (runnable) that was submitted. All tasks with the same affinity (just represented as a string) will be guaranteed to be executed in the order they were submitted. In our case, certain destination queues have an affinity and others do not. How long a thread waits for another task to be submitted with a given affinity is configurable, but some short value works well. I feel this is still scalable etc...

Now for the problem and why I am entering this issue:

  • There is no easy way to specify a ThreadPoolTaskExecutor to use for the client inbound and outbound channels. I was able to work around this by extending the WebSocketMessageBrokerConfigurationSupport class as opposed to using the @EnableWebsocketMessageBroker annotation and extending AbstractWebSocketMessageBrokerConfigurer. If a <? extends ThreadPoolTaskExecutor> could be specified then this would not be a problem.
  • The tasks in question in this case are ExecutorSubscribableChannel.SendTask, but this is private so I am unable to go from a runnable to something concrete here. If this was public then that would not be a problem.
  • Even if ExecutorSubscribableChannel.SendTask was public there is no way to get at the Message and it is the destination in the message headers that I want to examine to determine the affinity. If there was a getter for the Message then this would not be a problem.

I realize my suggestions for changes may not be agreeable and perhaps my solution may not be advisable, but I think it works well. This is a showstopper issue for the project I am working on and I was able to work around the problems by going down a nasty hack route that I would rather avoid. I am hoping the 3 changes above could be accomplished with little controversy.


Affects: 4.1 GA

Reference URL: http://stackoverflow.com/questions/23158928/spring-websocket-sequential-delivery-of-messages-on-clientoutboundchannel-per

Referenced from: commits 44e2921, 521bbfc, 179b236

1 votes, 3 watchers

Metadata

Metadata

Assignees

Labels

in: messagingIssues in messaging modules (jms, messaging)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions