前言
阿裡雲函數計算Function Compute(FC),旨在幫助使用者采用彈性伸縮、動态配置設定資源的方式,來執行業務函數。讓使用者無需購買部署伺服器,無需考慮業務負載,就能快速搭建可處理高并發的背景服務。
函數計算平台針對 Java 語言推出的 Java HTTP 觸發器功能,能夠無縫遷移傳統的 Java Web 應用。支援基于 Servlet 協定的 Web 架構所開發的應用,比如常用的 Spring、SpringBoot、Struts2等。
本文介紹如何使用 Java HTTP 觸發器來快速遷移 SpringBoot 應用
demo-springboot-hello,并使用函數計算提供的
fun 工具來快速部署。
繼續本文之前,建議先閱讀
相關連結
開始部署
SpringBoot 內建到函數計算平台 (FC) 有兩種方式可選擇:
- 将 FC 函數入口內建到 SpringBoot 工程
- 獨立開 FC 函數入口和 SpringBoot 工程
方式 一 較為簡單真正做到一鍵部署,但函數計算上傳的
代碼包大小有限制 50 M,可提工單調整。
方式 二 獨立的将 SpringBoot 工程打包成 war 包,并将函數入口工程打包成 jar 用來建立函數和加載 web 工程的 war 包。這種方式較為靈活,不受代碼包限制,但需要額外的建立一個函數入口工程。
方式一、內建函數入口到 SpringBoot 工程
您可以直接下載下傳
SpringBoot 內建到函數計算示例代碼測試運作
釋出 SpringBoot 工程到函數計算需要以下步驟:
1. 增加 FC 入口函數
在 SpringBoot 工程中添加 FC 的函數入口和函數初始化入口,代碼如下:
FcHandler.java
public class FcHandler implements FunctionInitializer, HttpRequestHandler {
private AppLoader fcAppLoader = new FcAppLoader();
// Request url web path
// 1. Without custom domain: /2016-08-15/proxy/${YourServiceName}/${YourFunctionName}
// 2. With custom domain: your mapping settings path
private String userContextPath = System.getenv("USER_CONTEXT_PATH");
// Webapp home directory after inited
private String appBaseDir = System.getenv("APP_BASE_DIR");
@Override
public void initialize(Context context) throws IOException {
FunctionComputeLogger fcLogger = context.getLogger();
// Config FcAppLoader
fcAppLoader.setFCContext(context);
if (appBaseDir != null) fcAppLoader.setBaseDir(appBaseDir);
// Load code from /code
fcLogger.info("Begin load code");
fcAppLoader.loadCodeFromLocalProject("");
fcLogger.info("End load code");
// Init webapp from code
long timeBegin = System.currentTimeMillis();
fcLogger.info("Begin load webapp");
boolean initSuccess = fcAppLoader.initApp(userContextPath, FcHandler.class.getClassLoader());
if(! initSuccess) {
throw new IOException("Init web app failed");
}
fcLogger.info("End load webapp, elapsed: " + (System.currentTimeMillis() - timeBegin) + "ms");
}
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response, Context context)
throws IOException, ServletException {
try {
fcAppLoader.forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
2. 增加 SpringBootServletInitializer 入口
要讓 FC 成功加載 SpringBoot,需要為 SpringBoot 配置 ServletInitializer 接口來指向 Application 入口類:
public class SpringBootStartApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
}
3. 配置打包方式
請參考
Java 代碼打包在 pom.xml 中增加如下配置:
<!-- Specify tomcat version to 8.5.20 -->
<properties>
<project.java.version>1.8</project.java.version>
<tomcat.version>8.5.20</tomcat.version>
</properties>
<!-- Exclude springboot embeded server-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Package plugin -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${project.java.version}</source>
<target>${project.java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
4. 建立服務和函數
最後,隻需在 FC 平台建立函數,以及 HTTP 觸發器即可。可使用 fun 工具來自動化建立過程,對應的 yml 配置如下:
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
# Create Service
demo-springboot-service:
Type: 'Aliyun::Serverless::Service'
Properties:
Description: 'Hello SpringBoot On FC'
Policies:
- AliyunOSSFullAccess
- AliyunLogFullAccess
LogConfig:
Project: hyt-proj
Logstore: hyt-store
InternetAccess: true
# Create function
demo-springboot:
Type: 'Aliyun::Serverless::Function'
Properties:
Initializer: hello.FcHandler::initialize
Handler: hello.FcHandler::handleRequest
Runtime: java8
CodeUri: './target/demo-springboot-hello-1.0.0.jar'
MemorySize: 256
Timeout: 60
InitializationTimeout: 60
EnvironmentVariables:
'USER_CONTEXT_PATH': '/2016-08-15/proxy/demo-sprinboot-service/demo-springboot'
'APP_BASE_DIR': '/tmp'
# Create http trigger
Events:
http: # trigger name
Type: HTTP # http trigger
Properties:
AuthType: ANONYMOUS
Methods: ['GET', 'POST']
執行
-
mvn clean package
-
fun deploy
即可部署成功
方式二、分離函數入口工程和 SpringBoot 工程
1. 打包需要遷移的 SpringBoot 工程為 war 包
demo-springboot-hello 示例代碼在源碼根目錄執行 maven 打包指令
maven clean package
。打包成功後,在 target 目錄下生成
demo-springboot-hello-1.0.0.war
這個檔案。
2. 上傳 war 包到 OSS 服務
具體怎麼上傳 OSS 請參考:
上傳檔案到 OSS3. 下載下傳示例代碼并部署
- 下載下傳 fc-demo-springboot 示例代碼
-
配置 OSS
假設上傳 OSS 的 war 包對應資訊為:
修改示例代碼中endpoint: oss-cn-hangzhou.aliyuncs.com bucket: fc-test-hyt key: demo-springboot-hello-1.0.0.war
中環境變量配置:template.yml
玩轉阿裡雲函數計算(三)——一鍵配置 SpringBoot 應用 -
部署
在示例代碼根目錄執行
即可fun deploy
測試函數運作
使用 curl 指令通路上述 deploy 生成的 url 位址:
curl https://{account_id}.{region}.fc.aliyuncs.com/2016-08-15/proxy/demo-springboot-service/demo-springboot/
成功傳回 SpringBoot 頁面