处理依赖关系#
添加运行时环境#
导入路径(例如,text_ml:app
)必须能在运行时被 Serve 导入。在本地运行时,该路径可能在你当前的工作目录中。然而,在集群上运行时,你也需要确保该路径可导入。将代码构建到集群的容器镜像中(详见集群配置)或使用带有远程 URI 的runtime_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)