聊聊我在字节基础架构组搞技术探索的一些野路子实践
去年双11刚过,组里开复盘会,leader 说了一句"明年我们要在基础架构层面做一些技术探索,鼓励大家多折腾"。我当时心里就想,得,又要卷了。不过说实话,作为一个在字节基础架构组搬了快五年砖的后端老兵,我对这种"技术探索"其实是有执念的。毕竟天天写 CRUD 是会让人废掉的。
先交代下背景吧。我坐标杭州,来字节之前面过阿里和网易,最后阴差阳错来了字节。说实话杭州这边互联网氛围确实好,跳槽机会也多,但我这人比较懒,习惯了字节的节奏也就不想动了。平时写代码是个重度 Vim 党,IDE 基本不用,同事经常吐槽我"都什么年代了还在用 Vim",我就回一句"你懂个锤子,Vim 才是男人的浪漫"。
好了废话不多说,今天想跟大家聊两个我最近折腾的东西——一个是 DALL-E 在内部工具链上的集成实践,另一个是区块链技术在内部权限审计上的探索。你可能会问,这俩玩意儿跟基础架构有毛关系?别急,听我慢慢道来。
先聊 DALL-E:当 AI 画图遇上内部工单系统
事情是这样的。我们组负责维护一套内部的运维工单系统,每天各个业务线提上来的工单少说也有大几百个。其中有一类是"资源申请"类的工单,经常需要附上一些架构图、拓扑图来说明申请理由。但说实话,大部分研发画的图那叫一个惨不忍睹,我见过用画图板画的"架构图",线条歪歪扭扭的,跟小孩涂鸦似的。
上个月有个同事提了个工单,申请一批 GPU 资源,附的图是用 PPT 画的,我看了差点没把饭喷出来。当时我就想,能不能用 AI 来辅助生成一些示意图?正好那阵子 DALL-E 的 API 开放了,我就动了心思。
技术选型上的纠结
刚开始我想的是直接调 OpenAI 的 API,但咱们毕竟是字节,数据安全这根弦得绷紧了。直接把内部架构信息传给外部 API,安全合规那边肯定过不去。所以我花了一周时间调研,最后决定走一条折中路线:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 直接调 OpenAI API | 简单粗暴,效果最好 | 数据安全风险大,合规过不了 |
| 自建 DALL-E 模型 | 数据完全可控 | 算力成本太高,模型微调周期长 |
| 本地部署开源替代 + DALL-E 风格微调 | 数据可控,成本适中 | 效果有折扣,需要调参 |
最后选了第三种方案。我们用 Stable Diffusion 作为底座,结合一些内部积累的架构图数据做了 LoRA 微调,尽量让生成的图接近 DALL-E 那种风格。虽然效果比不上原版 DALL-E,但至少能用了。
踩坑实录
集成过程中踩了不少坑,说几个印象深的:
第一个坑是 prompt 工程。我们发现直接让研发输入自然语言描述,生成的图经常牛头不对马嘴。比如有人输入"一个微服务架构",AI 给你画出来一个长着很多触手的章鱼。后来我们做了一层 prompt 模板化,把常见的架构模式抽象成模板,研发只需要填参数就行。
# prompt 模板化处理示例
ARCH_PROMPT_TEMPLATE = """
Technical architecture diagram, clean and professional style,
white background, blue and gray color scheme:
{component_list}
Connection style: {connection_type}
Layout: {layout_type}
"""
def generate_arch_prompt(components, conn_type="arrow", layout="layered"):
component_desc = ", ".join([
f"{c['name']} ({c['type']})" for c in components
])
return ARCH_PROMPT_TEMPLATE.format(
component_list=component_desc,
connection_type=conn_type,
layout=layout
)
第二个坑是生成速度。一张图在 A100 上跑大概要 15-20 秒,但工单系统对响应时间是有要求的。我们做了个异步队列,用 Redis 做任务分发,生成完了通过 WebSocket 推给前端。这块倒是轻车熟路,毕竟基础架构组天天跟这些中间件打交道。
// 异步任务分发,Go 写的,毕竟字节内部 Go 是主力
type ImageGenTask struct {
TaskID string `json:"task_id"`
Prompt string `json:"prompt"`
Callback string `json:"callback_url"`
Priority int `json:"priority"`
CreatedAt int64 `json:"created_at"`
}
func (s *ImageGenService) SubmitTask(ctx context.Context, task *ImageGenTask) error {
// 优先级队列,高优工单先处理
data, _ := json.Marshal(task)
return s.redisClient.ZAdd(ctx, "image_gen:queue",
&redis.Z{Score: float64(task.Priority), Member: string(data)}).Err()
}
第三个坑说出来你可能不信——是 Vim 的锅。我调试 prompt 的时候习惯用 Vim 编辑 JSON 配置文件,结果有一次手滑把模板里的转义字符搞乱了,导致生成的图全是乱码。排查了两个小时才发现,当时真的想砸键盘。后来老老实实写了个 JSON schema 校验,提交前自动检查格式。
上线效果
折腾了大概三周,这个功能上线了。效果嘛,说实话没有想象中那么惊艳,但确实帮了不少忙。据统计,工单中附带架构图的比例从 30% 提升到了 72%,而且图的质量肉眼可见地提升了。运维那边的兄弟反馈说审核工单的时候舒服多了,不用再对着灵魂画作猜意图了。
不过也有翻车的时候。有一次某个同事用这个工具生成了一张"分布式缓存架构"的图,结果 AI 给他画了一堆罐子(cache 嘛,罐子),底下还写着"Redis"。发到群里被大家笑了半天,那哥们儿尴尬得不行。后来我们在 prompt 里加了更强的约束,这种情况就少多了。
再聊区块链:内部权限审计的"链"上实践
第二个探索方向就更野了——区块链。别笑,我知道一提到区块链很多人就觉得是割韭菜的,但我这次做的跟币一点关系都没有。
起因是一次线上事故
今年年初,我们内部权限系统出了一次事故。有个已经离职的同事的账号,因为某个同步任务的 bug,权限没有被及时回收。结果这个账号被利用了大概 4 个小时,虽然最后没造成什么严重后果,但安全团队那边炸了锅,要求我们做整改。
复盘的时候我们发现一个核心问题:权限变更记录的审计链路不够可靠。虽然我们有操作日志,但日志是可以被篡改的,而且在多节点部署的情况下,日志的一致性也难以保证。当时安全团队提了个需求:能不能做一套不可篡改的权限变更审计系统?
我当时脑子里就蹦出来一个词——区块链。
为什么是区块链?
我知道这听起来有点杀鸡用牛刀,但你仔细想想区块链的核心特性:
- 不可篡改:数据一旦写入就无法修改,天然满足审计需求
- 可追溯:每一笔变更都有完整的时间线和因果关系
- 分布式共识:多节点验证,单点故障不影响数据完整性
这不就是为审计场景量身定做的吗?当然,我们不会去搞什么公链,用的是联盟链的思路,内部几个核心节点做共识就够了。
架构设计
整体架构其实不复杂,我画个文字版的:
┌─────────────────────────────────────────────────┐
│ 权限管理系统 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 权限分配 │ │ 权限回收 │ │ 权限变更 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └──────────────┼──────────────┘ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ 审计事件总线 │ │
│ └────────┬────────┘ │
└─────────────────────┼───────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ 联盟链审计网络 │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ Node-1 │ │ Node-2 │ │ Node-3 │ │ Node-4 │ │
│ │(基础架构)│ │(安全团队)│ │(合规部门)│ │(业务SRE)│ │
│ └────────┘ └────────┘ └────────┘ └────────┘ │
│ │
│ 共识算法: PBFT (实用拜占庭容错) │
│ 存储: LevelDB + MySQL(索引) │
└─────────────────────────────────────────────────┘
技术栈选型上,我们没有从零造轮子,而是基于 FISCO BCOS(微众银行开源的联盟链平台)做了二次开发。选它的原因很简单:国产开源、文档齐全、社区活跃,而且已经在金融领域验证过了,安全合规那边好交代。
核心代码片段
权限变更事件上链的核心逻辑,我用 Go 简单示意一下:
// 权限变更事件结构
type PermissionChangeEvent struct {
EventID string `json:"event_id"`
Timestamp int64 `json:"timestamp"`
Operator string `json:"operator"` // 操作人
TargetUser string `json:"target_user"` // 被操作人
ChangeType string `json:"change_type"` // grant/revoke/modify
Resource string `json:"resource"` // 权限资源
PrevState string `json:"prev_state"` // 变更前状态
NewState string `json:"new_state"` // 变更后状态
ApprovalID string `json:"approval_id"` // 审批单号
Signature string `json:"signature"` // 操作签名
}
// 上链服务
type AuditChainService struct {
chainClient *fiscobcos.Client
eventBus *EventBus
}
func (s *AuditChainService) RecordPermissionChange(
ctx context.Context, event *PermissionChangeEvent,
) error {
// 1. 生成事件摘要(用于链上存储,节省空间)
eventHash := sha256.Sum256(mustMarshal(event))
// 2. 构造链上交易
tx := &fiscobcos.Transaction{
Contract: "PermissionAudit",
Method: "recordChange",
Params: []interface{}{
event.EventID,
event.Timestamp,
event.Operator,
hex.EncodeToString(eventHash[:]),
event.Signature,
},
}
// 3. 提交交易,等待共识确认
receipt, err := s.chainClient.SendTransaction(ctx, tx)
if err != nil {
return fmt.Errorf("上链失败: %w", err)
}
// 4. 记录区块高度,用于后续溯源
log.WithFields(log.Fields{
"event_id": event.EventID,
"block_number": receipt.BlockNumber,
"tx_hash": receipt.TxHash,
}).Info("权限变更事件已上链")
return nil
}
踩过的坑和教训
坑一:性能问题。 刚开始我们把所有权限变更都上链,结果发现 TPS 上不去。联盟链嘛,共识过程本身就慢,PBFT 的 TPS 大概在 1000-2000 左右。但权限变更的高峰期(比如每天早上的批量授权)一秒能来好几千个事件。
解决方案是做了一层缓冲:高频的变更先在本地做 Merkle Tree 聚合,每隔 5 秒把一批事件的根哈希打包上链。这样 TPS 压力一下就降下来了,而且单个事件的不可篡改性通过 Merkle Proof 依然可以验证。
坑二:存储膨胀。 虽然链上只存哈希,但完整的审计数据还是要存的。我们用了 MySQL 做详细数据的存储,链上哈希做校验。但半年下来,数据量增长很快,查询也变慢了。后来加了 Elasticsearch 做索引,查询性能才上来。
坑三:同事的不理解。 这个坑其实最大。我刚开始在组里提这个方案的时候,好几个同事觉得我在搞噱头,"用个数据库不就行了,搞什么区块链"。我花了两周时间做 POC,拿着数据去给他们演示"你看,数据库日志确实被改过,但链上的数据改不了",这才说服了他们。
所以说,技术选型这件事,技术本身往往不是最难的,最难的是让团队理解和接受。
实际效果
上线半年了,效果还是可以的。几个关键数据:
| 指标 | 改造前 | 改造后 |
|---|---|---|
| 审计数据完整性 | 依赖日志系统,有丢失风险 | 链上存证,不可篡改 |
| 权限变更追溯时间 | 平均 2 小时(需要翻多个日志源) | 5 分钟内(链上直接查询) |
| 安全审计通过率 | 偶尔有不合规项 | 100% 通过 |
| 系统额外延迟 | 无 | P99 < 50ms(异步上链) |
安全团队那边很满意,还专门发了封感谢邮件。虽然邮件里说"感谢基础架构组的大力支持"这种套话,但好歹是被认可了,开心。
一些心得体会
折腾了这两个项目,有一些感悟想分享给大家:
第一,技术探索不要怕"不务正业"。 DALL-E 和区块链,看起来跟基础架构都不搭边,但只要你找到合适的切入点,就能产生实际价值。关键是你要主动去想、去试,而不是等着 leader 给你派活。
第二,不要迷信技术,也不要排斥技术。 区块链在很多人眼里是忽悠,但在特定场景下它确实能解决问题。DALL-E 看起来很酷,但落地的时候一堆坑。技术没有好坏,只有适不适合。
第三,性能优化永远是个话题。 不管是图片生成的异步队列,还是联盟链的聚合上链,本质上都是在做性能优化。我这个人别的爱好没有,就喜欢抠性能,看到 P99 从 200ms 降到 50ms 能开心一整天。可能这就是程序员的快乐吧,简单且枯燥。
第四,Vim 党永不为奴。 最后夹带个私货,这两个项目的所有配置文件、代码调试,我全是在 Vim 里完成的。同事问我效率怎么样,我说你不懂,当你的手指形成肌肉记忆之后,写代码就像弹钢琴一样。好吧其实有时候也会按错键删掉半小时的工作,但这个不重要。
好了,今天就聊到这里。如果你也在做类似的技术探索,欢迎来杭州找我面基,我请你喝奶茶。毕竟在字节搬砖这么多年,也就这点爱好了。
对了,如果你在杭州想找后端岗位,阿里和网易确实机会不少,但字节的待遇和技术氛围也不差的,可以考虑考虑(手动安利)。
我们下期再见,我去修 bug 了,线上又报警了,烦死。


评论 0