Wiki

Clone wiki

MultiServiceBus / Home

Multi Service Bus

Multi Service Bus Design FAQ

Multi Service Bus open source project is solution for communication inside process (In-Proc), inside host (In-Host) and inside network (In-Net) with the same abstraction. It uses Long Pooling (Push) pattern to solve firewall issues. For example imagine you have cell phone as the server in house in mountains. And you have to check what happen inside your home and access to this server. But cell phones are closed by firewall as usual, but you want to communicate from your flat in city...

So you define. C#

#!csharp
[Serializable]
[ProtoContract]
public class StatusMessageRequest : IMessage {
    [ProtoMember(1)]
    public string UserName {get; set;}
    [ProtoMember(2)]
    public string Password {get; set;}
}

[Serializable]
[ProtoContract]
public class StatusMessageResponse : IMessage {
    [ProtoMember(1)]
    public int Teperature {get; set;}
    [ProtoMember(2)]
    public bool AnyoneInside {get; set;}
}
Inside mountain home on cell phone connected to the internet you define. C#
#!csharp
// in any class
private static IReceiver2<StatusMessageRequest, StatusMessageResponse>
receiver
  = new Receiver2<StatusMessageRequest, StatusMessageResponse>
  ("net.tcp://IpAddressInCity:TCPPort")
  { RecieveAction = ReceiveMessage };
// and you have method ReeiveMessage
private static void ReceiveMessage(TransactId id, StatusMessageRequest message)
{
    // you validate credentials from request and made response
    if (ValidUser(StatusMessageRequest))
    {
        StatusMessageResponse response =  GetDataAboutMountainHouse();
        receiver.ResponseAsync(id, response);
    }
}

Inside home in city with connection to internet with open/forwarded IP address and TCP port you define. C#

#!csharp
// in any class
private static IRquester2<StatusMessageRequest, StatusMessageResponse>
requester
  = new Requester2<StatusMessageRequest, StatusMessageResponse>
  ("net.tcp://IpAddressInCity:TCPPort");

// and in any method that have access to reuqester you can call
requester.RequestSync(
    new StatusMessageRequest
    {
        UserName = "piotr",
        Password = "IfIHadThatHouseWouldBeNice@",
    },
    new Action<StatusMessageResponse>(
        msgRes => { /* use your response message here */ })
);

Design by Description

The idea is to use Publisher-Customers pattern for all communication. It means that many threads can add to concurrent queue messages and that messages are consumed by only 1 consumer thread per queue. That is very important for In-Proc communication to allow Multi Service Bus works good and introduce locking free, very scaleable services for high performance. And imagine you have 12 core CPU server and 48 such components... then Multi-Core ready solution is for you for free :).

For the In-Host and In-Net communication the design is using Push implementation as Long Pooling solution. It is based on data model, that is dictionary of queues, so we put to the queues messages in requesters. In receivers and/or responders we are getting the data by Long Pooling way. That simple way firewall issue is solved. Also data model based communication allow to send messages in batches not 1by1. That is also high performance design. When you send T services of all kind are slow but, when you use T[] magic happen.

From the serialization and communication perspective we are using Protobuf for serialization and de-serialization to the byte[] and Apache Thrift to send that trivial messages with byte[] data. There is one ThriftService.thrift file to share by all implications only for sending byte[]. Also Protobuf is the best in serialization to/from byte[]. That design decision free client code by define strong Thrift messages and services with all advantages of using this great solution for communication.

There is one more thing, with source code of Multi Service Bus it is possible to make Low-Latency solutions, to do so, all data buffers have to have constant capacities and if there will be no enough buffer logic should wait until it is enough buffer free. By math it is always possible to design Low-Latency and prepare enough buffers capacity constants. But it is much more advanced topic, probably for 2.0 release of Multi Service Bus :).

Design by Diagrams

TODO :)

Design by Code

That is definition how to use and how Multi Service Bus is made. C#

#!csharp
namespace CodingByToDesign.MultiServiceBus.Communication.Contracts
{
    using System;

    public interface IRequester1<TMessageReq> : IDisposable
    where TMessageReq : IMessage, new()
    {
        void RequestAsync(TMessageReq message);
    }

    public interface IRequester2<TMessageReq, TMessageRes> : IDisposable
    where TMessageReq : IMessage, new()
    where TMessageRes : IMessage, new()
    {
        Action<TMessageRes> ResponseAction { get; set; }
        void RequestAsync(TMessageReq message, Action<TMessageRes> responseAction = null);
        void RequestSync(TMessageReq message, Action<TMessageRes> responseAction = null);
    }

    public interface IReceiver1<TMessageReq> : IDisposable
    where TMessageReq : IMessage, new()
    {
        Action<TMessageReq> RecieveAction { get; set; }
    }

    public interface IReceiver2<TMessageReq, TMessageRes> : IDisposable
    where TMessageReq : IMessage, new()
    where TMessageRes : IMessage, new()
    {
        Action<TransactId, TMessageReq> RecieveAction { get; set; }
        void ResponseAsync(TransactId id, TMessageRes message);
    }

    public interface IResponder2<TMessageReq, TMessageRes> : IDisposable
    where TMessageReq : IMessage, new()
    where TMessageRes : IMessage, new()
    {
        Func<TMessageReq, TMessageRes> ResponseFunc { get; set; }
    }
}

That is definition how to use and how Multi Service Bus is made. Java (for review :P)

#!java
package net.codingbytodesign.multiservicebus.communication.contracts;

import net.codingbytodesign.multiservicebus.common.*;

// this will be implemented by ProtoBuf messages adapters with option to serialize/deserialize from/to byte array.
public interface IMessage {
    byte[] Serialize();
    void Deserialize(byte[] data);
}

public interface IRequester1<TMessageReq extends IMessage> extends IDisposable {
    public void requestAsync(TMessageReq message);
}

public interface IRequester2<TMessageReq extends IMessage, TMessageRes extends IMessage> extends IDisposable {
    public Action<TMessageRes> getResponseAction();

    public void setResponseAction(Action<TMessageRes> responseAction);

    public void requestAsync(TMessageReq message, Action<TMessageRes> responseAction);

    public void requestSync(TMessageReq message, Action<TMessageRes> responseAction);
}

public interface IReceiver1<TMessageReq extends IMessage> extends IDisposable {
    public Action<TMessageReq> getRecieveAction();

    public <TMessageRes> void setRecieveAction(Action<TMessageReq> receiveAction);
}

public interface IReceiver2<TMessageReq extends IMessage, TMessageRes extends IMessage> extends IDisposable {
    public Action2<ITransactId, TMessageReq> getRecieveAction();

    public void setRecieveAction(Action2<ITransactId, TMessageReq> recieveAction);

    public void responseAsync(ITransactId id, TMessageRes message);
}

public interface IResponder2<TMessageReq extends IMessage, TMessageRes extends IMessage> extends IDisposable {
    void setResponseFunc(Func<TMessageReq, TMessageRes> responseFunc);
}

TODO

  1. Learn: how to use Markdown syntax.
  2. Learn: how to highlight snippets of text (we use the excellent [Pygments][] library).
  3. Describe all design on wiki with diagrams to easy understand the concept.
  4. Make sure wiki contains examples in C#, Java and C++ when that parts will be ready.

Have fun!

Updated