玩转阿里云函数计算(一)----Java Http 触发器极速迁移传统 Spring 应用

简介: 前言 阿里云函数计算 Function Compute(FC),旨在帮助用户采用弹性伸缩、动态分配资源的方式,来执行业务函数。让用户无需购买部署服务器,无需考虑业务负载,就能快速搭建可处理高并发的后台服务。

前言

阿里云函数计算 Function Compute(FC),旨在帮助用户采用弹性伸缩、动态分配资源的方式,来执行业务函数。让用户无需购买部署服务器,无需考虑业务负载,就能快速搭建可处理高并发的后台服务。
函数计算平台针对 Java 语言推出的 Java HTTP 触发器功能,能够无缝迁移传统的 Java Web 应用。支持基于 Servlet 协议的 Web 框架所开发的应用,比如常用的 Spring、SpringBoot、Struts2等。
本文介绍如何使用 Java HTTP 触发器来快速迁移 Spring 提供的开源 Web 项目 GreenHouse

相关链接

开始迁移

Java HTTP 触发器使用示例代码

一、打包需要迁移的 Web 工程为 war 包

可以使用已编译好的 greenhouse.war,本步骤可直接跳过

  1. GreenHouse github 上下载 Web 工程源码。
  2. 在源码根目录执行 maven 打包命令 maven clean package -DskipTests

    注意 GreenHouse 使用的 JDK 版本是1.6,比较老。这里打包前需要修改下 pom.xml 为你使用的 JDK 版本。
    image

    打包成功后,在 target 目录下能看到 greenhouse-1.0.0.BUILD-SNAPSHOT.war 这个文件。最后为了方便将该 war 包重命名为 greenhouse.war

二、在函数计算平台创建 Java 函数

将要运行的应用 war 包可以和函数代码一起打包上传,也可以放在网络存储中比如 阿里云对象存储(OSS),或者任何其它的网络存储。以下示例将应用 war 包放在函数代码工程中和存储到 OSS 中两种方式。

方式一:应用 war 包放在函数代码工程

  1. 在本地创建 maven 工程,并创建一个 package 比如 com.aliyun.fc.example,在 package 中添加 Java 类 HelloWebLocal.java:

    public class HelloWebLocal implements FunctionInitializer, HttpRequestHandler {
        private FcAppLoader fcAppLoader = new FcAppLoader();
    
        private String key = "greenhouse.war";
        private String userContextPath = "/2016-08-15/proxy/${YourServiceName}/${YourFunctionName}";
      
        @Override
        public void initialize(Context context) throws IOException {
            FunctionComputeLogger fcLogger = context.getLogger();
          
            fcAppLoader.setFCContext(context);
          
            // Set war file path
            fcAppLoader.loadCodeFromLocalProject(key);
          
            // Init webapp from code
            long timeBegin = System.currentTimeMillis();
            fcLogger.info("Loading webapp: " + key);
            boolean initSuccess = fcAppLoader.initApp(userContextPath, HelloWebOSS.class.getClassLoader());
            if(! initSuccess) {
                throw new IOException("Init web app failed");
            }
            fcLogger.info("Loaded 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();
            }
        }
    }

    其中引用的 maven 库:

    <dependency>
       <groupId>com.aliyun.fc.runtime</groupId>
       <artifactId>fc-java-core</artifactId>
       <version>1.3.0</version>
      </dependency>
    
    <dependency>
       <groupId>com.aliyun.fc.runtime</groupId>
       <artifactId>fc-java-common</artifactId>
       <version>1.0.0</version>
      </dependency>
  2. 将 greenhouse.war 拷贝到 Java 工程中,上述代码中 loadCodeFromLocalProject 方法参数为 greenhouse.war 文件在工程中的相对路径。比如放在 src/main/resources 目录,那就和上述代码保持一样,否则改成对应的相对路径。

方式二:应用 war 包存储到 OSS 中

如果将 war 包放在创建函数的 Java 工程中,会增加创建函数时上传的代码包大小。对于代码包大小函数计算有限制最大为 50M ,请参考函数计算使用限制。往往 Java 的 web 应用 war 包会比较大,因而更好的方式是将 war 包放在 OSS 中,然后通过初始化函数 initializer 来下载 war 包到执行环境中。同样可以调用 fc-java-common 库中的 loadCodeFromOSS 方法即可,该方法会将对应的 war 包下载到执行环境的临时磁盘目录 /tmp 中。

  1. 将 greenhouse.war 上传到 OSS 中
  2. 方式一创建 maven 工程以及 Java package,并创建 HelloWebOSS.java:

    public class HelloWebOSS implements FunctionInitializer, HttpRequestHandler {
        private FcAppLoader fcAppLoader = new FcAppLoader();
    
        private String ossEndPoint = "${YourOSSEndpoint}";
        private String bucket = "${YourOSSBucket}";
        private String key = "greenhouse.war";
        private String userContextPath = "/2016-08-15/proxy/${YourServiceName}/${YourFunctionName}";
      
        @Override
        public void initialize(Context context) throws IOException {
            FunctionComputeLogger fcLogger = context.getLogger();
          
            fcAppLoader.setFCContext(context);
          
            // Load code from OSS
            fcLogger.info("Begin load code: " + key);
            boolean codeSuccess = fcAppLoader.loadCodeFromOSS(ossEndPoint, bucket, key);
            if (! codeSuccess) {
                throw new IOException("Download code failed");
            }
            fcLogger.info("End load code");
          
            // Init webapp from code
            long timeBegin = System.currentTimeMillis();
            fcLogger.info("Begin load webapp");
            boolean initSuccess = fcAppLoader.initApp(userContextPath, HelloWebOSS.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();
            }
        }
    }

函数计算平台创建函数

关于怎么在函数计算平台创建函数请参考: Hello World 示例
关于怎么使用 Java 语言请参考:Java 运行环境

将上述的 maven 工程打包,并在函数计算平台创建服务和函数,这里需要注意的点:

  1. 需要将您创建的服务名和函数名,填充到上述 HelloWebLocal.java 中:

    private String userContextPath = "/2016-08-15/proxy/${YourServiceName}/${YourFunctionName}";
  2. 如果您使用的是 OSS 存储方式,需要填充 OSS 相关信息到 HelloWebOSS.java 中:

      private String ossEndPoint = "${YourOSSEndpoint}";
      private String bucket = "${YourOSSBucket}";
      private String userContextPath = "/2016-08-15/proxy/${YourServiceName}/${YourFunctionName}";
  3. 创建函数时除了需要设置函数入口外,还需要设置初始化入口指向上述代码的 initialize 函数。
  4. Web 应用使用的内存较多,请注意函数内存大小设置,比如我这里设置的是 512M

示例配置如下:
image

为函数创建 HTTP 触发器

关于怎么创建 HTTP 触发器请参考:HTTP 触发器

测试函数运行

在函数计算控制台执行 HTTP 触发器,看到如下返回:
image

可以看到成功返回了 greenhouse 的 web 页面。
但是如果在浏览器中执行 HTTP 触发器的请求地址,web 页面将会已文件的形式下载。这是因为函数计算为了安全强制设置了请求返回的 header 为 Content-Disposition: attachment,所以返回结果会以附件形式下载。

为 HTTP 触发器绑定自定义域名

为了解决这个问题,需要用户申请自定义域名,并绑定域名解析到函数计算中,请参考函数计算绑定自定义域名
使用自定义域名访问,需要将最初的 Java 代码中 userContextPath 改为自定义域名的 contextPath 比如/ /greenhouse 等,这样才能保证页面中的超链接是相对于当前请求的域名:

// Not use custom domain
//private String userContextPath = "/2016-08-15/proxy/${YourServiceName}/${YourFunctionName}";

// Use custom domain
private String userContextPath = "/greenhouse";

自定义域名绑定到 HTTP 触发的示例配置:
image

自定义域名路径前缀必须和代码中 userContextPath 保持一致,比如这里都是 /greenhouse。当然可以选择其它的路径名,也可以使用根路径,即路径配置为 /* 对应的 userContextPath 为 /
通过修改配置路径和对应的 userContextPath,可映射到不同的 HTTP 触发器函数,从而映射到不同的 web 应用中。这样就能同一个域名同时复用到不同的 web 应用。

浏览器中访问自定义域名:
shop

大功告成!

后语

函数计算是 serverless 服务,对于传统的 Web 应用支持目前还是存在一些瑕疵。

  1. 无状态性,每次函数执行都是无状态的。对于 Web 应用往往有很多状态需要保持,比如 session,用户需要在自己的 Web 应用中去处理。当然很多 web 框架已经提供了很方便的分布式 session 方案,只需简单的配置即可。
  2. 冷启动,新的执行环境中第一次请求 web 应用会比较耗时,这是由于执行环境需要启动 JVM 以及加载 web 应用,针对这个可通过定时预热的方式来解决。

但这些相对于 serverless 提供的弹性伸缩和按需付费的优点不值一提,个人认为 serverless 必定会取代传统物理机或虚拟机的服务器方式,从而让有限的资源得到更高效的利用。

相关实践学习
函数计算部署PuLID for FLUX人像写真实现智能换颜效果
只需一张图片,生成程序员专属写真!本次实验在函数计算中内置PuLID for FLUX,您可以通过函数计算+Serverless应用中心一键部署Flux模型,快速体验超写实图像生成的魅力。
从 0 入门函数计算
在函数计算的架构中,开发者只需要编写业务代码,并监控业务运行情况就可以了。这将开发者从繁重的运维工作中解放出来,将精力投入到更有意义的开发任务上。
目录
相关文章
|
6月前
|
人工智能 运维 Kubernetes
Serverless 应用引擎 SAE:为传统应用托底,为 AI 创新加速
在容器技术持续演进与 AI 全面爆发的当下,企业既要稳健托管传统业务,又要高效落地 AI 创新,如何在复杂的基础设施与频繁的版本变化中保持敏捷、稳定与低成本,成了所有技术团队的共同挑战。阿里云 Serverless 应用引擎(SAE)正是为应对这一时代挑战而生的破局者,SAE 以“免运维、强稳定、极致降本”为核心,通过一站式的应用级托管能力,同时支撑传统应用与 AI 应用,让企业把更多精力投入到业务创新。
710 30
|
6月前
|
人工智能 算法 Java
Java与AI驱动区块链:构建智能合约与去中心化AI应用
区块链技术和人工智能的融合正在开创去中心化智能应用的新纪元。本文深入探讨如何使用Java构建AI驱动的区块链应用,涵盖智能合约开发、去中心化AI模型训练与推理、数据隐私保护以及通证经济激励等核心主题。我们将完整展示从区块链基础集成、智能合约编写、AI模型上链到去中心化应用(DApp)开发的全流程,为构建下一代可信、透明的智能去中心化系统提供完整技术方案。
437 3
|
7月前
|
存储 人工智能 Serverless
函数计算进化之路:AI 应用运行时的状态剖析
AI应用正从“请求-响应”迈向“对话式智能体”,推动Serverless架构向“会话原生”演进。阿里云函数计算引领云上 AI 应用 Serverless 运行时技术创新,实现性能、隔离与成本平衡,开启Serverless AI新范式。
744 12
|
6月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
483 8
|
7月前
|
人工智能 Java API
Java与大模型集成实战:构建智能Java应用的新范式
随着大型语言模型(LLM)的API化,将其强大的自然语言处理能力集成到现有Java应用中已成为提升应用智能水平的关键路径。本文旨在为Java开发者提供一份实用的集成指南。我们将深入探讨如何使用Spring Boot 3框架,通过HTTP客户端与OpenAI GPT(或兼容API)进行高效、安全的交互。内容涵盖项目依赖配置、异步非阻塞的API调用、请求与响应的结构化处理、异常管理以及一些面向生产环境的最佳实践,并附带完整的代码示例,助您快速将AI能力融入Java生态。
1239 12
|
7月前
|
人工智能 运维 安全
聚焦 AI 应用基础设施,云栖大会 Serverless AI 全回顾
2025 年 9 月 26 日,为期三天的云栖大会在杭州云栖小镇圆满闭幕。随着大模型技术的飞速发展,我们正从云原生时代迈向一个全新的 AI 原生应用时代。为了解决企业在 AI 应用落地中面临的高成本、高复杂度和高风险等核心挑战,阿里云基于函数计算 FC 发布一系列重磅服务。本文将对云栖大会期间 Serverless+AI 基础设施相关内容进行全面总结。
|
7月前
|
人工智能 Kubernetes 安全
重塑云上 AI 应用“运行时”,函数计算进化之路
回顾历史,电网的修建,深刻地改变了世界的经济地理和创新格局。今天,一个 AI 原生的云端运行时的进化,其意义也远不止于技术本身。这是一次设计哲学的升华:从“让应用适应平台”到“让平台主动理解和适应智能应用”的转变。当一个强大、易用、经济且安全的 AI 运行时成为像水电一样的基础设施时,它将极大地降低创新的门槛。一个独立的开发者、一个小型创业团队,将有能力去创造和部署世界级的 AI 应用。这才是技术平权的真谛,是激发全社会创新潜能的关键。
|
7月前
|
安全 Java API
Java SE 与 Java EE 区别解析及应用场景对比
在Java编程世界中,Java SE(Java Standard Edition)和Java EE(Java Enterprise Edition)是两个重要的平台版本,它们各自有着独特的定位和应用场景。理解它们之间的差异,对于开发者选择合适的技术栈进行项目开发至关重要。
1258 1
|
Web App开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
TCP洪水攻击(SYN Flood)的诊断和处理 Posted by  海涛  on 2013 年 7 月 11 日 Tweet1 ​1. SYN Flood介绍 前段时间网站被攻击多次,其中最猛烈的就是TCP洪水攻击,即SYN Flood。
1224 0
|
Web App开发 存储 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
      前段时间公司hadoop集群宕机,发现是namenode磁盘满了, 清理出部分空间后,重启集群时,重启失败。 又发现集群Secondary namenode 服务也恰恰坏掉,导致所有的操作log持续写入edits.new 文件,等集群宕机的时候文件大小已经达到了丧心病狂的70G+..重启集群报错 加载edits文件失败。
1101 0

相关产品

  • 函数计算
  • 下一篇
    开通oss服务