跳到主要内容

云引擎 Java 运行环境

信息

这篇文档是针对 Java 运行环境的深入介绍,如希望快速地开始使用云引擎,请查看 快速开始部署云引擎应用

云引擎目前支持使用 Maven 构建出的 WAR 或 JAR 项目。也支持直接上传 WAR 包。

如果要开始一个新的项目,建议从我们的示例项目开始:

警告

Java 对内存的需求较高,体验版实例的 256M 内存可能会导致 Java 进程启动时内存不足而崩溃(OOM)导致部署失败,或运行时内存不足而频繁重启。

我们建议 Java 项目至少选用 512 MB 以上的内存,Spring Boot 项目至少选用 1024 MB 以上的内存,并在之后的运行过程中根据内存用量统计随时调整。调整内存规格的方法详见 云引擎平台功能 § 调整实例规格和数量

启动命令

在完成构建后,云引擎会在 target 目录下查找 .war 或者 .jar 文件:

  • 如果找到 .war 会将其放入 Servlet 容器(Jetty 9.x)来运行
  • 如果找到 .jar 会通过 java -jar 来运行

配置 JVM 参数

云引擎运行 Java 应用时,会自动将 -Xmx 参数设置为实例规格的 70%,剩下的 30% 留给堆外内存和其他开销。如果你的应用比较特殊(比如大量使用堆外内存)可以自己定制 -Xmx 参数。假设使用 2 GB 内存规格的实例运行,则可以在云引擎的设置页面增加「自定义环境变量」,名称为 JAVA_OPTS,值为 -Xmx1500m,这样会限制 JVM 堆最大为 1.5 GB,剩下 500 MB 留给持久代、堆外内存或者其他一些杂项使用。注意:-Xmx 参数如果设置得过小可能会导致大量 CPU 消耗在反复的 GC 任务上。

配置 Java 版本

在项目根目录创建一个 system.properties 即可配置 Java 的版本:

system.properties
java.runtime.version=11

目前云引擎支持的版本有 AdoptOpenJDK 811121314

备注
对于新创建的应用,如未设置 Java 版本,云引擎会默认使用支持的版本中最新的稳定版本(LTS)。在 2021-09-02 之前创建的分组因兼容考虑会默认使用 Java `8`。

直接上传 WAR 包

在本地构建(如使用 mvn package)出 WAR 包后,可以在使用命令行工具部署时添加 --war 选项表示上传 WAR 包而不是源代码:

lean deploy --war

这种情况下在云端不会有安装依赖和构建的过程,WAR 包会被直接放入 Servlet 容器运行。

安装依赖和构建

如果上传了源代码,云引擎会使用 Maven 来安装 pom.xml 中列出的依赖,然后使用 mvn package 来进行构建。

自定义构建过程

除了特定语言默认的构建过程外,云引擎还提供了一种通用的自定义构建过程的能力,这些选项可以在 leanengine.yaml 中设置。

run 覆盖运行命令

leanengine.yaml
run: $(npm bin)/serve -c static.json -l ${LEANCLOUD_APP_PORT}

支持 Shell 语法(如引用环境变量等)。

install 覆盖依赖安装命令

覆盖默认的依赖安装命令(如 npm install),或在安装依赖前后运行自定义命令。

leanengine.yaml
install: npm

多数 runtime 有默认的依赖安装命令,可以用 {use: 'default'} 来引用默认的命令:

leanengine.yaml
install:
- { use: "default" }
- npm run install-additional

依赖安装步骤默认只会将依赖清单(如 package.json 等文件)加入构建目录,如需其他文件可以用 require 来引入:

leanengine.yaml
install:
- require:
- frontend/package.json
- frontend/package-lock.json
- cd frontend && npm ci

build 覆盖构建命令

leanengine.yaml
build: npm run build

在构建阶段全部代码文件都已经被加入了构建目录。

支持用数组来表示多条命令,支持 Shell 语法:

leanengine.yaml
build:
- echo 'building'
- NODE_ENV=production $(npm bin)/webpack

少数 runtime 有默认的构建命令,可以用 {use: 'default'} 来引用默认的命令。

构建日志

默认情况下构建过程中产生的日志不会显示到控制台,只有构建失败时,最后一个步骤的日志才会被显示在控制台上。

如需打印完整的构建日志以便调试,可以在部署时勾选「打印构建日志」或命令行工具添加参数 --options 'printBuildLogs=true'

系统级依赖

在云引擎的线上环境中,你可以通过 leanengine.yaml 文件的 systemDependencies 部分来自定义系统级依赖:

leanengine.yaml
systemDependencies:
- imagemagick

目前支持的选项包括:

  • ffmpeg 一个音视频处理工具库。
  • imagemagick 一个图片处理工具库。
  • fonts-wqy 文泉驿点阵宋体、文泉驿微米黑,通常和 phantomjschrome-headless 配合来显示中文。
  • fonts-noto 思源黑体(体积较大)。
  • phantomjs 一个无 UI 的 WebKit 浏览器(该项目已停止维护)。
  • chrome-headless 一个无 UI 的 Chrome 浏览器(体积很大,会显著增加部署耗时,运行时也会消耗大量 CPU 和内存;如果使用 puppeteer 的话,需要给 puppeteer.launch 传递这些参数:{executablePath: '/usr/bin/google-chrome', args: ['--no-sandbox', '--disable-setuid-sandbox']};暂不支持 Java)。
  • node-canvas 安装 node-canvas 所需要的系统级依赖(你仍需要安装 node-canvas)。
  • python-talib 金融市场数据分析库。
警告

注意添加系统依赖将会显著增加部署耗时,因此请不要添加未用到的依赖。

健康检查

云引擎目前主要为 Web 应用优化,应用在启动后需要在环境变量 LEANCLOUD_APP_PORT 中指定的端口上提供 HTTP 服务,注意需要监听在 0.0.0.0 地址(所有接口)上,而不是一些框架默认的 127.0.0.1

在应用部署时,云引擎的管理程序会每隔一秒去检查应用是否启动成功,如果超过启动时间限制(默认 30 秒)仍未启动成功,即认为启动失败,部署会中止。在之后的运行过程中,也会有定期的健康检查来确保应用正常运行,如果健康检查失败,云引擎管理程序会自动重启你的应用。

健康检查会通过 HTTP 检查应用的首页(/),如果返回 HTTP 2xx 的响应,就视作成功。

点击展开健康检查与云引擎 SDK 的关联

云引擎还会尝试检查由 SDK 处理的 /__engine/1/ping,如果 SDK 接入正确,便不再要求首页(/)返回 HTTP 2xx。

如果 云服务控制台 > 云引擎 > 你的分组 > 设置 > 云函数模式 设置为「开启」或 leanengine.yamlfunctionsMode 设置为 strict,云引擎会检查 SDK 是否被正确地接入,否则会视作启动失败。

点击展开自定义启动时长(startupTimeout

启动时间限制默认为 30 秒,可设置范围为 15–120 秒,如需延长或缩短,可以在 leanengine.yaml 文件中设置:

leanengine.yaml
startupTimeout: 60

云端环境

绑定自定义域名

云引擎需要设置域名才能访问。在 云服务控制台 > 云引擎 > 你的分组 > 设置 > 访问域名 处可以绑定域名。

如果你绑定的域名以 stg- 开头(如 stg-api.example.com),会自动关联到预备环境。

负载均衡和加速节点

所有对云引擎的 HTTP 或 HTTPS 请求都会经过负载均衡,负载均衡组件会处理 HTTPS 加密、重定向到 HTTPS、对响应进行压缩等一般性工作,因此云引擎上的程序不需要自己实现这些功能。同时负载均衡带来的一些限制,在云引擎程序内进行修改也无法越过,如:

  • /.well-known/acme-challenge/ 开头的路径被用于自动管理证书,不会转发到云引擎程序。
  • 请求头(URL 和 header)每行最大 8K,总计最大 64K。
  • 请求体积(上传文件体积)最大 100M。
  • 连接或等待响应的超时时间为 60 秒。

获取客户端 IP 等信息

云引擎的负载均衡会在 HTTP header 中传递一些有关原始请求的信息:

  • X-Real-IP: 请求的来源 IP。
  • X-Forwarded-Proto: 请求的来源协议(httphttps)。
  • Forwarded: RFC 7239 规定的用于传递代理信息的头,包含 IP 和 协议。
警告

在使用加速节点的情况下,以上的 HTTP header 中给出的实际上是加速节点的信息,而非原始请求信息。

在使用加速节点的情况下,还会有这些 HTTP header:

  • X-Forwarded-For: 逗号隔开的多个 IP,其中第一个是原始请求 IP。
警告

以上 HTTP 头中给出的信息并不可靠,云引擎无法确认其真实性,存在被伪造的可能。

EngineRequestContext.getRemoteAddress();
信息

中国大陆节点的云引擎应用会默认启用加速节点,如果确实需要准确的原始请求 IP,可以开通独立 IP 来绕过加速节点,更多关于加速节点与独立 IP 的区别见 域名绑定指南 § 云引擎域名

重定向到 HTTPS

在绑定云引擎自定义域名时,可以选择「强制 HTTPS」,勾选后负载均衡组件会将 HTTP 的请求重定向到 HTTPS 的同一路径。

警告

在使用加速节点的情况下,「强制 HTTPS」选项无法正确工作,仍需 在项目代码层面实现重定向

加速节点缓存

如果你将自定义域名解析到加速节点(也包括云引擎的共享域名),那么加速节点会对请求进行缓存,加速节点会有一些默认的缓存规则。

默认会缓存的情况:

  • 响应头中有 Last-Modified(通常是静态资源,其中 HTML 最多缓存 60 秒)。

不会缓存的情况:

  • 出错的响应(非 2xx)。
  • 非幂等请求(如 POST)。
  • 响应头中没有 Last-Modified(通常是动态接口)。

默认的缓存时长取决于文件类型和 Last-Modified(越不常修改的文件缓存越久),你可以通过自行设置 Cache-Control 来覆盖默认的行为,边缘节点会尽可能遵守其中的要求,比如:

  • 设置 Cache-Control: no-cache 来避免响应被缓存。
  • 设置 Cache-Control: max-age=3600 来设置缓存时长(一小时)。
信息

如果希望完全避免被缓存机制影响,可以开通独立 IP 来绕过加速节点,更多关于加速节点与独立 IP 的区别见 域名绑定指南 § 云引擎域名

环境变量

云引擎平台默认提供下列环境变量供应用使用:

变量名说明
LEANCLOUD_APP_ID当前应用的 App ID
LEANCLOUD_APP_KEY当前应用的 App Key
LEANCLOUD_APP_MASTER_KEY当前应用的 Master Key
LEANCLOUD_APP_ENV当前的应用环境:开发环境没有该环境变量,或值为 development(通过命令行工具启动)。预备环境值为 stage。生产环境值为 production
LEANCLOUD_APP_PORT当前应用开放给外网的端口,只有监听此端口,用户才可以访问到你的服务。
LEANCLOUD_API_SERVER访问存储服务时使用的地址。该值会因为所在数据中心等原因导致不一样,所以使用 REST API 请求存储服务或其他云服务时请使用此环境变量的值。
LEANCLOUD_APP_GROUP云引擎实例所在的组。当使用云引擎组管理功能时,该值为组的名称。
LEANCLOUD_REGION云引擎服务所在区域,值为 CNUS,分别表示国内版和国际版。
LEANCLOUD_VERSION_TAG云引擎实例部署的版本号。

旧版云引擎使用的以 LC_ 开头的环境变量(如 LC_APP_ID)已经被弃用。为了保证代码兼容性,LC_ 变量在一段时间内依然有效,但未来可能会完全失效。为了避免报错,建议使用 LEANCLOUD_ 变量来替换。

日志

备注

关于如何在控制台上查看日志,以及访问日志等更多内容,请看 云引擎平台功能 § 查看日志

云引擎会收集应用打印到标准输出(stdout)和标准错误输出(stderr)的日志:

备注

日志单行最大 4096 个字符,多余部分会被丢弃;日志收集速率最大 600 行每分钟,多余的部分会也被丢弃。

时区

云引擎使用北京时间(东八区)。

文件系统

你可以向 /home/leanengine/tmp 目录写入临时文件,最多不能超过 1 GB。

警告

云引擎每次部署都会产生一个新的容器,即使不部署系统偶尔也会进行一些自动调度,这意味着你 不能将本地文件系统当作持久的存储,只能用作临时存储。

如果你写入的文件体积较大,建议在使用后自动删除他们,否则如果占用磁盘空间超过 1 GB,继续写入文件可能会收到类似 Disk quota exceeded 的错误,这种情况下你可以重新部署一下,这样文件就会被清空了。

出入口 IP 地址

如果开发者希望在第三方服务平台(如微信开放平台)上配置 IP 白名单而需要获取云引擎的入口或出口 IP 地址,请进入 云服务控制台 > 云引擎 > 云引擎分组 > 设置 > 出入口 IP 来自助查询。

信息

中国大陆节点的云引擎应用会默认启用加速节点,取决于底层的供应商,入口 IP 将会非常频繁地变动。如果确实需要固定入口 IP,可以开通独立 IP。

我们会尽可能减少出入口 IP 的变化频率,但 IP 突然变换的可能性仍然存在。因此在遇到与出入口 IP 相关的问题,我们建议先进入控制台来核实一下 IP 列表是否有变化。

如需保持入口 IP 不变,建议为云引擎绑定独立 IP。

疑难问题

如何脱离命令行工具本地启动云引擎 Java 项目?

设置云引擎运行需要的环境变量后,可以通过脱离命令行工具,直接运行相应命令或使用 IDE 本地启动 Java 项目。

通过命令行启动 Jetty 项目或 JAR 项目,先设置环境变量:

eval "$(lean env)"

提示:命令 lean env 可以输出当前应用所需环境变量的设置语句,外层的 eval 是直接执行这些语句。 Windows 系统下需要手动设置 lean env 输出的环境变量。

如果是 Jetty 项目,运行:

mvn jetty:run

如果是 JAR 项目,使用 Maven 打包项目并运行:

mvn package
java -jar target/{zipped jar file}

使用 Eclipse 启动应用:

首先确保 Eclipse 已经安装 Maven 插件,并将项目以 Maven Project 方式导入 Eclipse 中。

Package Explorer 视图右键点击项目:

  • 如果是 Jetty 项目,选择 Run As > Maven build…,将 Main 标签页的 Goals 设置为 jetty:run
  • 如果是 JAR 项目,选择 Run As > Run Configurations…,选择 Application,设置 Main class:(示例项目为 cn.leancloud.demo.todo.Application)。

最后在 Environment 标签页增加以下环境变量和相应的值:

名称
LEANCLOUD_APP_ENVdevelopment
LEANCLOUD_APP_ID{{appid}}
LEANCLOUD_APP_KEY{{appkey}}
LEANCLOUD_APP_MASTER_KEY{{masterkey}}
LEANCLOUD_APP_PORT3000

配置完成后,以后只需点击 run 按钮即可启动应用。

如何在云引擎中依赖内部 library(也称为「二方库」)?

云引擎构建环境只能访问公开的程序库(library),如果你项目中使用了一些公司内部的依赖库,可以按照如下方式进行引用:

  1. 首先在项目根目录下新建 libs 目录,把所有依赖的 jar 文件拷贝进来;
  2. 然后在项目根目录下新建 leanengine.yaml 文件,并自定义 install 环节(详见下文示例);
  3. 最后修改 pom.xml 中依赖项和 spring-boot-maven-plugin 配置,增加 includeSystemScope 设置项(详见下文示例);

最终的工程目录结构如下:

{root}
|---libs
| |- yourdependency.jar etc.
|---leanengine.yaml
\---pom.xml

leanengine.yaml 内容如下:

install:
- require:
- libs
- { use: "default" }

pom.xml 中增加依赖项目:

<dependency>
<groupId>com.sample</groupId>
<artifactId>sample</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/yourdependency.jar</systemPath>
</dependency>

pom.xml 中对 spring-boot-maven-plugin 改动如下:

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>