浅谈技术探索与实践:一个外包老兵的血泪踩坑史

后端说没问题
2025-12-19 02:19
阅读 715

作者注:本文由一位在某知名(自封)外包公司摸爬滚打4年、Vim不离手、IDE常年吃灰、正偷偷改简历准备跳槽的老兵撰写。如你所见,我既不是架构师,也不是CTO,只是一个被产品经理追着改需求、被测试怼着修Bug、被运维甩锅说“你们代码有问题”的普通后端仔。


去年双11前两周,我司接了个“高大上”的项目:给一家做数字藏品的客户搭一套前后端系统,要求支持Web3登录、NFT铸造、链上查询……关键词一串:前端区块链后端资源管理——听起来像是要造火箭,但预算只够买个窜天猴。

最离谱的是,客户 PM 在需求评审会上轻描淡写地说:“我们希望下周三上线 Demo,能演示就行。”
我当时差点把 Vim 的 :q! 按成 rm -rf /*

但没办法,外包狗的命,就是“需求来了就得上”。于是,这场横跨前端、后端、区块链的技术探索,就此拉开序幕。


起因:被逼着学 Web3,只为保住 KPI

事情是这样的。我们团队常年维护几个政府类 OA 系统,技术栈稳定得像出土文物:jQuery + Spring Boot 2.3 + MySQL 5.7。突然有一天,老板拍板接了这个 Web3 项目,理由是“布局新赛道”。

我作为团队里唯一一个 GitHub Star 过三位数(其实是 fork 了太多仓库)、还折腾过 Ethereum 私有链的人,理所当然被推上了前线。

任务清单

  • 前端:用户钱包连接(MetaMask)、NFT 展示、铸造按钮
  • 后端:接收铸造请求、生成元数据、调用合约
  • 区块链:部署智能合约、处理交易、监听事件
  • 资源:图片/视频等媒体文件存储(还得省点钱)

听起来很酷,对吧?但现实是:我们连 Infura 都没注册过


前端:从“连接钱包”开始崩溃

前端同事小张是个 React 老手,但 Web3 完全新手。他第一天下班前兴冲冲跑来:“哥,我用 web3-react 搞定钱包连接了!”
结果第二天早上,测试发现:在 Safari 上完全打不开 MetaMask

查了一圈才知道,iOS 的 WebView 对 window.ethereum 支持极差,必须用 WalletConnect 中转。更惨的是,有些安卓机连 WalletConnect 的二维码都扫不出来——因为被微信内置浏览器拦截了。

我们被迫加了一堆 UA 判断和降级提示:

// 别笑,这是真实代码
const isMobile = /iPhone|Android/i.test(navigator.userAgent);
const isInWechat = /MicroMessenger/i.test(navigator.userAgent);

if (isInWechat) {
  alert("请在 Safari 或 Chrome 中打开本页面");
  return;
}

if (isMobile && !window.ethereum) {
  // 引导使用 WalletConnect
  connectWalletConnect();
} else {
  // 尝试直接注入
  connectInjected();
}

教训:Web3 的“去中心化”口号很美,但用户体验支离破碎。前端不仅要写业务逻辑,还得当“设备兼容性考古学家”。


区块链:Gas 费烧得我心慌

后端这边,我负责对接智能合约。客户坚持要用 Ethereum 主网(“显得专业”),但又不肯付 Gas 费补贴。

第一次测试铸造,一笔交易花了 0.03 ETH(约 60 刀)。我当场瞳孔地震——这还没算失败重试的成本!

赶紧跟客户沟通,换成 Polygon。便宜是便宜了(0.001 刀/笔),但问题来了:Infura 免费额度每天只有 10 万次请求,而我们的 Demo 要支持 50 人同时操作。

结果 Demo 当天,Infura 返回 429 Too Many Requests,整个链上功能瘫痪。运维老李在 Slack 里疯狂@我:“是不是你代码死循环了?”

后来我临时切到 Alchemy,结果 Alchemy 的 WebSocket 事件推送延迟高达 30 秒——用户点了“铸造”,页面卡住,以为失败了,狂点十次,最后链上出现十个 NFT。

血泪建议

  • 开发阶段务必用本地 Hardhat 节点
  • 生产环境至少准备两个 RPC 提供商(Infura + Alchemy 双活)
  • 所有链上操作加防重(比如前端按钮置灰 + 后端幂等校验)

后端:别让链上拖垮你的 API

很多人以为后端在 Web3 项目里只是“传话筒”:收请求 → 调合约 → 返回 hash。
天真!

真实场景是:用户点击铸造后,我们不仅要发交易,还要生成元数据(JSON)上传图片到 IPFS更新数据库状态推送通知……

最坑的一次:IPFS 上传超时(国内网络你懂的),导致整个 HTTP 请求 hang 住 2 分钟,Nginx 直接 504。用户刷新十次,后端开了十个线程同时上传同一张图,IPFS 节点直接拒了。

后来我重构了流程:

  1. 用户请求进来,立刻返回 status: "pending", txHash: null
  2. 后台异步任务处理:生成元数据 → 上传 IPFS → 发送交易
  3. 前端轮询 /api/nft/{id} 查状态

关键代码(Spring Boot + Web3j):

// 铸造入口:快速响应
@PostMapping("/mint")
public ResponseEntity<MintResponse> mint(@RequestBody MintRequest req) {
    String nftId = UUID.randomUUID().toString();
    mintService.asyncMint(nftId, req); // 异步入队
    return ResponseEntity.accepted()
        .body(new MintResponse(nftId, "pending"));
}

// 异步任务
@Async
public void asyncMint(String nftId, MintRequest req) {
    try {
        // 1. 生成元数据 JSON
        String metadataUri = ipfsService.uploadMetadata(req.getName(), req.getImageUrl());
        
        // 2. 调用合约
        TransactionReceipt receipt = contract.mint(metadataUri).send();
        
        // 3. 更新 DB
        nftRepo.updateStatus(nftId, "success", receipt.getTransactionHash());
    } catch (Exception e) {
        log.error("Mint failed", e);
        nftRepo.updateStatus(nftId, "failed", null);
    }
}

重点永远不要让区块链的不确定性阻塞你的 HTTP 接口。链上慢、失败、回滚都是常态,你的系统必须优雅降级。


资源管理:IPFS 不是银弹

说到资源,客户一开始要求“所有图片必须上 IPFS,去中心化!”。
我点头答应,心里却在滴血。

为什么?因为:

  • IPFS 上传速度慢(尤其国内)
  • 内容一旦上传无法删除(GDPR 怎么办?)
  • 如果没人 pin,内容会消失(“去中心化”的黑暗面)

我们试过 Pinata,免费版每月 1GB,Demo 一天就超了。付费?客户说“先看看效果”。

最后妥协方案:

  • 热数据(用户头像、NFT 缩略图)→ 存阿里云 OSS(带 CDN)
  • 冷数据(NFT 元数据 JSON)→ 上传 IPFS + Pinata 固定
  • 数据库里同时存 ipfs://xxxhttps://oss.xxx.com/xxx

这样既满足“链上引用 IPFS URI”的合规要求,又保证前端加载速度。

附上资源存储对比表:

方案 优点 缺点 适用场景
IPFS 去中心化、不可篡改 上传慢、可能丢失、难调试 元数据、法律存证
阿里云 OSS 快、稳定、便宜 中心化 图片、视频、静态资源
Arweave 永久存储 贵($3/GB)、生态小 长期归档

技术选型:稳定压倒一切

作为外包老兵,我深知一个真理:客户不在乎你用了多牛的技术,只在乎 Demo 能不能跑通、线上别崩

所以尽管我想用 Rust 写合约、用 Svelte 做前端、用 Substrate 搭私链……最后还是选了最稳妥的组合:

  • 前端:React + ethers.js(比 web3.js 轻量)
  • 后端:Spring Boot(团队熟、文档全、监控好)
  • 合约:Solidity 0.8 + OpenZeppelin(安全第一)
  • 链:Polygon(便宜 + EVM 兼容)
  • 资源:OSS + IPFS 混合

上周五晚上加班到 11 点,终于把最后一处 nonce 冲突 Bug 修完。测试通过那一刻,我默默在 Vim 里敲下 :wq,长舒一口气——不是因为技术多牛,而是又熬过一个外包项目


心得:探索是为了更好地“搬砖”

写这篇文章时,我其实在犹豫要不要跳槽。三年多外包生涯,见过太多“为了新技术而新技术”的项目:强行上微服务结果单体都跑不稳,硬塞 Kafka 导致日志乱序,还有一次为了“AI赋能”在后台加了个 Python 脚本识别验证码……最后全烂尾。

但这次 Web3 项目不一样。虽然过程痛苦,但真正理解了“链上+链下”协同的复杂性,也学会了在理想(去中心化)和现实(用户体验、成本、稳定性)之间找平衡。

如果你也在纠结要不要学新技术,我的建议是:

  • 带着问题去学:别为了学而学,找个实际场景(哪怕自己 mock)
  • 先跑通,再优化:Demo 能跑 > 架构完美
  • 留好退路:新技术出问题时,要有 Plan B(比如中心化兜底)

毕竟,我们不是学术研究员,是靠代码吃饭的打工人。技术探索的终点,不是炫技,而是解决实际问题,顺便让自己简历好看点


最后:外包人的自我修养

在这家公司三年半,我修过政府系统的内存泄漏,扛过电商大促的数据库雪崩,也写过给领导看的“区块链+乡村振兴”PPT。
有人说外包是技术坟墓,但我觉得——只要你愿意折腾,每个坑都是垫脚石

现在,我的 VS Code(对,偶尔也用)开着三个终端:

  • 一个跑 Hardhat 节点
  • 一个 tail 日志
  • 一个挂着招聘网站

Vim 里还开着 resume.md,光标停在“熟悉 Web3 全栈开发”这一行。

谁知道呢?也许下个项目,我就不用再为 Infura 的 429 错误掉头发了。

(完)


后记:本文所有踩坑均为真实经历,如有雷同,恭喜你——也入 Web3 坑了。
免责声明:本文不代表公司立场,纯属个人吐槽。老板看到请忽略最后一段。

评论 0

最热最新
暂无评论
后端说没问题Lv.1
0
影响力
0
文章
0
粉丝