使用Akka.net开发第一个分布式应用
既然這個系列的主題是”基于消息的架構(gòu)模型演變“,少不了說說Actor模型。Akka.net是一個基于Actor模型的分布式框架。如果你對分布式應(yīng)用還非常陌生,當(dāng)別人在談”分布式“、”云計算“等名詞時你感到茫然,那么本篇文章將帶你進(jìn)行一次分布式開發(fā)之旅。
一、什么是Actor模型
Actor模型由Carl Hewitt于上世紀(jì)70年代早期提出并在Erlang語言中得到了廣泛應(yīng)用,目的是為了解決分布式編程中一系列問題。其主要特點(diǎn)如下:
系統(tǒng)由Actor構(gòu)成
Actor之間完全獨(dú)立
消息傳遞是非阻塞和異步的
所有消息發(fā)送都是并行的
在Actor模型中Everything is an Actor。為什么感覺忽悠又開始了。。。
如果你看過了我寫的”基于消息的架構(gòu)演變“系列,你就會發(fā)現(xiàn)軟件系統(tǒng)從觀察者模式到事件然后再到消息,經(jīng)過了不斷的抽象。當(dāng)軟件通過消息來交互的時候再沒有了直接引用,沒有了耦合,所有的一切都變成了異步和并行。這時候再加上分布式支持,云計算也就變成了可能。
二、什么是Akka.net
Akka是一個基于scala語言的Actor模型庫,旨在構(gòu)建一套高并發(fā)、分布式、自動容錯、消息驅(qū)動應(yīng)用的工具集。Akka.net則是C#寫的Akka版本,并且有很友好的F#Api接口。git地址:https://github.com/akkadotnet/akka.net
出自微軟研究院的另一個Actor模型庫:Orleans。此項(xiàng)目旨在提供分布式、高伸縮性的云計算框架。git地址:https://github.com/dotnet/orleans,我隨后將寫關(guān)于orleans的入門文章,請關(guān)注。
三、響應(yīng)式宣言
說到Akka.net不得不提到響應(yīng)式宣言。隨著互聯(lián)網(wǎng)和軟件行業(yè)的發(fā)展,早先的軟件架構(gòu)已經(jīng)不適應(yīng)社會發(fā)展的需求。軟件系統(tǒng)的架構(gòu)應(yīng)該具備:彈性、松耦合、可伸縮性,更加容易開發(fā)和維護(hù),發(fā)生錯誤時能夠自我容錯。所以響應(yīng)式系統(tǒng)的概念隨之而來:
Responsive:The system responds in a timely manner if at all possible(系統(tǒng)應(yīng)盡可能的及時響應(yīng))
Resilient: The system stays responsive in the face of failure(系統(tǒng)在發(fā)生錯誤時任然能夠及時響應(yīng))
Elastic: The system stays responsive under varying workload(系統(tǒng)在各種負(fù)載之下都能及時響應(yīng))
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.(反應(yīng)式系統(tǒng)依賴于異步消息組件之間建立邊界確保松耦合、隔離、位置透明并提供委托錯誤消息的手段,這句翻譯的有點(diǎn)不夠準(zhǔn)確)
之所以要提到這個宣言是因?yàn)锳kka.net正是這樣一個能夠幫你建立響應(yīng)式系統(tǒng)的框架。
四、從HelloWorld開始
1、新建一個Console Application
2、從Nuget中安裝Akka
3、新建一個GreetMessage類來通知Actor
public? class? GreetingMessage { }
重點(diǎn)來了,既然在Akka.net中一切都是Actor,那么我們想要輸出一個”Hello world”也需要通過一個Actor來完成。新建GreetingActor類:
正如代碼所示:當(dāng)Actor收到GreetMessage消息時,輸出”Hello World”。
4、在Main方法中發(fā)送消息
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");
創(chuàng)建了一個名為"greeter”的Actor。
greeter.Tell(new?GreetingMessage());向greeter這個Actor發(fā)送GreetMessage消息。
Ctrl+F5跑起來看看:
這個例子雖然和簡單,但是向大家展示了Akka.net中如何使用消息和Actor。
五、開發(fā)一個分布式的HelloWorld
這個HelloWorld它的NB之處在于它不是一個簡單的HelloWorld,他是一個分布式的HelloWorld。。。
既然是分布式,我們需要建立兩個Console Application分別部署在云端和本地,另外新建一個Class liabrary項(xiàng)目用來放公用的message等類型。
這次Client和Server兩個項(xiàng)目都需要從Nuget中安裝Akka.Remote用來遠(yuǎn)程通信。
先從Client端開始說起:
1、既然涉及到了遠(yuǎn)程通信,免不了要配置本地的地址,通信協(xié)議,端口等信息。所有的這些配置都可以配置到web.config中。Akka.net使用HOCON(Human-Optimized Config Object Notation)的格式來配置,為了簡單期間,我們將這個配置直接寫到代碼里-其實(shí)內(nèi)容跟寫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 ???????? } ???? } }");
你可以看到這個配置描述了遠(yuǎn)程通信的provider、使用了helios來做TCP通信,另外定義了client的hostname,端口號等。
2、定義Client端的ActorSystem,并向遠(yuǎn)程發(fā)送消息
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()); ???????????? } ???????? } ???? }這次的重點(diǎn)在于創(chuàng)建Actor是通過system.ActorSelection方法來實(shí)現(xiàn),因?yàn)榇薃ctor在云端,我們沒有通過引用云端的程序集,而是通過云端的Actor地址akka.tcp://MyServer@localhost:8081/user/Greeting來訪問GreetingActor。MyServer是云端的ActorSystem名稱,localhost:8081是云端的地址和ip,由于我們在本地模擬,所以任然為localhost。user/Greeting表示我們要選取名稱為Greeting的Actor。
當(dāng)用戶在client端輸入"sayHello"之后,會向GreetingActor發(fā)送一個GreetingMessage的消息。
3、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端大同小異,只是擁有不同的端口號,如果部署在云端,應(yīng)該輸入云端的ip。
4、Server端的ActorSystem
using? ( var? system = ActorSystem.Create( "MyServer" , config)) ?? { ?????? system.ActorOf<GreetingActor>( "Greeting" ); ?????? Console.ReadLine();??}
這個代碼很簡單,跟第一個例子中的代碼有點(diǎn)相似。
5、Server端的GreetingActor幾乎跟第一個例子一樣,不同之處在于使用了IHandle<TMessage>接口,這樣顯得Actor職責(zé)更加清晰,Actor能夠處理哪些消息一目了然。
public? class? GreetingActor:TypedActor,IHandle<GreetingMessage> { ???? public? void? Handle(GreetingMessage message) ???? { ???????? Console.WriteLine( "Hello world!" ); ???? } }
6、運(yùn)行
在解決方案中把Client和Server同時設(shè)置為啟動項(xiàng)
然后Ctrl+F5,在client中輸入"sayHello"之后,sever端會輸出Hello World。
六、Actor結(jié)構(gòu)
Akka.net中的Actor是一個具有層級結(jié)構(gòu)的模型,每個ActorSystem都有多個Actor構(gòu)成,而每個父Actor又可以創(chuàng)建自己的子Actor,對應(yīng)到業(yè)務(wù)處理過程中,不同的Actor可以模擬面向?qū)ο蟮慕Y(jié)構(gòu)來處理具體的工作。而這個過程又可以分布在不同的服務(wù)器上,從而構(gòu)成了一套完整的分布式計算系統(tǒng)。
七、總結(jié)
本文提到的例子非常簡單,但是展示了Actor和基于消息通信的方式。Akka.net的強(qiáng)大之處在于它不僅像ESB那樣解決了消息的生產(chǎn)和消費(fèi),而且提供了Actor并行消費(fèi)消息的策略和機(jī)制,他更多的強(qiáng)調(diào)如何讓大量的Actor之間協(xié)調(diào)工作,從而構(gòu)建分布式和響應(yīng)式的系統(tǒng)。
使用Akka.net還可以輕松實(shí)現(xiàn)CQRS,如果說DDD玩的是面向?qū)ο蠓治?#xff0c;那么Akka.net將為你解決剩下的技術(shù)細(xì)節(jié)。已經(jīng)有人使用scala在Akka上進(jìn)行這樣的嘗試ddd-leaven-akka,期待.net平臺下也有更好的應(yīng)用讓我們進(jìn)一步去學(xué)習(xí)和了解。
原文地址:http://www.cnblogs.com/richieyang/p/4945905.html
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關(guān)注
總結(jié)
以上是生活随笔為你收集整理的使用Akka.net开发第一个分布式应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微软HTTP API指南
- 下一篇: 打造自己的LinqProvider