使用Akka.net開發第一個分佈式應用

系列主題:基於消息的軟件架構模型演變

 

既然這個系列的主題是」基於消息的架構模型演變「,少不了說說Actor模型。Akka.net是一個基於Actor模型的分佈式框架。若是你對分佈式應用還很是陌生,當別人在談」分佈式「、」雲計算「等名詞時你感到茫然,那麼本篇文章將帶你進行一次分佈式開發之旅。html

1、什麼是Actor模型react

Actor模型由Carl Hewitt於上世紀70年代早期提出並在Erlang語言中獲得了普遍應用,目的是爲了解決分佈式編程中一系列問題。其主要特色以下:ios

  • 系統由Actor構成
  • Actor之間徹底獨立
  • 消息傳遞是非阻塞和異步的
  • 全部消息發送都是並行的

在Actor模型中Everything is an Actor。爲何感受忽悠又開始了。。。git

若是你看過了我寫的」基於消息的架構演變「系列,你就會發現軟件系統從觀察者模式到事件而後再到消息,通過了不斷的抽象。當軟件經過消息來交互的時候再沒有了直接引用,沒有了耦合,全部的一切都變成了異步和並行。這時候再加上分佈式支持,雲計算也就變成了可能。github

2、什麼是Akka.netweb

Akka是一個基於scala語言的Actor模型庫,旨在構建一套高併發、分佈式、自動容錯、消息驅動應用的工具集。Akka.net則是C#寫的Akka版本,而且有很友好的F#Api接口。git地址:https://github.com/akkadotnet/akka.net編程

出自微軟研究院的另外一個Actor模型庫:Orleans。此項目旨在提供分佈式、高伸縮性的雲計算框架。git地址:https://github.com/dotnet/orleans,我隨後將寫關於orleans的入門文章,請關注。服務器

3、響應式宣言架構

說到Akka.net不得不提到響應式宣言。隨着互聯網和軟件行業的發展,早先的軟件架構已經不適應社會發展的需求。軟件系統的架構應該具有:彈性、鬆耦合、可伸縮性,更加容易開發和維護,發生錯誤時可以自我容錯。因此響應式系統的概念隨之而來:併發

  • Responsive:The system responds in a timely manner if at all possible(系統應儘量的及時響應)
  • Resilient: The system stays responsive in the face of failure(系統在發生錯誤時任然可以及時響應)
  • Elastic: The system stays responsive under varying workload(系統在各類負載之下都能及時響應)
  • Message Driven: Reactive Systems rely on asynchronous message-passing to establish a boundary between components that ensures loose coupling, isolation, location transparency, and provides the means to delegate errors as messages.(反應式系統依賴於異步消息組件之間創建邊界確保鬆耦合、隔離、位置透明並提供委託錯誤消息的手段,這句翻譯的有點不夠準確)

之因此要提到這個宣言是由於Akka.net正是這樣一個可以幫你創建響應式系統的框架。

4、從HelloWorld開始

一、新建一個Console Application

二、從Nuget中安裝Akka

三、新建一個GreetMessage類來通知Actor

    public class GreetingMessage
    {
    }

三、重點來了,既然在Akka.net中一切都是Actor,那麼咱們想要輸出一個」Hello world」也須要經過一個Actor來完成。新建GreetingActor類:

    public class GreetingActor : ReceiveActor
    {
        public GreetingActor()
        {
            Receive<GreetMessage>(greet =>Console.WriteLine("Hello World"));
        }
    }

正如代碼所示:當Actor收到GreetMessage消息時,輸出」Hello World」。

四、在Main方法中發送消息

        static void Main(string[] args)
        {
            // Create a new actor system (a container for your actors)
            var system = ActorSystem.Create("MySystem");

            // Create your actor and get a reference to it.
            var greeter = system.ActorOf<GreetingActor>("greeter");

            // Send a message to the actor
            greeter.Tell(new GreetingMessage());

            Console.ReadLine();
        }

一個ActorSystem是一組Actor的容器。

 var greeter = system.ActorOf<GreetingActor>("greeter");

建立了一個名爲"greeter」的Actor。

greeter.Tell(new GreetingMessage());

向greeter這個Actor發送GreetMessage消息。

Ctrl+F5跑起來看看:

這個例子雖然和簡單,可是向你們展現了Akka.net中如何使用消息和Actor。

5、開發一個分佈式的HelloWorld

這個HelloWorld它的NB之處在於它不是一個簡單的HelloWorld,他是一個分佈式的HelloWorld。。。

既然是分佈式,咱們須要創建兩個Console Application分別部署在雲端和本地,另外新建一個Class liabrary項目用來放公用的message等類型。

此次Client和Server兩個項目都須要從Nuget中安裝Akka.Remote用來遠程通訊。

先從Client端開始提及:

一、既然涉及到了遠程通訊,免不了要配置本地的地址,通訊協議,端口等信息。全部的這些配置均可以配置到web.config中。Akka.net使用HOCON(Human-Optimized Config Object Notation)的格式來配置,爲了簡單期間,咱們將這個配置直接寫到代碼裏-其實內容跟寫web.config是同樣的。

 var config = ConfigurationFactory.ParseString(@"
akka {  
    actor {
        provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
    }
    remote {
        helios.tcp {
            transport-class = ""Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote""
		    applied-adapters = []
		    transport-protocol = tcp
		    port = 0
		    hostname = localhost
        }
    }
}
");

你能夠看到這個配置描述了遠程通訊的provider、使用了helios來作TCP通訊,另外定義了client的hostname,端口號等。

二、定義Client端的ActorSystem,並向遠程發送消息

        using (var system = ActorSystem.Create("MyClient", config))
            {
                var greeting = system.ActorSelection("akka.tcp://MyServer@localhost:8081/user/Greeting");

                while (true)
                {
                    var input = Console.ReadLine();
                    if (input.Equals("sayHello"))
                    {
                        greeting.Tell(new GreetingMessage());
                    }
                }
            }

此次的重點在於建立Actor是經過system.ActorSelection方法來實現,由於此Actor在雲端,咱們沒有經過引用雲端的程序集,而是經過雲端的Actor地址akka.tcp://MyServer@localhost:8081/user/Greeting來訪問GreetingActor。MyServer是雲端的ActorSystem名稱,localhost:8081是雲端的地址和ip,因爲咱們在本地模擬,因此任然爲localhost。user/Greeting表示咱們要選取名稱爲Greeting的Actor。

當用戶在client端輸入"sayHello"以後,會向GreetingActor發送一個GreetingMessage的消息。

三、Server端的配置

 var config = ConfigurationFactory.ParseString(@"
akka {  
    actor {
        provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
    }
    remote {
        helios.tcp {
            transport-class = ""Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote""
            applied-adapters = []
            transport-protocol = tcp
            port = 8081
            hostname = localhost
        }
    }
}
");

Server端的配置跟Client端大同小異,只是擁有不一樣的端口號,若是部署在雲端,應該輸入雲端的ip。

四、Server端的ActorSystem

          using (var system = ActorSystem.Create("MyServer", config))
            {
                system.ActorOf<GreetingActor>("Greeting");

                Console.ReadLine();
            }

這個代碼很簡單,跟第一個例子中的代碼有點類似。

五、Server端的GreetingActor幾乎跟第一個例子同樣,不一樣之處在於使用了IHandle<TMessage>接口,這樣顯得Actor職責更加清晰,Actor可以處理哪些消息一目瞭然。

     public class GreetingActor:TypedActor,IHandle<GreetingMessage>
    {
        public void Handle(GreetingMessage message)
        {
            Console.WriteLine("Hello world!");
        }
    }

六、運行

在解決方案中把Client和Server同時設置爲啓動項

而後Ctrl+F5,在client中輸入"sayHello"以後,sever端會輸出Hello World。

6、Actor結構

Akka.net中的Actor是一個具備層級結構的模型,每一個ActorSystem都有多個Actor構成,而每一個父Actor又能夠建立本身的子Actor,對應到業務處理過程當中,不一樣的Actor能夠模擬面向對象的結構來處理具體的工做。而這個過程又能夠分佈在不一樣的服務器上,從而構成了一套完整的分佈式計算系統。

7、總結

本文提到的例子很是簡單,可是展現了Actor和基於消息通訊的方式。Akka.net的強大之處在於它不只像ESB那樣解決了消息的生產和消費,並且提供了Actor並行消費消息的策略和機制,他更多的強調如何讓大量的Actor之間協調工做,從而構建分佈式和響應式的系統。

使用Akka.net還能夠輕鬆實現CQRS,若是說DDD玩的是面向對象分析,那麼Akka.net將爲你解決剩下的技術細節。已經有人使用scala在Akka上進行這樣的嘗試ddd-leaven-akka,期待.net平臺下也有更好的應用讓咱們進一步去學習和了解。

相關文章
相關標籤/搜索