Pokazywanie postów oznaczonych etykietą context. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą context. Pokaż wszystkie posty

czwartek, 22 października 2015

[MessageQueues] ZeroMQ

Jest to technologia open source, cross platformowa, wbudowana w proces hosta (in-memory). API bazuje na programowaniu socketów. Nazwa ma reprezentować ideę "zero broker" - bez middleware w komunikacji.

Zero MQ jest wbudowaną biblioteką do messagingu. Jest łatwa do zintegrowania, pasuje do małych rozwiązań, ma niski koszt uruchomienia.

Jedną z wad jest to, że nie dostarcza wbudowanej serializacji, kompresji, szyfrowania i autentykacji. Nie może również zapewnić persystowania wiadomości na dysk. Dużą zaletą będzie szybkość przesyłania wiadomości, a co za tym idzie duża przepustowość.

Z poziomu języka C# mamy do dyspozycji clrzmq.dll (wrapper na libzmq.dll napisanej w C++). Bibliotekę najlepiej zainstalować za pomocą NuGeta.


Przykładowy kod wstawiający wiadomości do kolejki:

var context = new Context();

var socket = context.Socket(SocketType.PUSH);
socket.Connect("tcp://localhost:5400");

for(var i = 0; i < 1000; i++)
{
    socket.Send("message #" + i, Encoding.UTF8);
    System.Threading.Thread.Sleep(100);
}

Kod jest bardzo prosty, jednak metoda Send przyjmuje tylko stringi lub tablice bajtów, stąd konieczność serializacji obiektów "we własnym zakresie". Wiadomości przechowywane będą w pamięci procesu hostującego. Podobnie wygląda to po stronie odbierającej wiadomości:

var context = new Context();
var socket = context.Socket(SocketType.PULL);
socket.Bind("tcp://127.0.0.1:5400");

while (true)
{
    var message = socket.Recv(Encoding.UTF8);
    Console.WriteLine("processed " + message);
}

Warto zwrócić uwagę na to, że Bind nie działa dla adresu localhost, dlatego należy wpisać IP.

Context powinien być Singletonem. Tworzy on sockety i zapewnia komunikację międzyprocesową. Socket definiuje pattern komunikacyjny (PUSH,PULL,REQ,REP itd).

poniedziałek, 15 grudnia 2014

[C#|Visual Studio] ASP .NET SignalR: Hubs

Kod serwerowy można pisać na dwóch poziomach abstrakcji. Niskopoziomowo możemy wykorzystać tzw. Persistent Connection, natomiast prostszym modelem, wystarczającym do większości potrzeb są Huby. Hub można postrzegać jako zbiór metod wystawionych przez serwer do dwukierunkowej komunikacji z klientem. Nazwy metod powinny odpowiadać biznesowym operacjom, dlatego zasadna wydaje się analogia do kontrolerów ze wzorca MVC. Nie powinniśmy nigdzie w kodzie przechowywać referencji do naszych hubów - nie mamy kontroli nad ich cyklem życia, a zatem nie warto także przechowywać stanu bezpośrednio w hubie. Każda publiczna metoda może być wołana z zewnątrz (zostanie dodana do dynamicznie generowanego klienckiego proxy). Serwer może też wołać dowolną metodę kliencką dzięki Dynamic Language Runtime. Wywołanie takie sprowadzi się do serializacji metody i jej parametrów. Domyślnym serializatorem jest JSON.NET.

[HubName("modernChat")]
public class ModernChatHub : Hub
{
    public void SendMessage(string message)
    {
        Clients.All.newMessageFrom(Context.ConnectionId);
        Clients.Caller.acknowledged();
        Clients.Others.postMessage(message);
    }

    public void Subscribe(string groupName)
    {
        Groups.Add(Context.ConnectionId, groupName);
    }

    public void Unsubscribe(string groupName)
    {
        Groups.Remove(Context.ConnectionId, groupName);
    }

    public void Hello(string groupName)
    {
        var msg = string.Format("Welcome from {0}",
            groupName);
        Clients.Group(groupName).greetings(msg);
    }

    public override Task OnConnected()
    {
        var dependencyResolver = GlobalHost.DependencyResolver;
        var connectionManager = dependencyResolver.Resolve<IConnectionManager>();
        var hubContext = connectionManager.GetHubContext<ModernChatHub>();
        var all = hubContext.Clients.All;
        all.connected(Context.ConnectionId);
        return base.OnConnected();
    }
}

Mamy do dyspozycji kilka możliwości przetwarzania wiadomości. Możemy skorzystać z property Clients, wysyłając wiadomości do nadawcy, do wszystkich, do wszystkich poza nadawcą. Można także selektywnie wybierać odbiorców po id połączenia. Property Context zawiera także cookies, tożsamość użytkownika czy query string.

Kolejnym modelem są grupy agregujące użytkowników wg pewnego klucza. Trzeba pamiętać, że SignalR w żaden sposób nie przechowuje stanu po stronie serwera, co otwiera znakomite możliwości skalowalności, ale też nie zapamięta nam tego, kto był w której grupie przy restarcie aplikacji. Grupa jest zatem jedynie zrzeszeniem kilku połączeń. Grupy są tworzone w sposób dynamiczny (jeżeli łączymy się do grupy, która nie istnieje, to zostanie założona). Jedno połączenie może być skojarzone z wieloma grupami.

Ostatni przykład, to zdarzenia, do których mamy dostęp z poziomu Hub-a, takie jak OnConnected, OnDisconnected oraz OnReconnected. Wewnątrz nich możemy wołać dowolny kod. Jeżeli chcemy notyfikować podłączonych klientów spoza Huba, możemy skorzystać z DependencyResolvera (odpowiednik ServiceLocatora).