处理依赖关系#

添加运行时环境#

导入路径(例如,text_ml:app)必须能在运行时被 Serve 导入。在本地运行时,该路径可能在你当前的工作目录中。然而,在集群上运行时,你也需要确保该路径可导入。将代码构建到集群的容器镜像中(详见集群配置)或使用带有远程 URIruntime_env,该远程 URI 指向远程存储中托管的代码。

例如,请参阅 GitHub 上的 Text ML Models 应用。即使你没有本地代码,也可以使用此配置文件将文本摘要和翻译应用部署到你自己的 Ray 集群。

import_path: text_ml:app

runtime_env:
    working_dir: "https://github.com/ray-project/serve_config_examples/archive/HEAD.zip"
    pip:
      - torch
      - transformers

注意

你还可以将部署图打包成一个独立的 Python 包,可以使用 PYTHONPATH 导入它,以便在本地机器上实现位置独立性。然而,最佳实践是使用 runtime_env,以确保集群中所有机器的一致性。

每个部署的依赖关系#

Ray Serve 还支持服务具有不同(可能冲突的)Python 依赖关系的部署。例如,你可以同时服务一个使用旧版 Tensorflow 1 的部署和一个使用 Tensorflow 2 的部署。

在 Mac OS 和 Linux 上,Ray 通过其运行时环境功能支持此特性。与其他所有 Ray actor 选项一样,通过部署中的 ray_actor_options 传入运行时环境。请务必先运行 pip install "ray[default]" 以确保已安装运行时环境功能。

示例

import requests
from starlette.requests import Request

from ray import serve
from ray.serve.handle import DeploymentHandle


@serve.deployment
class Ingress:
    def __init__(
        self, ver_25_handle: DeploymentHandle, ver_26_handle: DeploymentHandle
    ):
        self.ver_25_handle = ver_25_handle
        self.ver_26_handle = ver_26_handle

    async def __call__(self, request: Request):
        if request.query_params["version"] == "25":
            return await self.ver_25_handle.remote()
        else:
            return await self.ver_26_handle.remote()


@serve.deployment
def requests_version():
    return requests.__version__


ver_25 = requests_version.options(
    name="25",
    ray_actor_options={"runtime_env": {"pip": ["requests==2.25.1"]}},
).bind()
ver_26 = requests_version.options(
    name="26",
    ray_actor_options={"runtime_env": {"pip": ["requests==2.26.0"]}},
).bind()

app = Ingress.bind(ver_25, ver_26)
serve.run(app)

assert requests.get("http://127.0.0.1:8000/?version=25").text == "2.25.1"
assert requests.get("http://127.0.0.1:8000/?version=26").text == "2.26.0"

提示

避免动态安装需要从源代码编译的包:这些包安装过程可能很慢,会占用所有资源,从而导致 Ray 集群出现问题。考虑在私有仓库或 Docker 镜像中预编译此类包。

部署中所需的依赖关系可能与驱动程序(运行 Serve API 调用的程序)中安装的依赖关系不同。在这种情况下,你应该在类中使用延迟导入,以避免在驱动程序中导入不可用的包。即使不使用运行时环境,这也适用。

示例

from ray import serve


@serve.deployment
class MyDeployment:
    def __call__(self, model_path):
        from my_module import my_model

        self.model = my_model.load(model_path)