第二章:云函数基础

好,咱们正式开始接触 Serverless 的核心——云函数。说实话,我第一次接触这个概念时,心里也犯嘀咕:「这不就是换个名字的虚拟机吗?」后来踩过坑、写过生产代码,才真正理解它的设计哲学。

云函数到底是什么?

云函数,说白了就是一段代码,一段「用完即走」的代码。你不需要关心它跑在哪台机器上,不需要配置 Nginx,不需要操心运维。你只管写逻辑,平台负责执行。

我习惯把云函数比作「外卖小哥」:你点餐(触发事件),小哥接单(函数启动),送到你家(返回结果),然后小哥就走了(函数结束)。你不会关心小哥骑什么车、走哪条路,对吧?

核心特征:

  • 无状态:每次调用都是全新的环境,不保留上次的变量
  • 事件驱动:有事件来了才执行,没事就休眠
  • 自动扩缩:1 个请求来就 1 个实例,10000 个请求来就 10000 个实例
  • 按量付费:不运行就不花钱,这点对个人开发者太友好了

你想想看,传统后端开发中,你写个接口要经历什么?买服务器、装系统、配环境、部署代码、配置反向代理、设置监控告警……这一套下来,少说半天。云函数呢?写代码,上传,完事。

创建你的第一个云函数

光说不练假把式。咱们直接上手,用腾讯云 SCF(Serverless Cloud Function)来创建一个最简单的「Hello World」函数。

嗯,这里要注意:不同平台的创建流程大同小异,核心概念是一样的。

步骤一:准备工作

  1. 登录云平台控制台,找到「云函数」服务
  2. 点击「新建」按钮
  3. 选择运行环境:我建议新手先用 Node.js 16+,生态成熟,调试方便
  4. 函数名称:hello-serverless

步骤二:编写代码

云函数的入口是一个固定的方法。以 Node.js 为例:

// index.js
exports.main_handler = async (event, context) => {
    console.log('函数被调用了!');
    console.log('事件内容:', JSON.stringify(event));
    
    return {
        statusCode: 200,
        body: 'Hello, Serverless! 这是我的第一个云函数。'
    };
};

看到没?就是一个普通的异步函数。event 是触发事件的数据,context 是运行时上下文信息。返回什么,调用方就收到什么。

我的小习惯:开发阶段我会在函数开头打印 event 内容,方便调试。生产环境记得去掉,避免日志刷屏。

步骤三:部署与测试

点击「部署」按钮,等几秒钟。然后你会看到一个「测试」按钮。点它!

平台会弹出一个测试模板,你可以自定义输入参数。比如传个 JSON:

{
    "name": "小明",
    "action": "greet"
}

点击运行,右侧会显示执行结果和日志。我第一次看到这个界面时,心里想的是:「就这?这么简单?」——是的,就这么简单。

云函数的生命周期

这部分我建议你认真看,很多坑都出在这里。

一个云函数从创建到销毁,经历这几个阶段:

阶段 说明 触发时机
初始化 加载代码、建立数据库连接、初始化 SDK 第一次调用或冷启动时
运行 执行你的 handler 函数 每次事件触发
冻结 函数空闲一段时间后,平台暂停实例 无请求持续数分钟(各平台不同)
销毁 实例被彻底回收 长时间无请求或版本更新

这里有个关键概念:冷启动 vs 热启动

  • 冷启动:函数从「初始化」阶段开始,需要加载依赖、建立连接,耗时较长(几百毫秒到几秒)
  • 热启动:函数实例还在,直接执行 handler,耗时极短(几毫秒)

我曾经踩过的坑:有一次线上服务突然变慢,排查半天发现是数据库连接在每次冷启动时都重新创建,导致响应时间从 50ms 飙升到 2s。解决方案是把连接池放在 handler 外面,利用实例复用。

正确的做法是这样的:

// 放在 handler 外面,只在初始化时执行一次
const db = createConnectionPool({
    host: 'xxx',
    max: 10
});

exports.main_handler = async (event, context) => {
    // 这里直接使用 db,不需要重新连接
    const result = await db.query('SELECT * FROM users');
    return result;
};

事件模型:云函数的灵魂

云函数不是自己主动运行的,它是「被叫醒」的。谁叫醒它?事件。

我习惯把事件模型理解成一个「消息总线」:各种服务往总线上发消息,云函数订阅感兴趣的消息,收到后就执行。

常见的事件源

事件源 触发场景 典型用途
HTTP 请求 用户访问 API 网关 RESTful API、Webhook
对象存储 文件上传/删除 图片处理、视频转码
定时任务 Cron 表达式触发 数据备份、报表生成
消息队列 队列中有新消息 异步任务、削峰填谷
数据库变更 数据增删改 数据同步、缓存更新

举个例子:用户上传头像到对象存储,触发云函数,云函数自动生成缩略图,然后保存到另一个目录。整个过程不需要你写任何轮询代码。

事件模型的核心优势:解耦。上传服务和图片处理服务完全独立,各自可以独立升级、独立扩缩容。你想想看,传统架构里要实现这个,得写多少胶水代码?

事件的结构

每个事件源发来的事件格式略有不同,但大体结构类似:

{
    "requestId": "abc-123",
    "source": "apigw",        // 事件来源
    "type": "HTTP",           // 事件类型
    "time": "2024-01-15T10:00:00Z",
    "data": {
        "path": "/users",
        "method": "POST",
        "body": {"name": "小明"},
        "headers": {
            "Content-Type": "application/json"
        }
    }
}

你的函数需要根据 sourcetype 来判断如何处理。我一般会在函数开头写一个简单的路由:

exports.main_handler = async (event, context) => {
    const { source, type, data } = event;
    
    if (source === 'apigw' && type === 'HTTP') {
        return handleHttpRequest(data);
    }
    
    if (source === 'cos' && type === 'ObjectCreated') {
        return handleFileUpload(data);
    }
    
    return { error: '未知事件类型' };
};

小结

这一章我们聊了云函数的核心概念:它是什么、怎么创建、生命周期怎么走、事件模型怎么玩。说白了,云函数就是「把后端逻辑拆成一个个独立的小单元,让事件来驱动它们」。

我个人觉得,理解事件模型比理解语法更重要。因为语法可以查文档,但架构思维需要慢慢培养。下一章我们会深入云函数的进阶用法,包括环境变量、日志、监控这些生产环境必备的能力。

嗯,先消化这些。有问题随时翻翻这一章,或者动手写个函数试试。实践出真知嘛。