Actor 命名
Abstract
在 Ray 中,Actor 可以在命名空间(namespace)内被赋予一个唯一名称。 通过这个名称,你可以在 Ray 集群中的任意 job / driver 中重新获取该 Actor,而无需在任务之间显式传递 actor handle。
命名 Actor 常见用于以下情况:
-
无法直接传递 handle: 例如任务链路较长、跨模块 / 跨服务调用,或启动 Actor 的 driver 不方便传递 handle。
-
访问其他 driver 创建的 Actor: 比如一个长期运行的“服务型 Actor”,需要被多个 driver 共享。
-
轻量级服务发现: 使用名称作为入口,driver 启动后通过
ray.get_actor()获取 Actor。
import ray
@ray.remote
class Counter:
pass
# Create an actor with a name
counter = Counter.options(name="some_name").remote()
# Retrieve the actor later somewhere
counter = ray.get_actor("some_name")
命名 Actor 是基于命名空间(namespace)进行作用域划分的。 如果没有显式指定命名空间,它们默认会被放入一个 default 命名空间中。
import ray
@ray.remote
class Actor:
pass
# driver_1.py
# Job 1 creates an actor, "orange" in the "colors" namespace.
ray.init(address="auto", namespace="colors")
Actor.options(name="orange", lifetime="detached").remote()
# driver_2.py
# Job 2 is now connecting to a different namespace.
ray.init(address="auto", namespace="fruit")
# This fails because "orange" was defined in the "colors" namespace.
ray.get_actor("orange")
# You can also specify the namespace explicitly.
ray.get_actor("orange", namespace="colors")
# driver_3.py
# Job 3 connects to the original "colors" namespace
ray.init(address="auto", namespace="colors")
# This returns the "orange" actor we created in the first job.
ray.get_actor("orange")
获取或创建命名 Actor
一个常见的使用场景是:仅当 Actor 不存在时才创建它。Ray 提供了 get_if_exists 选项,可以直接实现这一模式。该选项需要在通过 .options() 为 Actor 设置名称之后使用。
其行为如下:
- 如果 Actor 已经存在:返回该 Actor 的 handle,并忽略传入的初始化参数
- 如果 Actor 不存在:使用指定参数创建一个新的 Actor
import ray
@ray.remote
class Greeter:
def __init__(self, value):
self.value = value
def say_hello(self):
return self.value
# Actor `g1` doesn't yet exist, so it is created with the given args.
a = Greeter.options(name="g1", get_if_exists=True).remote("Old Greeting")
assert ray.get(a.say_hello.remote()) == "Old Greeting"
# Actor `g1` already exists, so it is returned (new args are ignored).
b = Greeter.options(name="g1", get_if_exists=True).remote("New Greeting")
assert ray.get(b.say_hello.remote()) == "Old Greeting"
Actor 生命周期
默认情况下,Actor 的生命周期与其所属的 job(driver 进程)绑定。当 driver 退出时,Actor 也会随之被销毁。
Detached Actor
另外,Actor 的生命周期可以与 job 解耦,这意味着即使作业的 driver 进程已经退出,Actor 仍然可以继续存在。这种 Actor 称为 Detached Actor。
counter = Counter.options(name="CounterActor", lifetime="detached").remote()
CounterActor 会在运行上述脚本的 driver 退出后依然保持存活。因此,可以在另一个 driver 中获取它:
counter = ray.get_actor("CounterActor")
注意
一个 Actor 可以被命名,但不一定是 detached。如果只指定了名称,而没有设置 lifetime="detached",那么 CounterActor 只能在原始 driver 仍在运行时被获取。
Detached Actor 的垃圾回收
与普通 Actor 不同,detached Actor 不会被 Ray 自动进行垃圾回收。 当你确认不再需要某个 detached Actor 时,必须手动将其销毁。
可以使用 ray.kill 来手动终止该 Actor。调用之后,该 Actor 的名称可以被重新使用。