问题
I am trying to get my head around message buses and ioc's and my head is spinning with questions.
This is the scenario I have in mind
Three computers connected by LAN, no internet access. The three computers each have a service that runs and automatically self discovers the others, in other words , they each send messages on a common bus?? which identifies themselves.
From that point on wards they can exchange any type of messages.
Is this possible in the first instance just using a message bus architecture?
If it is, how would the self discovery bit work? All the examples I have seen seem to be local queues which are machine specific. I cant seem to find an example where remote queues are sent messages or where self discovery is done.
I have got a local service working with rebus in .Net but looking to now understand the missing pieces of the puzzle.
I am not talking about any fancy setup using ASP.Net or anything at this moment. Any help is greatly appreciated
回答1:
So I don't know rebus but I can talk in depth about MassTransit.
If I wanted a system without Internet connectivity to be able to automatically enroll in the bus so it can exchange messages with its peers, there are two primary options that come to mind.
RabbitMQ or MSMQ have a known, central location that every instance connects to. With RabbitMQ it's simple the RabbitMQ instance everyone uses, like rabbitmq://10.0.0.10/my_queue as the
ReceiveFrom
address in configuration. For MSMQ, it would be msmq://10.0.0.10/mt_subscriptions for the subscription service queue location. Then theReceiveFrom
queue should be msmq://localhost/my_queue. Once the bus shares a central location then all peers can communicate.Have a "two bus" system. First use MSMQ's multicast for discovery. Basically broadcast a message every minute or so until a central server is found then start up the other bus like #1 but with the address provided from the multicast bus. If you use RabbitMQ it means mixing RabbitMQ and MSMQ buses.
A third, but not awesome, possibility is just flat out using the multicast subscription client for MSMQ. This isn't perfect as multicast wasn't designed for production use. However, if the trade offs are acceptable, then you could use it. MSMQ Multicast has a start up lag between when the service begins execution and when the subscriptions are full negotiated. This can cause message loss if you start publishing right away. Multicast requires either all machines on the same subnet or back vodoo magic* with your routers to get the multicast to work across subnets.
It's worth noting this has nothing to with IoC at this point. That's really just a configuration thing. The idea with MassTransit is that once you're enrolled in a bus, as long as another member of the bus publishes to it - the message will end up of all consumers of that message automatically.
*Note: I'm pretty sure it's not black vodoo magic but as far as I'm concerned it is. You'll need help from someone else to make this work.
2nd Note: With MSMQ it's important to use the ReceiveFrom
queue on the localhost. Sending to remote hosts works well enough, but reading from is much harder to diagnose when there's an issue.
3rd Note: I will promote RabbitMQ over MSMQ every time except if you require all peers are enrolled in DTC. If that's a requirement for you I wish you the best of luck with all your heartache.
回答2:
With Rebus, you can easily achieve the behavior you're describing by making all three service endpoints share the same subscription storage, e.g. a central SQL Server/MongoDB/RavenDB/PostgreSQL database, and then letting each subscriber establish the subscription by subscribing with itself.
In order to subscribe with itself, an endpoint must be the owner of all the message types, e.g. by having the following Rebus XML in app.config:
<configSections>
<section name="rebus" type="Rebus.Configuration.RebusConfigurationSection, Rebus" />
</configSections>
<rebus inputQueue="myOwnInputQueue" errorQueue="sharedErrorQueue@anotherMachine">
<add messages="SomeMessageAssembly" endpoint="myOwnInputQueue"/>
</rebus>
This way, each endpoint need only do a bus.Subscribe<SomeMessage>()
in order to register as a subscriber of that particular message type, and from that point on it will get to handle all published SomeMessage
s, regardless of which endpoint publishes it (note: including itself!)
If an endpoint needs to filter incoming messages by who sent it, it can inspect the rebus-return-address header in order to e.g. ignore messages that it has published itself.
If you want to centralize your subscription storage in other ways than the mentioned database options, you can use your own implementation of IStoreSubscriptions that stores subscriptions somewhere else or uses other logic to decide who receives messages of a given type.
Take a look at the IStoreSubscriptions wiki page for more information and inspiration :)
Does that make sense?
Update: I couldn't help it, I had to try - check out the MessageBus sample in the Rebus samples repository - it is a POC of the solution I described here by using a shared XML file to store subscriptions.
来源:https://stackoverflow.com/questions/23488670/bus-discovery-in-message-busses