Serverless(无服务器架构)是近年来云计算的热门方向。

它让开发者不用关心服务器,只需要写代码就能部署应用。听起来很美好,但很多人对Serverless的了解还停留在概念层面,不知道怎么在实际项目中落地。

我之前也是这样,看了很多文章,觉得Serverless很厉害,但真要在项目里用的时候,又不知道从何下手。后来在几个项目里尝试了Serverless,踩了不少坑,也积累了一些经验。

本文通过几个真实的落地案例,带你从零开始学习Serverless,包括它的核心概念、适用场景、优缺点、以及具体的落地实践。

一、Serverless是什么

先说说Serverless到底是什么。

Serverless直译是"无服务器",但不是真的没有服务器,而是开发者不用关心服务器。服务器的管理、运维、扩容,都由云厂商负责,开发者只需要写代码。

Serverless主要包含两部分:

  1. FaaS(Function as a Service,函数即服务):把代码写成函数,按事件触发,按调用次数计费。比如AWS Lambda、阿里云函数计算、腾讯云SCF。
  2. BaaS(Backend as a Service,后端即服务):把后端能力做成服务,直接调用,不用自己写后端。比如对象存储、数据库、消息队列、身份认证等。

Serverless的核心特点:

  • 免运维:不用管服务器,云厂商帮你搞定
  • 弹性伸缩:自动扩容,流量来了自动加实例,流量没了自动缩到零
  • 按需付费:按调用次数和运行时间计费,没有调用不花钱
  • 事件驱动:函数由事件触发,比如HTTP请求、消息、定时任务、文件上传

二、Serverless的适用场景

Serverless不是万能的,它有自己的适用场景。

适合的场景:

  1. 事件驱动型应用:比如图片处理、文件转换、消息处理
  2. API后端:比如小程序后端、移动App后端、Webhook
  3. 定时任务:比如定时爬虫、定时报表、数据备份
  4. 流量波动大的应用:比如活动页面、秒杀系统、促销接口
  5. 物联网后端:比如设备数据采集、消息转发
  6. 数据处理:比如ETL、日志分析、数据清洗

不适合的场景:

  1. 长时间运行的任务:函数有执行时间限制(一般最多15分钟),不适合长时间任务
  2. 高并发、低延迟的核心服务:冷启动会影响延迟
  3. 有状态的服务:函数是无状态的,不适合需要长连接、会话保持的场景
  4. 复杂的单体应用:Serverless适合微服务架构,不适合大而全的单体应用
  5. 对启动延迟极度敏感的场景:冷启动可能需要几百毫秒到几秒

三、Serverless的优缺点

说说Serverless的优缺点。

优点:

  1. 成本低:没有调用不花钱,适合流量小、波动大的应用
  2. 免运维:不用管服务器,专注写代码
  3. 弹性好:自动扩容,不用担心流量突增
  4. 开发快:很多后端能力可以直接用BaaS服务,不用自己写
  5. 高可用:云厂商保证多可用区部署,可用性高

缺点:

  1. 冷启动:函数长时间不调用,再次调用时需要启动,有延迟
  2. 调试困难:本地调试和云端环境有差异,调试不方便
  3. 厂商锁定:不同云厂商的Serverless实现不一样,迁移成本高
  4. 执行时间限制:函数最多跑15分钟,不适合长任务
  5. 监控和排错复杂:分布式调用链长,排错困难
  6. 不适合有状态服务:函数无状态,需要借助外部存储

四、落地案例一:图片自动处理

第一个案例,是图片自动处理。

场景: 用户上传图片后,自动生成不同尺寸的缩略图,压缩图片大小,加水印。

传统方案: 写一个后端服务,监听上传事件,处理图片。需要自己维护服务器,处理高峰期的并发。

Serverless方案:

  • 用户上传图片到对象存储(OSS)
  • OSS触发函数计算(FaaS)
  • 函数读取图片,生成缩略图、压缩、加水印
  • 处理后的图片存回OSS
  • 通知用户处理完成

为什么用Serverless:

  • 图片处理是事件驱动的,适合FaaS
  • 上传量波动大,Serverless自动伸缩
  • 不用维护服务器,成本低
  • 处理时间短(几秒),在函数执行时间限制内

技术栈:

  • 阿里云OSS + 函数计算
  • 腾讯云COS + SCF
  • AWS S3 + Lambda

关键代码(伪代码):

def handler(event, context):
    # 获取上传的图片
    bucket = event['bucket']
    key = event['key']
    image = download_image(bucket, key)
    
    # 生成缩略图
    thumbnail = resize(image, 200, 200)
    upload_image(bucket, 'thumb/' + key, thumbnail)
    
    # 压缩图片
    compressed = compress(image, quality=80)
    upload_image(bucket, 'compressed/' + key, compressed)
    
    # 加水印
    watermarked = add_watermark(image, '我的网站')
    upload_image(bucket, 'watermarked/' + key, watermarked)
    
    return 'success'

踩过的坑:

  1. 函数内存要设够,图片处理比较吃内存,建议设512MB以上
  2. 大图片处理可能超时,要设置合理的超时时间
  3. 处理失败要重试,用消息队列做缓冲
  4. 注意图片格式的兼容性

五、落地案例二:小程序后端

第二个案例,是微信小程序的后端。

场景: 一个小程序,需要用户登录、数据存储、API接口、消息推送。

传统方案: 买服务器,搭后端框架,写接口,部署运维。

Serverless方案:

  • 用云开发(微信云开发 / 阿里云小程序云)
  • 用户登录:用云开发的身份认证
  • 数据存储:用云数据库
  • API接口:用云函数
  • 文件存储:用云存储
  • 消息推送:用云开发的消息推送

为什么用Serverless:

  • 小程序流量一般不大,Serverless成本低
  • 不用维护服务器,个人开发者也能做
  • 开发快,很多能力开箱即用
  • 自动扩容,不用担心活动期间流量突增

技术栈:

  • 微信云开发(最方便,和小程序集成最好)
  • 阿里云小程序云
  • 腾讯云CloudBase

关键代码(云函数):

// 获取用户信息的云函数
exports.main = async (event, context) => {
  const { OPENID } = cloud.getWXContext()
  
  // 从数据库查询用户信息
  const user = await db.collection('users').doc(OPENID).get()
  
  if (!user.data) {
    // 新用户,创建记录
    await db.collection('users').add({
      _id: OPENID,
      nickName: event.nickName,
      avatarUrl: event.avatarUrl,
      createTime: new Date()
    })
  }
  
  return { success: true, user: user.data }
}

踩过的坑:

  1. 云函数的冷启动,第一次调用会慢一些,可以用定时触发器预热
  2. 云数据库的查询有配额限制,大查询要分页
  3. 云函数之间的调用,要注意超时和重试
  4. 本地调试要用云开发的CLI工具,模拟云端环境

六、落地案例三:定时爬虫和数据报表

第三个案例,是定时爬虫和数据报表。

场景: 每天定时爬取几个网站的数据,清洗后存入数据库,生成日报,推送到邮箱或钉钉。

传统方案: 买服务器,写爬虫脚本,用crontab定时执行,维护数据库和邮件服务。

Serverless方案:

  • 定时触发器(比如每天早上8点)触发函数
  • 函数执行爬虫,抓取数据
  • 数据清洗后存入云数据库
  • 生成报表,用邮件服务或钉钉机器人推送
  • 函数执行完毕,自动释放资源

为什么用Serverless:

  • 定时任务,每天只跑一次,Serverless按需付费,成本极低
  • 不用维护服务器,不用管crontab
  • 爬虫失败可以自动重试
  • 报表推送可以直接用云服务

技术栈:

  • 阿里云函数计算 + 定时触发器 + RDS + 邮件推送
  • 腾讯云SCF + 定时触发器 + 云数据库 + 邮件推送
  • AWS Lambda + CloudWatch Events + RDS + SES

关键代码(伪代码):

def handler(event, context):
    # 爬取数据
    data1 = crawl_website_a()
    data2 = crawl_website_b()
    
    # 数据清洗
    cleaned1 = clean_data(data1)
    cleaned2 = clean_data(data2)
    
    # 存入数据库
    save_to_db(cleaned1)
    save_to_db(cleaned2)
    
    # 生成报表
    report = generate_report(cleaned1, cleaned2)
    
    # 推送报表
    send_email(report)
    send_dingtalk(report)
    
    return 'success'

踩过的坑:

  1. 爬虫可能被目标网站封IP,需要用代理IP池
  2. 爬取数据量大时,函数执行时间可能不够,可以拆分成多个函数
  3. 反爬机制要处理,比如设置User-Agent、请求间隔
  4. 数据存储要注意去重,避免重复数据

七、落地案例四:Webhook和API网关

第四个案例,是Webhook和API网关。

场景: 接收第三方服务的Webhook(比如GitHub、支付回调、消息推送),做处理后转发到内部系统。

传统方案: 搭一个API服务,暴露公网地址,接收Webhook,处理后转发。需要维护服务器、域名、HTTPS证书。

Serverless方案:

  • 用API网关暴露HTTP接口
  • API网关触发函数计算
  • 函数验证Webhook签名,处理数据
  • 转发到内部系统或存入消息队列
  • 返回响应

为什么用Serverless:

  • Webhook调用量不确定,Serverless自动伸缩
  • 不用维护API服务器和HTTPS证书
  • API网关自带限流、鉴权、日志
  • 函数处理完就释放,成本低

技术栈:

  • 阿里云API网关 + 函数计算
  • 腾讯云API网关 + SCF
  • AWS API Gateway + Lambda

关键代码(伪代码):

def handler(event, context):
    # 验证Webhook签名
    signature = event['headers'].get('X-Signature')
    if not verify_signature(event['body'], signature):
        return {'statusCode': 403, 'body': 'Invalid signature'}
    
    # 处理Webhook数据
    payload = json.loads(event['body'])
    result = process_webhook(payload)
    
    # 转发到内部系统
    forward_to_internal(result)
    
    return {'statusCode': 200, 'body': 'success'}

踩过的坑:

  1. Webhook的签名验证要做好,防止伪造请求
  2. 处理要快,第三方服务有超时限制,一般5-10秒
  3. 处理失败要返回正确的状态码,让第三方重试
  4. 幂等性要处理好,Webhook可能重复推送

八、Serverless的最佳实践

通过这几个案例,总结一些Serverless的最佳实践。

1. 函数设计要小而专

每个函数只做一件事,不要写大而全的函数。函数越小,启动越快,调试越容易。

2. 处理好冷启动

  • 选择启动快的语言(Node.js、Python比Java、C#启动快)
  • 减少函数的依赖包大小
  • 用定时触发器预热函数
  • 对延迟敏感的接口,用预留实例(Provisioned Concurrency)

3. 做好错误处理和重试

  • 函数内部要捕获异常,返回正确的错误信息
  • 用消息队列做异步处理,保证可靠性
  • 设置合理的重试策略
  • 用死信队列处理失败的消息

4. 无状态设计

函数是无状态的,不要在函数内存里存数据。状态要存在外部存储(数据库、缓存、对象存储)里。

5. 监控和日志

  • 开启详细的日志记录
  • 用云厂商的监控服务,监控调用次数、延迟、错误率
  • 设置告警,出问题及时发现
  • 用分布式追踪工具,排查调用链问题

6. 安全

  • 函数的权限要最小化,只给需要的权限
  • 敏感信息(密钥、密码)用环境变量或密钥管理服务
  • API接口要做鉴权和限流
  • 输入验证要做好,防止注入攻击

7. 成本控制

  • 合理设置函数内存,内存越大CPU越强,有时候大内存反而更便宜(因为执行时间短)
  • 用日志分析,找出调用量大的函数优化
  • 删除不用的函数和资源
  • 长期运行的任务,考虑用容器或虚拟机,可能更便宜

九、常见问题

说说常见的问题。

Q1:Serverless能省多少钱?

A:取决于使用场景。流量小、波动大的应用,能省很多钱(可能省80%以上)。流量大、稳定的应用,可能比服务器还贵。要根据实际情况计算。

Q2:冷启动怎么解决?

A:几个方法:用启动快的语言、减少依赖、定时预热、用预留实例。对延迟不敏感的场景,冷启动影响不大。

Q3:Serverless怎么调试?

A:用云厂商的CLI工具,本地模拟云端环境。或者用云端调试,直接在云端跑函数,看日志。

Q4:厂商锁定怎么办?

A:几个策略:用Serverless Framework等开源框架,抽象厂商差异;函数逻辑和厂商API解耦;选择支持标准的厂商。但完全避免锁定很难,要权衡。

Q5:Serverless适合生产环境吗?

A:适合。很多大公司已经在生产环境大规模使用Serverless。但要根据场景选择,不是所有应用都适合。

十、学习路径

如果你是Serverless新手,建议按这个路径学习:

  1. 基础概念:了解Serverless、FaaS、BaaS的概念,看官方文档
  2. 动手实践:注册一个云账号,写第一个Hello World函数
  3. 做小项目:从简单的项目开始,比如图片处理、定时任务
  4. 学习最佳实践:看官方的最佳实践文档,学习别人的经验
  5. 做复杂项目:尝试用Serverless做一个完整的应用,比如小程序后端
  6. 深入研究:学习性能优化、成本优化、安全、监控等高级主题

十一、推荐资源

学习Serverless,推荐这些资源:

  1. 官方文档:阿里云函数计算、腾讯云SCF、AWS Lambda的官方文档,最权威
  2. Serverless Framework:开源的Serverless框架,支持多云
  3. 《Serverless架构》:不错的入门书
  4. Serverless中文社区:国内的社区,有很多中文资料
  5. 各大云厂商的博客和公开课:有很多实战案例

十二、写在最后

Serverless是云计算的一个重要方向,它让开发者从服务器的运维中解放出来,专注于业务逻辑。

但Serverless不是银弹,它有自己的适用场景和局限。在选择Serverless之前,要了解你的业务场景,评估它的优缺点。

本文通过四个落地案例(图片处理、小程序后端、定时爬虫、Webhook),介绍了Serverless的实际应用。这些案例都是我在实际项目中用过的,希望能帮你快速入门。

2022年了,Serverless已经越来越成熟,越来越多的公司在生产环境中使用它。如果你还没试过,建议动手做一个小项目,感受一下Serverless的魅力。

最后,用一句话总结:"Serverless不是没有服务器,而是让你不用关心服务器。选对场景,它能让你事半功倍。"

祝大家的Serverless之旅顺利。