使用Akka.net开发第一个分布式应用
既然这个系列的主题是”基于消息的架构模型演变“,少不了说说Actor模型。Akka.net是一个基于Actor模型的分布式框架。如果你对分布式应用还非常陌生,当别人在谈”分布式“、”云计算“等名词时你感到茫然,那么本篇文章将带你进行一次分布式开发之旅。
一、什么是Actor模型
Actor模型由Carl Hewitt于上世纪70年代早期提出并在Erlang语言中得到了广泛应用,目的是为了解决分布式编程中一系列问题。其主要特点如下:
系统由Actor构成
Actor之间完全独立
消息传递是非阻塞和异步的
所有消息发送都是并行的
在Actor模型中Everything is an Actor。为什么感觉忽悠又开始了。。。
如果你看过了我写的”“系列,你就会发现软件系统从观察者模式到事件然后再到消息,经过了不断的抽象。当软件通过消息来交互的时候再没有了直接引用,没有了耦合,所有的一切都变成了异步和并行。这时候再加上分布式支持,云计算也就变成了可能。
二、什么是Akka.net
Akka是一个基于scala语言的Actor模型库,旨在构建一套高并发、分布式、自动容错、消息驱动应用的工具集。Akka.net则是C#写的Akka版本,并且有很友好的F#Api接口。git地址:
出自微软研究院的另一个Actor模型库:Orleans。此项目旨在提供分布式、高伸缩性的云计算框架。git地址:,我随后将写关于orleans的入门文章,请关注。
三、响应式宣言
说到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正是这样一个能够帮你建立响应式系统的框架。
四、从HelloWorld开始
1、新建一个Console Application
2、从Nuget中安装Akka
3、新建一个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”。
4、在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。
五、开发一个分布式的HelloWorld
这个HelloWorld它的NB之处在于它不是一个简单的HelloWorld,他是一个分布式的HelloWorld。。。
既然是分布式,我们需要建立两个Console Application分别部署在云端和本地,另外新建一个Class liabrary项目用来放公用的message等类型。
这次Client和Server两个项目都需要从Nuget中安装Akka.Remote用来远程通信。
先从Client端开始说起:
1、既然涉及到了远程通信,免不了要配置本地的地址,通信协议,端口等信息。所有的这些配置都可以配置到web.config中。Akka.net使用(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、使用了来做TCP通信,另外定义了client的hostname,端口号等。
2、定义Client端的ActorSystem,并向远程发送消息
using
(
var
system = ActorSystem.Create(
"MyClient"
, config))
{
var
greeting = system.ActorSelection(
"akka."
);
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的消息。
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端大同小异,只是拥有不同的端口号,如果部署在云端,应该输入云端的ip。
4、Server端的ActorSystem
using
(
var
system = ActorSystem.Create(
"MyServer"
, config))
{
system.ActorOf<GreetingActor>(
"Greeting"
);
Console.ReadLine();
}
这个代码很简单,跟第一个例子中的代码有点相似。
5、Server端的GreetingActor几乎跟第一个例子一样,不同之处在于使用了IHandle<TMessage>接口,这样显得Actor职责更加清晰,Actor能够处理哪些消息一目了然。
public
class
GreetingActor:TypedActor,IHandle<GreetingMessage>
{
public
void
Handle(GreetingMessage message)
{
Console.WriteLine(
"Hello world!"
);
}
}
6、运行
在解决方案中把Client和Server同时设置为启动项
然后Ctrl+F5,在client中输入"sayHello"之后,sever端会输出Hello World。
六、Actor结构
Akka.net中的Actor是一个具有层级结构的模型,每个ActorSystem都有多个Actor构成,而每个父Actor又可以创建自己的子Actor,对应到业务处理过程中,不同的Actor可以模拟面向对象的结构来处理具体的工作。而这个过程又可以分布在不同的服务器上,从而构成了一套完整的分布式计算系统。
七、总结
本文提到的例子非常简单,但是展示了Actor和基于消息通信的方式。Akka.net的强大之处在于它不仅像ESB那样解决了消息的生产和消费,而且提供了Actor并行消费消息的策略和机制,他更多的强调如何让大量的Actor之间协调工作,从而构建分布式和响应式的系统。
使用Akka.net还可以轻松实现CQRS,如果说DDD玩的是面向对象分析,那么Akka.net将为你解决剩下的技术细节。已经有人使用scala在Akka上进行这样的尝试,期待.net平台下也有更好的应用让我们进一步去学习和了解。
原文地址:http://www.cnblogs.com/richieyang/p/4945905.html
.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注