大多数收集网络数据的计划会为抓取器做预算,却忘记了人。第一个版本只需几周就能写完,所以一个人的团队看起来绰绰有余。然后网站发生变化,数据量增长,某个客户发现了一个错误的数字,结果发现这份工作从来就不是写抓取器,而是让它们保持准确。
我们找不到一个可信的、已发布的基准来说明这需要多少人,而且任何单一的比例都会误导你。因此本指南提供角色划分、一个你可以用自己的数据运行的小模型,以及在每个规模下往往最先出问题的地方。
决定人员数量的因素
数据量的影响比你想象的要小。从同样的数据源多抓取十倍的页面,主要是预算和基础设施的问题。人员数量取决于以下四点:
- 数据源的数量,因为每一个都可能独自出问题。
- 它们出问题的频率,这取决于网站变化的频率以及访问它的难度。
- 你能承受多大的错误。一份每周更新的研究数据集可以等待。但客户据此采取行动的价格数据流则不能。
- 你新增数据源的数量,因为接入新源与维护旧源会争夺同一批人手。
角色
这些是角色,而不是职位头衔。在一个小团队中,一个人可能身兼数职,这没关系,只要每个角色都有一个明确的负责人。
| 角色 | 负责内容 | 往往缺失直到 |
|---|---|---|
| 采集工程师 | 抓取器、数据提取、修复故障 | 从不缺失 |
| 平台工程师 | 调度、队列、代理、浏览器、存储、成本 | 多个人在重复搭建同样的基础设施 |
| 数据质量负责人 | 检查、漂移、“正确”的定义 | 客户先发现了错误 |
| 产品或数据负责人 | 采集什么、优先级、数据源决策 | 所有事情都变得紧急 |
| 法律与合规联系人 | 范围、条款、个人数据、审批 | 一个新数据源引发了没人能回答的问题 |
最后一个角色很少是全职的,但应该指定一个具体的人。一份简短的书面数据收集政策可以让这个人不必反复回答同样的问题。
一个规划模型
这个脚本把经常性的工作量转换成小时数,再把小时数转换成人数。它只需要 Python 3.9 或更高版本。每个数字都是一个假设,应替换为你自己的数据:数一数上个季度你做了多少次修复,以及花了多长时间。
"""A planning model for how many engineers a data collection operation needs.
Every default is an assumption to replace with your own numbers.
"""
from __future__ import annotations
import math
HOURS_PER_FTE = 30 # focused engineering hours per person per week
def team_size(sources, breaks_per_source_per_month, hours_per_fix, new_sources_per_month,
hours_per_new_source, weekly_platform_hours=20, weekly_support_hours=8):
"""Recurring hours become people; reserve a quarter of the time for project work."""
fixes = sources * breaks_per_source_per_month * hours_per_fix / 4.33
onboarding = new_sources_per_month * hours_per_new_source / 4.33
weekly = fixes + onboarding + weekly_platform_hours + weekly_support_hours
fte = weekly / (HOURS_PER_FTE * 0.75)
return {"fixes": round(fixes), "onboarding": round(onboarding),
"platform": weekly_platform_hours, "support": weekly_support_hours,
"weekly_hours": round(weekly), "fte": round(fte, 1), "people": math.ceil(fte)}
if __name__ == "__main__":
scenarios = {
"10 sources, stable": (10, 0.25, 4, 1, 16),
"50 sources, mixed": (50, 0.5, 4, 3, 16),
"200 sources, mixed": (200, 0.5, 4, 8, 16),
"200 sources, hard": (200, 1.5, 6, 8, 24),
}
print(f"{'scenario':22}{'fixes':>6}{'new':>5}{'platform':>9}{'support':>8}{'hrs/wk':>7}{'FTE':>6}{'people':>7}")
for name, args in scenarios.items():
r = team_size(*args)
print(f"{name:22}{r['fixes']:>6}{r['onboarding']:>5}{r['platform']:>9}{r['support']:>8}"
f"{r['weekly_hours']:>7}{r['fte']:>6}{r['people']:>7}")
输出:
scenario fixes new platform support hrs/wk FTE people
10 sources, stable 2 4 20 8 34 1.5 2
50 sources, mixed 23 11 20 8 62 2.8 3
200 sources, mixed 92 30 20 8 150 6.7 7
200 sources, hard 416 44 20 8 488 21.7 22
这些场景使用的是示例性的输入而非实测数据,脚本中的参数展示了每一个场景。稳定的数据源每四个月出一次故障,修复需要四个小时;难搞的数据源每月出一次半故障,修复需要六个小时。
有两点值得注意。从 50 个混合数据源增加到 200 个,数据源数量变为原来的 4 倍,但团队规模只增加到约 2.4 倍,因为平台工作是共享的。然后同样是这 200 个数据源,仅仅因为更难维持运转,团队就从 7 人变成了 22 人。故障率对人员数量的影响比数据源数量更大,所以这是首先要衡量的数字。
该模型为每个人保留了四分之一的时间用于项目工作。这已经算是比较精简的了。Google 的 SRE 手册提出的目标是至少 50% 的时间用于工程工作而非运维工作,按这个比例,这些团队的规模会扩大 1.5 倍。如果没人有时间去修复根本原因,同样的故障就会反复出现。
最先出问题的地方
一到两人。 关键人风险。一切都集中在一个人的脑子里,休假就会变成事故。把每个数据源的工作原理和修复方法都写下来。购买你的基础设施,而不是自己运营。
三到五人。 质量问题。团队忙于修复显而易见的故障,而无声的问题却在不断积累,比如一个选择器返回了错误的字段却仍返回 200 状态码。指定一位质量负责人,并对内容以及状态码都进行流水线监控。
六到十人。 重复建设与优先级问题。每位工程师都搭建了自己的重试机制和代理处理方式,而每位相关方的数据源都变得紧急。这时一位平台负责人就会带来回报,同时也需要一位能够说”不”的产品负责人。
超过十人。 协调与值班问题。Google 的 SRE 手册计算出,一个单站点团队如果要有两人值班、轮班一周,至少需要八名工程师。很少有数据团队应该搭建这样的规模。要设计能够独立恢复、事后再补上进度的流水线,并为客户真正依赖的部分保留全天候值守。
减少所需人数
- 购买商品化的层级。 我们的自建还是购买指南详细介绍了自己运营基础设施的真实成本。
- 削减数据源。 淘汰价值最低的十个数据源往往是你能做的最廉价的”招聘”。
- 优先选择稳定的渠道。 官方 API、数据源和结构化数据比 HTML 选择器出问题的频率更低。
- 修复整类故障。 共享的重试机制、共享的检查和共享的解析器能把许多小故障合并成一个问题来处理。
结论
不要按照某个比例来配置人手。要根据你的数据源数量、故障率以及你能承受的错误程度来配置人手,并在下一次招聘讨论之前先衡量这些数字。尽早指定一位质量负责人,购买那些不是你核心优势的部分,并预料到瓶颈会随着你的发展而转移。
来源与参考资料
- Google, Site Reliability Engineering, Being On-Call: sre.google
- Google, Site Reliability Engineering, Eliminating Toil: sre.google