Skip to content
Drew Noakes edited this page Jan 10, 2017 · 5 revisions

FAQ

Q. How to log out what the class is doing internally?

To avoid dependencies, this class deliberately does not depend on any existing logging framework.

You can pass a custom logger in when you instantiate the class:

var subject = new SubjectNetMQ<MyMessage>("tcp://127.0.0.1:56001", loggerDelegate: msg => Console.Write(msg));

Q. How does it know where to send messages?

Each message is routed according to it's class name. For example, if we had a class MyClass, the this would be equivalent to a Tibco subject of MyClass.

Internally, it matches on the first 32 letters of the class name, as that is the limit for multicast routing.

Notes - Use Cases

This library is great for some use cases, and not so good for other use cases.

Good Use Cases

This library is good for any situation where we have one application that wants to publish data to many other applications (i.e. one-to-many publishing).

Examples of good use cases for this library:

  • A C# service wishes to publish data to an Excel plugin written in C#.
  • A C# service wishes to publish health statistics to any application that is listening.
  • In Service Oriented Architecture (SOA), a single service wishes to publish low latency/high volume data to all GUI applications that are listening.
  • We need good performance (this library does 180,000 messages per second on localhost, which outperforms Tibco by a factor of 3.5).
  • We want to use multicast, using the pgm:// protocol.

Bad Use Cases

This library is not designed for many applications all wanting to talk to each other (i.e. many-to-many publishing), because configuration becomes very difficult as we need to keep track of so many endpoints. If we want things to just work with minimal configuration, we need some sort of centralized message broker or a directory service sitting in the middle. This message broker or directory service makes configuration very easy: each application only has to connect to one endpoint.

Examples of bad use cases for this library:

  • A service bus where any service can talk to any other service.
  • If we suddenly realize that we have 7 applications using this library, and they all want to talk to each other.

Broker vs. Brokerless, and the Hybrid approach

If we want many-to-many communication, and we also want ultra fast speed for a handful of point-to-point links in the network, there is a hybrid approach:

  • By default, use a central message broker for ease of configuration;
  • If we need high speed links between certain nodes in the network, use this library (NetMQ.ReactiveExtensions), and use the message broker or a directory service to fetch the configuration endpoints dynamically.

For more information, see Broker vs. Brokerless. It should be noted that a broker based architecture is very easy to configure, as each application only has to know the address of the central message broker.

If we really want good support for many-to-many communication, and we are not too worried about speed, we can try a RX wrapper that has support for transports which have centralized message brokers, see Obvs.

Notes - Shared Transport

Normally, there can be many subscribers to a single endpoint, e.g. tcp://127.0.0.1:56001. However, there can be only one publisher on a single endpoint, e.g. tcp://127.0.0.1:56001. The reason is that once a port is bound to a process for writing, it is locked and cannot be reused again (which makes sense).

However, within a single process, this limitation is removed, as this library will transparently reuse a shared transport:

var publisher1 = new PublisherNetMQ<MyMessage1>("tcp://127.0.0.1:56001");
subject1.OnNext(new MyMessage1()); // Automatically sets up a transport as a publisher.

var publisher2 = new PublisherNetMQ<MyMessage2>("tcp://127.0.0.1:56001"); 
subject2.OnNext(new MyMessage2()); // Automatically reuses the shared transport.

However, if a second process attempts to bind to the publishing endpoint in the first process, an "in-use" exception will be thrown, e.g.

// Application Process 1
var publisher1 = new PublisherNetMQ<MyMessage1>("tcp://127.0.0.1:56001");
subject1.OnNext(new MyMessage1()); // Automatically binds as a publisher.

// Application Process 2 (fails)
var publisher2 = new PublisherNetMQ<MyMessage2>("tcp://127.0.0.1:56001"); 
subject1.OnNext(new MyMessage2()); // Automatically attempts to bind to the publisher.
// throws exception at this point: "Cannot bind to 'tcp://127.0.0.1:56001'.

If we really want good support for many-to-many communication, we would have to use a library that has some form of centralized message broker such as ActiveMQ or RabbitMQ, see Obvs. However, this would be slower: neither ActiveMQ or RabbitMQ can come close to 120,000 messages/second.