# 服务开发说明

本文介绍开发云托管服务时需要了解的一些事项。

# 编程语言支持

您可以使用任何语言、任何框架编写应用,甚至直接使用公共的容器镜像。

快速入门文档中提供了以多种主流语言编写的示例,但暂不在示例范围内的语言也均可支持。

# 代码要求

# 侦听 HTTP 请求

服务必须侦听 HTTP 请求,您可以自行配置发送请求的端口,并在 部署服务 时正确填写监听端口。在云托管的容器实例内部,PORT 环境变量的值始终反映请求发送到的端口。您的代码应检查是否存在此 PORT 环境变量,如果存在,则应侦听该变量以最大限度地提高可移植性。

# 无状态服务

服务必须是无状态服务,不能依赖永久性本地状态。这是为了能够进行水平的自动扩缩容。

无状态服务(stateless service)指的是对单次请求的处理,不依赖其他请求。处理一次请求所需的全部信息必须都包含在这个请求里,或者可以从数据库、文件存储等外部获取,实例本身不存储任何信息。

有状态服务(stateful service)则相反,它会在自身保存一些数据,先后的请求是有关联的。

# 避免后台活动

服务处理完请求后,对应的容器实例无法再访问 CPU。因此,代码中请不要在请求处理程序范围之外启动后台线程或例程,并确保在传送响应之前完成所有异步操作。强行运行后台线程可能会导致异常。

如果您怀疑服务中可能存在并不明显的后台活动,可以在日志查找在 HTTP 请求条目后记录的任何内容。

# 代码容器化

基于容器部署服务,您需要提供一个容器镜像,或者提供代码由云托管在线构建镜像。容器镜像是一种封装格式,其中包含您的代码、代码软件包、所需的全部二进制依赖项、要使用的操作系统以及运行服务所需的其他任何内容。因此,镜像一旦构建完成,以上所有信息就都被固化,云托管不会感知镜像具体内容,容器实例运行过程中镜像内容也不会变化。

如您需要修改任何内容,则需要重新构建镜像。

通常,您可以使用名为 Dockerfile 的文件来声明如何构建镜像。快速入门文档中提供的示例,也包含多种主流语言的 Dockerfile 参考。

提示

Dockerfile 背景知识:查看 Dockerfile 官方文档 (opens new window)了解语法,并查看编写 Dockerfile 的最佳做法 (opens new window)中的提示了解如何将这些语法整合在一起。

Dockerfile 通常从基础镜像(例如 FROM golang:1.11)开始。您可以在 Docker Hub (opens new window) 上找到由操作系统和语言作者维护的基础镜像。

# 谨慎使用依赖项

如果您使用具有依赖项库的动态语言,例如导入 Node.js 模块,那么在冷启动期间加载这些模块会增加延迟时间。 您可以通过以下方式缩短启动延迟时间:

  • 最大限度地减少依赖项的数量和大小,以构建精简服务。
  • 惰性加载不常用的代码(如果您所用的语言支持此方式)。
  • 使用代码加载优化技术。

# 控制镜像大小

镜像较大会造成以下影响:

  • 增加安全漏洞;
  • 降低镜像的构建速度,增加构建时长,甚至引发构建超时;
  • 降低服务的部署速度。

提示

镜像的大小不会影响请求处理时间,但过大的镜像会消耗更多构建时长,拉长的部署时间也会消耗更多 CPU 和内存资源,从而产生更多费用。

如何优化镜像请参阅:优化容器镜像