1. 免费服务器这件事,先把账算明白再动手
聊"服务器免费"这个话题,我见过太多人第一反应是去找一个"永久免费"的机器,结果折腾两周,要么被限额卡死,要么到期扣了一笔说不清的钱。免费服务器的本质不是零成本,而是成本被转移到了别的地方——时间、稳定性、流量额度或者数据迁移的麻烦上。我长期在自己项目和团队的小工具上使用各种免费形态,从云厂商的体验额度到家里旧笔记本自建,踩过的坑比用过的方案还多,这篇就把五种主流形态一条条拆开,顺带讲清楚"从免费额度到自建内网穿透"这条路上哪些地方最容易翻车。
先给个结论性质的前提:免费方案能不能用,取决于你的服务是"有人随时访问"还是"我偶尔用一下"。前者需要稳定性和可用性承诺,免费资源基本给不了;后者完全可以靠免费额度、Serverless 甚至家里的旧设备撑住。这个判断做错了,后面所有的选型都是白费力气。
标题里"内网穿透"这四个字值得单独说一句:它指的是把处于内网环境的设备(家里的 NAS、开发机、办公室的小主机)通过一条隧道暴露到公网访问,是很常规的网络工程做法。本文讨论的自建方案,前提都是只访问你自己有管理权限的设备和数据,并且遵守所在网络环境与服务提供商的使用规则,这一点在动手前就要摆正。
1.1 "免费"的三种成本结构,先分清你付的是哪种
我习惯把免费方案按成本转移方式分成三类。第一类是额度型免费:厂商给你一定量的资源(几个月的实例、每月若干次函数调用、若干 GB 流量),超额或到期就按量计费。这类方案的风险点在于"到期"和"超出",钱是从你没想到的缝隙里流走的,比如快照存储、公网出流量、日志留存。第二类是限制型免费:资源不要钱,但限制死规格,比如容器闲置后休眠、函数单次执行最长若干秒、静态站点单文件大小上限。这类方案不烧钱,烧的是你的耐心和架构设计的自由度。第三类是资源置换型免费:你用自己的硬件、电费、宽带上行带宽去换一台"服务器",典型就是自建加内网穿透。它看起来零现金支出,实际上电费、硬件折旧、运维时间都是成本,而且家宽的上行带宽往往只有下行的十分之一,这是很多人做完才发现最难受的地方。
把这三类对上自己的需求,选型基本就清晰了:对外提供的展示类页面走第二类,内部工具、定时任务走第一类,需要长期跑、数据量大、访问者只有自己或小团队的服务走第三类。下面五种形态就是按这个逻辑展开的。
1.2 一个反向的判断:先想迁移,再想免费
我在早期犯过一个很典型的错误:贪图某个平台的免费额度,把数据库和应用都堆在上面,连备份都没做,到期那天才发现导出数据要额外开一台机器,重新部署花了一整个周末。从那以后我形成了一个习惯——任何免费方案在启用前,先写好"退出路径"。
退出路径要回答四个问题:数据存在哪、怎么导出、导出后能不能在别处跑起来、切换需要多久。如果这四个问题有一个答不上来,这个免费方案就不该承载你的核心数据。具体做法很朴素:应用尽量容器化,配置全部写成文件放进版本管理,数据不要放在实例本地盘,定期导出一份到对象存储或者自己的机器上。免费额度那种几个月的方案,我在到期前两周就开始做迁移演练,DNS 记录的 TTL 提前调到 60 秒,切换当天基本能做到无感。这些动作看着琐碎,但真出事的时候能救命。
2. 形态一:云厂商的免费额度与新用户体验资源
这是大多数人最先接触到的形态。主流云平台会给新账号一段时间的体验资源(通常是轻量规格的实例加一定量的流量),或者提供长期存在的"免费层"(固定小规格实例、若干 GB 对象存储、有限的 CDN 流量)。它最大的优点是开箱即用、生态完整:有控制台、有镜像、有安全组、有监控,装个环境跑个 Demo 十几分钟的事。
它的边界也非常明确。规格低:免费实例一般是 1 核 1G 或者 2 核 2G 起步,跑个 Nginx 加轻量后端没问题,跑数据库加中间件就吃力了。时长久:体验资源多是 3 个月到 1 年,永久免费层通常只针对极小规格和特定地域。流量不含或者很少:这是最容易忽略的一点,很多方案给了机器却不给带宽,公网出流量单独计价,一个小博客被爬虫刷一轮,账单就不好看了。
2.1 免费额度里最容易被忽略的四项计费点
我把这些年被扣过钱的地方列成表,你对着自己的控制台逐项确认一遍,能省掉不少意外支出。
| 计费项 | 典型触发场景 | 应对做法 |
|---|---|---|
| 公网出流量 | 静态资源被外链、爬虫抓取、视频直出 | 图片走对象存储加 CDN,接口加限流 |
| 磁盘快照 | 手动或自动备份累积,从不清理 | 设置保留策略,定期删旧快照 |
| 公网 IP 与带宽 | 实例释放后 IP 未解绑仍占资源 | 释放实例时同步释放弹性 IP |
| 日志与监控存储 | 默认全量采集且长期保留 | 缩短保留天数,只留错误级别 |
还有一个隐形项是自动续费。绑定支付方式之后,很多平台在你开通时默认勾选自动续费,体验期一过直接按原价扣。我的做法是开通当天就去账单页面把自动续费关掉,同时设一个预算告警,阈值设在免费额度的一点二倍左右,一旦超出立刻能收到通知。
2.2 到期前两周该做的迁移动作清单
免费额度型方案最怕的不是不够用,而是"到期那天下不来台"。我给自己定的流程是这样:到期前 14 天,把实例上跑的东西全部梳理一遍,标记出哪些是"必须在",哪些是"顺手装的"。然后在新环境把"必须在"的部分重新部署一遍,这个过程会暴露出所有硬编码的路径、写死的 IP、藏在本地文件里的配置。到期前 7 天,把数据同步一次,验证新环境能正常读写。到期前 1 天,把 DNS 或者域名解析切过去,观察一轮错误日志。
注意:迁移演练一定要真的切一次流量,哪怕只有十分钟。只在本地跑通不算验证,DNS 缓存、证书链、防火墙规则这些只有在真实流量下才会暴露问题。
这套流程配合容器化用起来最省心:应用打成镜像,配置走环境变量,数据放外部存储,新环境拉起来就能跑。反过来,如果你在免费实例上手敲了三个月的环境,迁移就是一场灾难,这也是我建议哪怕只是玩票也把部署过程脚本化的原因。
3. 形态二:Serverless 与函数计算的免费调用额度
函数计算这类产品的免费额度通常按调用次数、执行时长(GB·秒)和出网流量计算,每月给一个相当宽裕的基础量。对低频、突发、事件驱动的负载来说,这是性价比最高的形态——一个每天被调用几百次的 Webhook 接收端,或者一个每小时跑一次的定时任务,放在函数上几乎是零成本,还省掉了打补丁、盯监控的功夫。
它的适用边界需要说清楚。常驻长连接不适合:WebSocket、长轮询这类场景在函数上很难做,即使勉强做,成本模型也会崩。重计算不适合:单次执行有超时上限,大文件转码、大数据量批处理容易被腰斩。需要本地磁盘的不适合:函数实例的临时目录不保证持久,写进去的东西下次调用就没了。需要固定出口 IP 的不适合:出网地址通常是共享池,对接一些有白名单要求的第三方服务会卡住。
3.1 冷启动、并发与超时:三个必须提前验证的指标
冷启动是函数计算绕不开的体验问题。闲置一段时间后第一次调用,平台要重新拉起运行环境,延迟可能从几毫秒变成几百毫秒甚至一两秒。我的处理方式是:对延迟敏感的接口做轻量预热,把依赖包压到最小(只装真正用到的库,别把整个数据处理框架拖进去),初始化逻辑放在函数入口外做复用。
并发限制也很关键。免费额度的并发上限通常不高,一旦有突发流量,超出部分会被限流或者排队。这时候要做的不是加大额度,而是在入口处限流并给出明确的降级响应,让调用方知道发生了什么,而不是拖到超时。
超时上限决定了你的业务能不能落在这上面。做批量任务时我会把工作拆成小片,每片控制在超时上限的三分之一以内,用队列串起来,而不是在一个函数里跑几十分钟。这样做还有一个好处:失败重试的粒度更细,不会因为一片出错整批重来。
3.2 出网流量与日志,账单从这两个口子漏
函数计算的调用次数通常不是问题,出网流量和日志存储才是。返回给客户端的大响应、调用外部 API 的流量,都算在出网里。我见过一个接口返回了几 MB 的 JSON,调用量一大,流量费就上去了。解决办法很直接:接口做分页、压缩响应、大文件走对象存储加签名链接。
日志方面,默认配置往往是全量采集并长期保留,调用量上来之后这块的存储成本会悄悄超过计算本身。我一般会把日志级别调到只保留 warn 和 error,保留期设成 7 天,需要排查问题时再临时打开 debug。这个习惯在小项目上体现不出价值,项目一上量就很明显。
4. 形态三:静态托管与边缘分发的免费层
如果你的"服务器"其实只需要对外提供一堆静态文件——文档站、产品介绍页、前端打包产物、图片库——那么静态托管加边缘分发是成本最低、稳定性最好的选择,很多平台提供相当慷慨的免费层,甚至对个人项目完全免费。
这个形态最大的优势是没有运维:不用装系统、不用配 Web 服务器、不用担心被打挂,边缘节点天然抗压。前端项目我把构建产物往上一扔,绑定域名就能访问,HTTPS 证书自动管理,这块省下来的时间可以全投到内容上。免费层的限制主要在构建次数、构建时长、单文件大小和流量上,个人站点基本够用。
4.1 单页应用上线后刷新 404,问题出在重写规则
这个问题几乎每个用静态托管部署单页应用的人都会遇到一次。前端路由是浏览器端处理的,用户直接访问/docs/getting-started时,托管平台会去文件系统里找这个路径,找不到就返回 404。解决方式是配置一条回退规则,把未匹配的请求统一指向入口文件。
以常见平台的重写配置示意为例(不同平台字段名有差异,按你用的平台文档改):
{ "rewrites": [ { "source": "/(.*)", "destination": "/index.html" } ] }配完之后还要注意缓存。入口文件不能长缓存,否则用户拿到旧版本会一直加载不存在的资源。我一般把入口设成no-cache,带哈希的静态资源设成一年,这样更新能立刻生效,静态资源又能充分利用缓存。
# 缓存策略示意 location = /index.html { add_header Cache-Control "no-cache"; } location ~* \.(js|css|woff2|png|jpg|svg)$ { add_header Cache-Control "public, max-age=31536000, immutable"; }4.2 构建超时与大文件:仓库里不该放什么
免费层的构建时长通常有限制,依赖装得太多、仓库里堆了大文件,构建就容易超时。我踩过一次坑:把一个几百 MB 的素材目录直接提交进了仓库,每次构建都在拉这些东西,构建时间从两分钟涨到八分钟,最后撞上限额失败。后来的做法是把素材放对象存储,仓库里只留压缩后的必要资源,并用.gitignore把构建产物和本地缓存挡掉。
还有一个细节是构建缓存。大多数平台支持依赖缓存,把锁文件(package-lock.json、poetry.lock之类)提交进去、不要随意删,能显著缩短构建时间。我在项目里把这一步写进了提交前检查,避免有人图省事把锁文件删了重新生成,导致构建变慢还引入版本漂移。
5. 形态四:免费容器托管与轻量应用平台
容器托管是介于"完整云主机"和"函数计算"之间的形态:你把应用打成镜像推上去,平台负责运行和扩缩容,免费层通常给有限的实例数、内存和月度运行时长。它的好处是部署体验统一——本地跑得起来的镜像,线上基本也能跑,不会出现"我电脑上没问题"的经典困境。
这个形态最关键的一个特性是休眠机制。为了控制资源占用,平台会在应用闲置一段时间后把实例停掉,下一次请求触发冷启动,用户看到的是几秒甚至十几秒的等待。对于个人工具、内部后台这类"我自己用"的场景完全可以接受;对于对外展示的门面页面,就要谨慎。我见过有人为了对抗休眠写定时请求去保活,这个做法要先看清楚平台的服务条款,很多平台明确不鼓励这类行为,被判定为滥用后账号受限,得不偿失。更稳妥的思路是接受休眠,把首屏做成静态页,把重逻辑放到唤醒之后。
5.1 容器文件系统是临时的,数据库必须外置
这是新手最容易踩的一脚:应用写了个 SQLite 文件放在容器目录里,跑了几天发现数据莫名其妙回滚了。原因是容器的文件系统在实例重启、重新调度之后会被重置,本地写入的东西不保证留存。
正确做法是把状态全部外置:数据库用托管服务或者自建在别处,文件上传走对象存储,会话用外部缓存或者干脆做成无状态加签名令牌。如果实在要用 SQLite,那就要挂载持久卷,并且确认平台提供了这个能力以及对应的容量限制。
| 数据类型 | 放在容器内 | 正确做法 |
|---|---|---|
| 用户上传文件 | 重启后丢失 | 对象存储加签名 URL |
| 数据库文件 | 调度后重置 | 托管数据库或外部实例 |
| 会话状态 | 多实例不一致 | 外部缓存或签名令牌 |
| 日志 | 随实例销毁 | 输出到标准输出由平台采集 |
5.2 月度运行时长与实例规格的换算
免费容器的额度通常按"实例数 × 运行小时"计算。假设免费层给的是每月 750 实例小时,跑一个实例可以全天候在线,跑两个实例就只剩半个月。多副本部署之前先算这笔账,否则月中就被限流。
内存配额也要留意。免费层一般给 256MB 到 512MB,Java 那类默认堆内存偏大的运行时容易直接 OOM。我的经验是:把堆内存上限显式设成容器限制的 70% 左右,留出元空间和系统开销;能用轻量运行时就不用重量级的,一个简单的 API 服务用 Go 或者 Node 写出来,镜像能压到几十 MB,启动也快。
6. 形态五:自建加内网穿透,把家里的机器变成"服务器"
前面四种都是租别人的资源,最后一种是拿自己的硬件换一台服务器。数据完全在自己手里、磁盘想多大就多大、想装什么装什么,代价是要自己解决"外面的网络怎么访问进来"这个问题——绝大多数家庭宽带没有固定的公网地址,即使有,直接暴露端口也不安全。内网穿透就是在这个背景下出现的:在公网找个有固定地址的中继节点,内网设备主动连出去建立一条隧道,外部访问中继节点时,流量被转发回内网设备。
整体架构其实很简单,三部分:内网服务(家里的 NAS、开发机、树莓派上的应用)、隧道客户端(跑在内网设备上,主动向外建立连接)、中继节点(有公网地址的机器,负责接收外部请求并转发)。有些方案还支持点对点打洞,即两端尝试直连,直连成功就不走中继,延迟和带宽都好得多,失败时再回落到中继。
6.1 打洞与中继的取舍:先看你的场景能不能直连
直连成功的条件是双方的网络环境允许(NAT 类型友好、没有严格的对称型限制)。打洞成功时,流量不经过中继,带宽只受两端上行带宽限制,延迟也低。但打洞不是百分百成功,尤其是移动网络、多层 NAT 环境,失败率不低。
中继模式则稳定得多,只要客户端能连上中继节点就能通,但代价有两个:流量绕路带来延迟,以及中继节点的带宽和流量成本。如果中继节点本身也是免费额度,那就要格外小心流量上限,一个视频流或者大量文件同步很容易把它打满。
我的实际选择是这样:文件同步、远程桌面这类对带宽敏感的场景优先尝试直连;设备管理页面、API 调用这类低频小流量的走中继完全够用。配置上通常可以同时启用两种模式,让工具自己协商,协商失败再强制走中继。
6.2 中继端的配置与加固,别让隧道变成后门
自建中继最怕的一件事是:隧道建好了,安全没做,全网扫描器几天就找上门。我见过有人把内网的管理后台直接映射到公网,密码还是默认的,结果被批量扫描的脚本拿下。下面这套配置和加固动作是我目前的标准做法。
# 中继端示意配置(字段名以你实际选用的工具为准) bind_addr = 0.0.0.0 bind_port = 7000 auth_token = 换成32位以上的随机串 max_ports_per_client = 5 log_level = infoauth_token一定要换成长随机串,所有客户端共用同一个 token,别用默认值。max_ports_per_client限制单客户端能映射的端口数,防止误配把一堆服务全暴露出去。
客户端配置示意:
# 内网端示意配置 server_addr = relay.example.net server_port = 7000 auth_token = 与中继端保持一致 [[proxies]] name = "nas-web" type = "tcp" local_ip = 127.0.0.1 local_port = 5000 remote_port = 15000关键点在于local_ip写127.0.0.1而不是0.0.0.0,让它只转发本机上的那个服务,避免把内网其他设备的端口也带出去。
中继机上的防火墙只放行必要端口:
uvicorn_placeholder=1 ufw default deny incoming ufw allow 22/tcp ufw allow 7000/tcp ufw allow 443/tcp ufw enable ufw status verbose客户端用 systemd 托管,保证断线自动重连:
[Unit] Description=tunnel client After=network-online.target [Service] ExecStart=/usr/local/bin/tunnel -c /etc/tunnel/client.ini Restart=always RestartSec=5 [Install] WantedBy=multi-user.target6.3 证书、域名与反向代理:把隧道藏在 443 后面
直接映射端口能用,但体验不好:地址带端口号、没有 HTTPS、各种客户端提示不安全。我的做法是在中继机上用 Nginx 做反向代理,把隧道映射出来的本地端口包一层,统一走 443,证书用自动签发工具管理。
server { listen 443 ssl; server_name nas.example.net; ssl_certificate /etc/letsencrypt/live/nas.example.net/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/nas.example.net/privkey.pem; client_max_body_size 200m; location / { proxy_pass http://127.0.0.1:15000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }证书签发时有个细节:如果中继机的 80 端口不方便对外开放,用 DNS 方式验证比 HTTP 方式更省事,尤其是给纯内网设备签证书的场景。另外把client_max_body_size显式设一下,默认 1MB 在传文件时会直接给你 413,我在这上面浪费过半小时。
注意:对外提供网站服务涉及域名与接入的相关手续,各地要求不同,本文不展开,请按你所在地的规定自行确认后再上线。
6.4 实测中最常遇到的四个问题
上行带宽是硬伤。家庭宽带的下行看着很爽,上行往往只有几十兆甚至更低。远程看个视频、传个大文件,瓶颈全在上行,这个没法靠配置优化解决,只能降低预期或者换方案。
地址会变。家庭宽带的公网地址可能定期变化,如果你用的是直连而不是中继,需要配合动态域名解析,客户端定时上报当前地址。中继模式不受影响,因为连接是内网主动发起的。
中继流量烧得快。中继节点的流量成本要盯着看,尤其是拿免费额度做中继的时候。我一般会在中继上做限速,并且把大流量服务单独拆出去走直连。
重连风暴。网络抖动时客户端可能疯狂重连,日志刷屏还占资源。RestartSec设个几秒、工具本身开启指数退避,能缓解不少。
6.5 内网设备本身的安全底线
隧道只是通道,设备本身的安全才是根。我这几年固定做几件事:禁用密码登录改用密钥、关掉不需要的服务、管理后台加一层基础认证、开启失败登录封禁。管理后台的默认密码是重灾区,很多设备出厂密码全网皆知,映射出去等于公开。
还有一条容易被忽略:审计。定期看一眼中继和设备的访问日志,有没有陌生的 IP 在扫端口、有没有异常时间的登录尝试。这一步花不了几分钟,但能提前发现很多问题。
7. 五种形态横向对比:按场景选,不要按"免费"选
写到这,五种形态的脾气基本都摸清了。我做了一张对照表,选型时直接对号入座比反复纠结有用得多。
| 形态 | 现金成本 | 稳定性 | 运维负担 | 最适合的场景 | 主要上限 |
|---|---|---|---|---|---|
| 云厂商免费额度 | 额度内为零 | 较高 | 中等 | 需要完整环境的学习与小型后端 | 时长、规格、流量 |
| Serverless 函数 | 额度内为零 | 高 | 低 | 低频接口、定时任务、事件处理 | 执行时长、并发、冷启动 |
| 静态托管加边缘 | 基本为零 | 很高 | 极低 | 文档站、前端产物、图片库 | 构建次数、单文件大小 |
| 免费容器托管 | 额度内为零 | 中等 | 低 | 个人工具、内部后台、Demo | 休眠、运行时长、内存 |
| 自建加内网穿透 | 电费与硬件 | 取决于自己 | 高 | 数据自主、大容量存储、长期运行 | 上行带宽、地址变动 |
选型时我的判断顺序是:先问访问频率,再问数据敏感度,最后问预算。访问频率低的走函数,纯静态的走托管,需要长期在线且数据要自己拿着的走自建,中间地带用免费容器兜底,实在需要一个完整环境就用云厂商额度过渡。
8. 踩坑清单:免费方案翻车的完整排查链路
这一节讲的是真出事时怎么查。我把最近一次"莫名扣费"的排查过程完整还原一遍,思路可以直接套用。
8.1 从账单异常到定位根因的六步链路
第一步,进账单页面按资源类型分组,不要按时间看总额,按类型才能看出是哪一类在涨。我那次发现扣费集中在"网络流量"和"存储"两项,计算资源反而是零。
第二步,把流量按时间段展开,找到突增的时间点。那次是凌晨三点开始持续上涨,这个时间点很说明问题——不是真实用户在访问。
第三步,翻访问日志。日志里能看到大量来自同一批地址的请求,抓的是同一个图片路径,明显是被批量抓取了。
第四步,确认是否配置了缓存和限流。检查后发现图片直接由实例出网,没走 CDN,也没有任何限流。
第五步,确认存储费用的来源。是快照——之前手动打的一次快照忘了删,一直按容量计费。
第六步,处置并加固:图片迁到对象存储加 CDN,实例侧加请求限流,删掉无用快照,设置预算告警和自动续费关闭。
整个过程花了不到一小时,但如果一开始就按这个顺序查,能省掉大量瞎猜。排查的核心是把"一笔总额"拆成"资源类型 → 时间段 → 请求来源 → 配置缺失"四层,一层层往下钻。
8.2 限速、限流、休眠:三个不写在显眼位置的隐形坑
免费方案的限制往往不体现在报错上,而是体现在"能用但很难受"。限速表现为带宽被压到很低,下载文件像蜗牛,测速才发现被限制了。限流表现为偶发的 429 或者超时,压力小的时候完全看不出来,一上量就爆。休眠表现为第一次访问特别慢,之后就正常,很容易被误判成代码性能问题。
识别方法:遇到"偶发但规律"的异常,先怀疑平台限制,而不是自己的代码。我在项目里会做一个小脚本,定时打点记录响应时间,连续跑几天,看看延迟分布的形态——如果存在明显的双峰(快的一批、慢的一批),基本就是冷启动或者限流在作怪。
8.3 暴露面管理:免费资源被扫描是常态
公网上的任何地址,只要开放了端口,几小时内就会开始收到扫描请求,这跟你的服务大小无关。免费方案尤其要注意,因为很多默认配置是"能用就行",安全设置基本靠用户自己。
我的固定动作有这么几条:管理类端口一律不直接对外,走隧道加认证;SSH 禁用密码登录,只留密钥;数据库、缓存这类服务绝不放公网;对失败登录做封禁;定期看看有没有多余的服务在监听。
# 快速看一眼当前对外监听的端口 ss -tulnp | grep -v 127.0.0.1 # 检查失败登录尝试 lastb | head -20这两条命令我一般在新机器上线当天就跑一遍,确认没有意外暴露的服务。ss那条会把只监听本机的行过滤掉,剩下的都是对外的,逐个确认用途,说不清楚的一律关掉。
9. 一点个人体会
这五种形态我全都用过,而且经常是混着用:门面页面放静态托管,定时任务丢函数,开发机上跑的调试服务和家里的存储走自建隧道,需要一个完整环境做压力测试的时候临时开一台免费实例,测完就释放。这套组合下来的现金支出几乎为零,代价是我得记住每个方案的额度和到期时间,还得接受"偶尔会慢一下"。
如果只让我给一条建议,那就是别把免费当成长期方案,把它当成过渡和验证。真正决定你要不要迁移的,不是钱,而是某个凌晨服务挂掉时你有没有能力在两小时内恢复。免费方案里能做到这一点的,通常只有你已经把部署脚本化、数据外部化、退出路径写好的那些。剩下的,玩得开心就好,别放重要东西。