初识云函数

1.云函数概述

云函数(Serverless Cloud Function,简称SCF)是一种无服务器(Serverless)计算服务,它允许开发者在不管理服务器的情况下运行代码。云函数通常由事件触发,如HTTP请求、oss上传、消息队列或定时任务。这种服务模型提供了一种简单、灵活且成本效益高的方式来处理各种计算任务。

以下是云函数的一些关键特点:

  1. 无需管理服务器:云服务提供商负责服务器的维护、扩展和可用性。

  2. 按需自动扩展:云函数可以根据请求的数量自动扩展,无需手动干预。

  3. 无状态:是指云函数在执行时不保留任何状态信息。每次调用云函数时,它都是从一个干净的状态开始执行,而不依赖于任何之前的执行或外部状态。

  4. 事件驱动:云函数可以响应各种事件,如HTTP请求、数据库更改、文件上传等。

  5. 快速部署:开发者可以快速部署代码,通常只需要几行配置。

  6. 成本效益:云函数通常按实际使用量计费,只在函数执行时产生费用。

  7. 多种语言支持:大多数云服务提供商支持多种编程语言,如Node.js、Python、Java、Go、C#等。

  8. 集成开发工具:云函数通常与IDE、CI/CD工具和其他开发工具集成,方便开发和部署。

  9. 安全性:云服务提供商提供安全措施,如身份验证、授权和网络隔离。

  10. 可组合性:云函数可以与其他云服务(如数据库、存储、消息队列等)轻松集成,构建复杂的应用程序。

腾讯云、阿里云、AWS Lambda、Google Cloud Functions 和 Azure Functions 等云服务提供商都提供了云函数服务。每个提供商可能有特定的服务名称和特性,但基本概念和使用方式相似。

这里最重要的两个概念:

Serverless:无服务器不是表示没有服务器,而表示在使用 Serverless 时,无需关心底层资源,也无需登录服务器和优化服务器,只需关注最核心的代码片段,即可跳过复杂的、繁琐的基本工作。

无状态:每次调用云函数都是独立的,函数的执行不依赖于任何外部状态或上下文。这意味着每次调用都是从零开始,函数内部需要处理所有必要的逻辑。

这两个特征使得SCF 拥有近乎无限的扩容能力,空闲时,不运行任何资源。代码运行无状态,可以轻易实现快速迭代、极速部署。

如何与外部资源交互?

无状态并不意味着云函数不能与外部系统交互或存储数据。云函数可以调用数据库、缓存、消息队列和其他服务来存储和检索数据。关键是这些交互是临时的,每次函数调用都是独立的,不会在函数实例之间保留状态。

云函数每次调用是独立的,但是云函数处理的对象本身是可以无状态的。打个比方,部署在云函数的一个游戏接口,功能是扣减道具,每次调用虽然是独立的,但操纵的玩家背包是有状态的。云函数设计的时候需要自行处理内部状态管理,例如可以使用分布式锁或者消息队列。

2.腾讯云函数

2.1.新用户免费试用

本文以腾讯云函数作为演示对象。前往腾讯云  注册帐号,新人可以白嫖试用3个月,足够学习了。

从控制台进入云函数界面, 这里有很多功能比较强大的社区模板,新人当然是从helloword开始了。 

官方支持Python,Go,Java,Node,Php几种语言,其中解释型语言Python,Node,Php这三种是支持在线IDE编辑,而Go,Java这两种编译型语言只运行本地编译后打包上传。

下图为Node的在线编辑器(Cloud StudioVSCode高度类似)。

2.2.不同语言的内存占用

分别以这几种语言,跑下helloworld,观察下每种语言的内存占用。

可以看到,java占用45M,Node13.5M,其余都是8M以内。

java本身JRE体积是比较大的(使用jdk9+可以通过模块化减少体积),另一方面,java主流采用JIT(即时编译),只有热点代码才会被编译成本地代码(可以简单理解为,运行越久,代码跑得越快)。因此对于云函数这种要求启动快,执行时间短来说,java这种“慢热”语言天生不适宜。

3.使用层管理公共库

3.1 创建云函数

本地创建一个云函数,使用到第三方依赖,例如sl4f。

执行mvn package,将第三方依赖

3.1.层的创建与绑定

当多个云函数拥有较多的公共依赖库或公共代码文件,可以使用 SCF 中的层进行管理。使用层管理,您可以将依赖放在层中而不是部署包中,可确保部署包保持较小的体积。

在云函数操作界面,可以看到“层”管理,新建一个层,上传本地依赖zip文件(上一步生成的vendor.zip文件)。

需要注意的是,这里的运行环境需要包含云函数所对应的运行环境。否则,在云函数界面无法进行绑定。

已绑定层的函数被触发运行,启动并发实例时,将会解压加载函数的运行代码至 /var/user/ 目录下,同时会将层内容解压加载至 /opt 目录下。

从官方文档可以看出,java云函数会把层的解压目录(/opt)加入到classpath。这意味着,云函数jar包无须手动设置MANIFEST.MF文件里面的classpath路径。(使用mave打包的话,不用设置以下参数)

编辑云函数代码,如下:

package example;
import com.qcloud.scf.runtime.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Hello {

    public String mainHandler(Params params, Context context) {
        Logger logger = LoggerFactory.getLogger("");
        logger.error("-----------------");
        System.out.println("Hello world!");
        String content = "requestId=" + context.getRequestId();
        return String.format("context = %s, params = %s.", content, params);
    }

}

在云函数操作界面,绑定 层

 3.2.踩到腾讯云函数层的bug

点击“测试”按钮,报错,无法找到class

初步怀疑,层的依赖没有解压到/opt目录下,修改代码,把/opt目录的文件输出来

package example;

import com.qcloud.scf.runtime.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.Objects;

public class Hello {

    public String mainHandler(Params params, Context context) {
        File file = new File("/opt");
        if (file.exists()) {
            System.out.println("directory exist");
            if (file.isDirectory()) {
                for (File f : Objects.requireNonNull(file.listFiles())) {
                    System.out.println("jar name: "+f.getName() +", path: " + f.getAbsolutePath());
                }
            } else {
                System.out.println("only one file");
            }
        } else {
            System.out.println("directory NOT exist");
        }

        Logger logger = LoggerFactory.getLogger("");
        logger.error("-----------------");

        System.out.println("Hello world!");
        String content = "requestId=" + context.getRequestId();
        return String.format("context = %s, params = %s.", content, params);
    }

}

重新上传,部署,测试,输出如下:(可以清楚看到层的依赖确实被解压出来了)

 问题仍然存在,百思不得其解,无头苍蝇乱试了很久,一次偶然的操作,我把sl4f.jar不打包成zip上传,居然成功了!

破防!!这意味着,如果需要使用层的功能,有多少个第三方依赖,就会创建多少个层。每一个层是一个未经压缩的jar文件。无奈之下,求助人工客服。

客服委托技术找了半小时之后,说问题需要转交,需要再半小时。然而,半小时后(此时15:30),客服说,五点之前给答复。看来,这个问题以前没人发现啊,一不小时就被我踩到了。16:30客户来信,说是符合预期的,就是需要将依赖跟代码打到同一个jar包云。简直无语~~

客服可能觉得确实有点敷衍,说需要进一步核实,18:00前答复。

感觉这个操作很基础啊,使用层管理公共依赖,减少云函数jar包大小。唯一的解释是,使用java来开发云函数的人真得很少,这种低级bug都没人反馈

后来又延迟到20:00。估计当初的技术已经被优化了,新来的实习生还在看文档。

当晚11点,技术人员发来消息,笔者隔天才回复(技术加班加点修bug~~)

 看来这个问题短期无法解决,需要等技术评估后升级。如果使用java,要么把代码和依赖打成一个胖包(忍受每次上传一个大文件),要么每一个依赖都打包成一个层。希望后续腾讯云能把这个功能修复,方便我们这些javaer。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jforgame

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值