版本:2.3.12,原文地址: 这是原文地址链接
派发器
Akka MessageDispatcher是维持Akka actor运行,它是整个机器的引擎,
所有的MessageDispatcher实现同样也是一个ExecutionContext,它可以用来执行任何代码,例如Futures
默认派发器
在没有为Actor配置的情况下,每一个ActorSystem都有一个默认的派发器。
默认派发器是可配的,默认情况下是一个指定的default-executor的Dispatcher。
如果通过传递ExecutionContext来创建ActorSystem,在此ActorSystem中,这个ExecutionContext将作为所有派发器的默认执行者。
如果没有提供ExecutionContext,将回退到akka.actor.default-dispatcher.default-executor.fallback的executor。
默认情况下是“fork-join-executor”,在大多数情况下给予非常高的性能。
查找派发器
派发器实现了ExecutionContext接口,因此可以用来运行Future调用等待。
1. // 这是个scala并发ExecutionContext
2. // 于Futures、Scheduler等使用
3. final ExecutionContext ex = system.dispatchers().lookup("my-dispatcher");
为角色设置派发器
所以,如果你想为你的actor配置一个不同与默认的派发器,你需要做两件事情,首先是配置派发器:
my-dispatcher {
# Dispatcher is the name of the event-based dispatcher
type = Dispatcher
# What kind of ExecutionService to use
executor = "fork-join-executor"
# Configuration for the fork join pool
fork-join-executor {
# Min number of threads to cap factor-based parallelism number to
parallelism-min = 2
# Parallelism (threads) ... ceil(available processors * factor)
parallelism-factor = 2.0
# Max number of threads to cap factor-based parallelism number to
parallelism-max = 10
}
# Throughput defines the maximum number of messages to be
# processed per actor before the thread jumps to the next actor.
# Set to 1 for as fair as possible.
throughput = 100
}
这里提供了另外一种使用”thread-pool-executor”的例子:
my-thread-pool-dispatcher {
# Dispatcher is the name of the event-based dispatcher
type = Dispatcher
# What kind of ExecutionService to use
executor = "thread-pool-executor"
# Configuration for the thread pool
thread-pool-executor {
# minimum number of threads to cap factor-based core number to
core-pool-size-min = 2
# No of core threads ... ceil(available processors * factor)
core-pool-size-factor = 2.0
# maximum number of threads to cap factor-based number to
core-pool-size-max = 10
}
# Throughput defines the maximum number of messages to be
# processed per actor before the thread jumps to the next actor.
# Set to 1 for as fair as possible.
throughput = 100
}
通过默认派发器配置章节查看更多选项。
此时你如往常一样创建actor,并在部署配置时定义派发器。
ActorRef myActor =
system.actorOf(Props.create(MyUntypedActor.class),
"myactor");
akka.actor.deployment {
/myactor {
dispatcher = my-dispatcher
}
}
一种代替部署配置方法是在代码里定义派发器。
如果你在部署配置里定义派发器则该值将被使用代替编码时提供的参数。
ActorRef myActor =
system.actorOf(Props.create(MyUntypedActor.class).withDispatcher("my-dispatcher"),
"myactor3");
注意:
你在withDispatcher里指定了派发器,在部署配置时派发器的属性事实上就是配置中的一个路径。
所以这种情况下它属于顶层配置,但你可以把它放在下面的层次,用来表示子层次,就像:“foo.bar.my-dispatcher”。
派发器类型
一共有四种类型的消息派发器:
Dispatcher
- 这是基于事件的派发器,该派发器绑定在一组actor到线程池,如果没有指定,将使用默认派发器。
- 共享:无限制
- 邮箱:任何,每一个actor都有一个
- 使用场景:默认派发器,Bulkheading(啥玩意)
- 驱动:java.util.concurrent.ExecutorService指明使用”executor”、”fork-join-executor”、”thread-pool-executor”
或者akka.dispatcher.ExecutorServiceConfigurator的完全限定类名
PinnedDispatcher
- 此派发器致力于为每个使用它的actor提供一个唯一的线程,例如:每个actor将有自己的仅包含一个线程的线程池。
- 共享:无
- 邮箱:任何,每一个actor都有一个
- 使用场景:Bulkheading(啥玩意)
- 驱动:任何akka.dispatch.ThreadPoolExecutorConfigurator默认为一个”thread-pool-executor”
- CallingThreadDispatcher
- 此派发器仅在当前线程上运行调用。此派发器不会创建任何新的线程,但它同时可以由不同的线程使用同一个的actor。详情和限制请看CallingThreadDispatcher。
- 共享:无限制
- 邮箱: 任何,每个Actor每个线程创建一个(需要时)
- 使用场景:测试
- 驱动:调用的线程(duh)
更多派发器配置案例
配置PinnedDispatcher:
my-pinned-dispatcher {
executor = "thread-pool-executor"
type = PinnedDispatcher
}
于是使用它:
ActorRef myActor = system.actorOf(Props.create(MyUntypedActor.class)
.withDispatcher("my-pinned-dispatcher"));
注意:
thread-pool-executor如按照上面my-thread-pool-dispatcher例子配置是不可用的。因为当使用PinnedDispatcher时,每一个actor将有自己的线程池,并且线程池将只有一个线程。注意:
随着时间流逝这将不会保证一直使用相同线程,由于核心池超时用于PinnedDispatcher在闲置actor情况下,降低资源使用。
为一直使用相同的线程,你需要添加thread-pool-executor.allow-core-timeout=off到PinnedDispatcher配置中。