本指南提供了设计、实现、测试和部署 Cloud Run 服务的最佳做法。如需了解更多提示,请参阅迁移现有服务。
编写高效的服务
本部分介绍设计和实现 Cloud Run 服务方面的一般最佳实践。
后台活动
后台活动是指在 HTTP 响应送达后发生的任何活动。如需确定服务中是否存在并不明显的后台活动,请检查日志以查找在 HTTP 请求条目后记录的任何内容。
配置基于实例的结算方式以使用后台活动
如果您希望在 Cloud Run 服务中支持后台活动,请将 Cloud Run 服务设置为基于实例的结算方式,以便您可以在请求之外运行后台活动,并且仍拥有 CPU 访问权限。
如果使用基于请求的结算方式,请避免进行后台活动
如果您需要将服务设置为基于请求的结算方式,则当 Cloud Run 服务处理完请求后,实例对 CPU 的访问将被停用或受到严重限制。如果使用此类型的结算方式,您不应启动在请求处理程序范围之外运行的后台线程或例程。
建议检查您的代码,以确保所有异步操作都会在传送响应之前完成。
在启用基于请求的结算方式的情况下运行后台线程可能会导致出现意外行为,因为对同一容器实例发出的任何后续请求都会恢复任何已暂停的后台活动。
删除临时文件
在 Cloud Run 环境中,磁盘存储空间属于内存文件系统。写入磁盘的文件会占用供服务使用的内存,并且可在多次调用之间继续留存。 如果不删除这些文件,最终可能会导致内存不足错误,并且随后容器启动时间会变慢。
报告错误
您需要处理所有异常,防止服务因错误而崩溃。崩溃会导致容器启动缓慢,同时流量需要排队以等候某个替换实例。
如需了解如何适当地报告错误,请参阅报告错误指南。
优化性能
本部分介绍性能优化方面的最佳做法。
快速启动容器
因为实例根据需要进行扩缩,所以其启动时间会影响服务的延迟时间。Cloud Run 会将实例启动和请求处理分离,因此在某些情况下,请求必须等待新实例启动才能处理。当服务从零开始扩缩时,通常会发生这种情况。
启动例程包括以下步骤:
- 下载容器映像(使用 Cloud Run 的容器映像流式传输技术)
- 通过运行 entrypoint 命令启动容器。
- 等待容器开始侦听已配置的端口。
优化容器启动速度可以最大限度地缩短请求处理延迟时间。
使用启动 CPU 加速功能缩短启动延迟时间
您可以启用启动 CPU 加速,在实例启动期间临时增加 CPU 分配,以缩短启动延迟时间。
使用实例数下限减少容器启动时间
您可以配置实例数下限和并发,以最大限度地减少容器启动时间。例如,如果使用实例数下限 1,则表示您的服务已准备好接收为服务配置的并发请求数,而无需启动新的实例。
请注意,等待实例启动的请求将在队列中保持待处理状态,如下所示:
请求将等待,最长为此服务容器实例平均启动时间的 3.5 倍或 10 秒(以较长者为准)。
谨慎使用依赖项
如果您使用具有依赖项库的动态语言,例如导入 Node.js 模块,则这些模块的加载时间会增加启动延迟时间。
您可以通过以下方式缩短启动延迟时间:
- 最大限度地减少依赖项的数量和大小,以构建精简服务。
- 惰性加载不常用的代码(如果您所用的语言支持此方式)。
- 使用代码加载优化技术,例如 PHP 的 Composer 自动加载器优化技术。
使用全局变量
在 Cloud Run 中,您不能假设服务状态会在各请求之间保持不变。但是,Cloud Run 确实会重复使用独立的实例来处理持续流量,因此您可以在全局范围内声明一个变量,以允许后续调用重复使用其值。无法预知重复使用此变量是否会让任何单独的请求受益。
如果在每个服务请求中重新创建对象会带来很大的开销,您还可以在内存中缓存对象。将对象从请求逻辑转移到全局范围有助于提升性能。
Node.js
Python
Go
Java
对全局变量执行延迟初始化
全局变量的初始化始终在启动期间进行,因此这会增加容器启动时间。对不常用的对象使用延迟初始化可以延后其时间成本,缩短容器启动时间。
延迟初始化的一个缺点是,对新实例的首次请求的延迟时间会增加。当您部署正在积极处理大量请求的服务的新版本时,这可能会导致过度扩缩和丢弃请求。