Dynamic channel configuration

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Dynamic channel configuration

grampajohn
Administrator

I'm looking at the server with an eye to how the various message channels get defined, and trying to avoid as much as possible needing channel-specific code in the various plugins. The simplest configuration is pipe-and-filter, meaning that every module that uses messages has either one input channel, one output channel, or one of each. It's also far easier if these are pre-defined and not computed at runtime.

The need to support a set of brokers defined only at runtime makes this a challenge. Also, some messages (new tariffs, market clearing prices) need to be distributed to all brokers, while other messages (tariff subscriptions, account updates) need to be directed at specific brokers. Of course, the number and identities of the brokers is not known until runtime - these are game-configuration details, and in fact the channels to individual brokers probably cannot be connected until they log in.

If we want to avoid multiple output channels on various components (for example, the forward market produces data for individual brokers and for accounting, as well as summary data for all brokers), then it seems there are two options:

  1. Build our own message-distribution module - a fairly fancy router - that knows how to route a variety of messages, can dynamically configure channels, and contains explicit code for directing output to multiple channels. This router would have to know about all the different message types and be able to inspect at least some of their contents. This sounds like a high-coupling approach.
  2. Insist that every module have only one output channel, and introduce additional structure to pull out the extra channels. The place this seems to be most problematic is the separation of per-broker and all-broker outputs. So we could decide that all existing modules that communicate with brokers put their output on a channel that gets routed to individual brokers. Then we introduce a new module (market-data) that gathers up the information needed by all brokers using method calls or database lookups. These then go to an output-only channel that goes to all brokers.

The second problem is the need for dynamic configuration of channels at runtime. If someone knows how to do this without impacting plugin code, please help out. My initial research has not been encouraging. A fallback approach would be to implement a fixed set of broker proxies, whose responsibility is to handle the external communication with brokers. Brokers would be assigned a proxy when they log in.

Please let me know your thoughts on this problem, especially if you know something about configuring channels beyond what's in the SIA book.

Thanks.

John

Reply | Threaded
Open this post in threaded view
|

Re: Dynamic channel configuration

grampajohn
Administrator
In that last post, I said that plugins should have just one input and one output channel. That's not exactly right. Any given method in a plugin can serve a separate (input, output) pair. What a method cannot easily do is to serve multiple output channels. So there's actually a third option for dealing with the need to serve multiple outputs -- accumulate state within a service, and then dump that state periodically. So the market, for example, could send out transactions for individual brokers, and accumulate the summary data, then dump the summary data through another method when triggered somehow.

Have I missed any other reasonably straightforward options?

John
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic channel configuration

ddauer
This is (roughly) how it was done with the TAC Energy server: The competition controller creates a queue for incoming messages and a queue for every broker that it expects to participate. Now, when sending messages to brokers, these queues are adressed dynamically (say "brokers.{id}.output"). There's a JmsBrokerManagementService in edu.kit.iism.cdamarket in the old tacenergy code if you're interested in details.

Therefore, I think the best way for now is to have one message endpoint (which could be called BrokerProxy), which would intelligently route messages based on their type to the different output queues to the broker(s). This would conform with your solution #1. I agree that this is a relatively high-coupled approach, but we're not going to change message types a lot?! I think one endpoint might be enough since every module could use the proxy's input channel as one of its output channels if appropriate, right? Every message sent would of course need to contain a broker id so the router would know which broker to address. Let's say a message with no broker id sent to the proxy will be sent to all brokers. Am I missing something or is there a specific reason why you're mentioning a set of multiple broker proxies?

Does that help?

David
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic channel configuration

grampajohn
Administrator
ddauer wrote
...

I think the best way for now is to have one message endpoint (which could be called BrokerProxy), which would intelligently route messages based on their type to the different output queues to the broker(s). This would conform with your solution #1. I agree that this is a relatively high-coupled approach, but we're not going to change message types a lot?! I think one endpoint might be enough since every module could use the proxy's input channel as one of its output channels if appropriate, right? Every message sent would of course need to contain a broker id so the router would know which broker to address. Let's say a message with no broker id sent to the proxy will be sent to all brokers. Am I missing something or is there a specific reason why you're mentioning a set of multiple broker proxies?

Does that help?
Thanks, David, that's very helpful. I guess that would mean that any information we want to have broadcast CANNOT have a broker ID.

We'll have to think about how to package up tariffs for redistribution. Is it important that broadcast tariffs NOT be identifiable with individual brokers? That does not see quite right. Perhaps we should send broadcast tariffs inside a simple wrapper that lacks the broker ID.

Here's another idea: As I understand it, channels are associated with individual methods in a service, not with the service itself, right? So perhaps an alternative would be to have two methods on the BrokerProxyService, one for broadcast and one for per-broker forwarding. There would then be two channels, a broker-output channel and a broker-broadcast channel, into which other components could dump messages. There could also be an API that could be called to send stuff to brokers. Does this make any sense?

Another question is about type relationships in a channel. If we expect a certain field to exist in a message (for routing purposes, for example), do all the messages in the channel need to be subtypes of a message type that contains that field (such as a broker ID)? Also, if I have a method defined as an endpoint, can I implement multiple versions of that method for different message types (polymorphic methods) and have the normal runtime dispatching work correctly? I'm assuming the answer is yes. Of course, this is something you could not do in Java at all, unless you implement some sort of visitor scheme.

Just trying to get a clearer understanding of how all this stuff can work...

John
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic channel configuration

ddauer
On Thu, Mar 3, 2011 at 10:33 PM, grampajohn [via Power TAC Developers] <[hidden email]> wrote:

Thanks, David, that's very helpful. I guess that would mean that any information we want to have broadcast CANNOT have a broker ID. 

We'll have to think about how to package up tariffs for redistribution. Is it important that broadcast tariffs NOT be identifiable with individual brokers? That does not see quite right. Perhaps we should send broadcast tariffs inside a simple wrapper that lacks the broker ID.

I don't see an obvious reason why broadcast tariffs should not be identifiable with individual brokers. In fact, I think it is important that they are in order to allow brokers to profile each other. As for ids that need to be hidden, I think there's definitely going to be a way we can filter those out (probably similar to what you mentioned before by extending the proxy's logic).
 

Here's another idea: As I understand it, channels are associated with individual methods in a service, not with the service itself, right?

A service-activator is associated with an individual method, not the channel. See http://static.springsource.org/spring-integration/docs/2.0.0.RELEASE/reference/htmlsingle/#overview-endpoints-service-activator for an example.
 
So perhaps an alternative would be to have two methods on the BrokerProxyService, one for broadcast and one for per-broker forwarding. There would then be two channels, a broker-output channel and a broker-broadcast channel, into which other components could dump messages. There could also be an API that could be called to send stuff to brokers. Does this make any sense?

Yes, two methods would be the better way to do this. Not sure if I understand you correctly, but there's no need for an explicit API since you can programmatically put a message into any configured channel. (See http://static.springsource.org/spring-integration/docs/2.0.0.RELEASE/reference/htmlsingle/#channel-interfaces)
 
Another question is about type relationships in a channel. If we expect a certain field to exist in a message (for routing purposes, for example), do all the messages in the channel need to be subtypes of a message type that contains that field (such as a broker ID)?

No, a channel can contain any type of message. Routing itself is highly customizable, so we wouldn't have a problem handling messages containing a broker id or not (See http://static.springsource.org/spring-integration/docs/2.0.0.RELEASE/reference/htmlsingle/#router). I guess we could either use a HeaderValueRouter assuming that we add the broker id to the message header, or we could write a custom router.
 
Also, if I have a method defined as an endpoint, can I implement multiple versions of that method for different message types (polymorphic methods) and have the normal runtime dispatching work correctly? I'm assuming the answer is yes. Of course, this is something you could not do in Java at all, unless you implement some sort of visitor scheme.

Yes, that works fine.

- David
Reply | Threaded
Open this post in threaded view
|

Re: Dynamic channel configuration

grampajohn
Administrator
ddauer wrote
> So perhaps an alternative would be to have two methods on the BrokerProxyService, one for broadcast and one for per-broker forwarding. There would then be two channels, a broker-output channel and a broker-broadcast channel, into which other components could dump messages. There could also be an API that could be called to send stuff to brokers. Does this make any sense?

Yes, two methods would be the better way to do this. Not sure if I understand you correctly, but there's no need for an explicit API since you can programmatically put a message into any configured channel. (See http://static.springsource.org/spring-integration/docs/2.0.0.RELEASE/reference/htmlsingle/#channel-interfaces)
It's a convenience issue. To programmatically put a message into a channel, you have to look up the channel, package your content as a message, and put it in the channel. Then the content gets pulled back out of the message, and the method gets called. On the other hand, you could just call the method. Grails autowiring takes care of filling in the service reference. I am inclined to think that the only way messaging adds value _inside_ the server is when you want (or might want) deferred activation. For example, by queuing up transactions while the customer models run, and processing them later.

Am I missing something?

John
Reply | Threaded
Open this post in threaded view
|

AW: Dynamic channel configuration

chris.flath
In reply to this post by ddauer

>> We'll have to think about how to package up tariffs for redistribution. Is it important that broadcast tariffs
>> NOT be identifiable with individual brokers? That does not see quite right. Perhaps we should send broadcast
>> tariffs inside a simple wrapper that lacks the broker ID.

> I don't see an obvious reason why broadcast tariffs should not be identifiable with individual brokers. In fact, I
> think it is important that they are in order to allow brokers to profile each other. As for ids that need to be
> hidden, I think there's definitely going to be a way we can filter those out (probably similar to what you
> mentioned before by extending the proxy's logic).
 
I second the idea that you should be able to see all offered tariffs and identify them by broker. This is potentially a key ingredient to competitive learning and strategy evaluation for the brokers.

Chris