如题,楼主今天面了一下抖音的“agent研发岗位”
前情提要:面试之前这个面试被推迟了两次,今天终于面到了
上来先和我拉家常,问我现在在哪里,我说在学校。他问秋招已经快要结束了,你同学们目前情况如何啊?我说同学们都在走流程(我都没好意思说没实习的0约面,有实习的坎坎坷坷这回事).又问我自己觉得今年的校招行情比去年好还是坏,我说“感觉大家普遍认为今年的进度比去年同期晚一个月吧”
然后才自我介绍
介绍完之后简单问了一下我agent的业务背景,问我这个agent是用来干什么的,我简单讲了一下。又问我如何评估我这个策略迁移agent生成的新代码的正确性,我从agent本身的校验(子sgent调用内部沙箱MCP工具调试lua代码,传回调试结果,重点聚焦是否采用了未在内部平台注册的工具函数)和业务本身的校验与再开发(具体的游戏业务可以使用我们提供的迁移后代码的覆盖率和重合率以评判此次迁移的好坏,可以视业务需要,结合之前迁移时在agent中产生的上下文与长期记忆,与之前的agent会话交互以完成修改与再开发)。
然后就再也没有问过我agent相关的事情,开始拷打微服务RPC了。
他说你是以后端实习生的身份去腾讯实习的,那你们那边的后端架构是怎么样的?楼主说我们的后端微服务都是基于组内自研的g3框架做的,g3框架提供了线上负载均衡,服务发现,心跳检测等功能。我们负责编写组内业务相关的微服务,都是以C++编写而成,编译成动态链接库由g3框架拉起服务进程。
然后问你说你参与了组内线上微服务的开发,那你都参与了哪些服务的开发,有没有自己主导开发的?楼主说了一堆参与的,以及自己主导开发的告警服务alarmsvr。然后开始介绍alarmsvr,楼主说alarmsvr是一个告警聚合服务,负责将线上运行的文本审核策略,在线上运行时产生的运行时错误(包括因为逻辑本身的问题而运行时错误,以及线上策略请求远端大模型的时候返回的错误,如接口格式错误等)筛选,去重,聚合,并且发给下游的告警发送机器人。然后问了一下楼主这个服务的QPS,楼主说这里聚焦了全腾讯所有游戏的文本审核策略,包括了特征层,策略层,标准化层三层,日常的QPS是200W,分散在8000多个实例上。
然后问楼主各个步骤具体都在做什么,楼主说筛选负责筛选出一定时间窗口内已经发送过的告警消息,将其去除。去重负责在实例的内存中维护一片共享内存,用多个进程并发去重,聚合指的是把去重后的信息分层次(业务上的特征层,策略层,标准化层三层),分类型聚合在一起,构造新的请求包和上游服务的回包;然后把内容发给下游的全中心统一告警机器人。
追问:1.你觉得你们这个架构设计有什么问题?共享内存的去重是单机的,你能保证最终负责人收到的告警消息一定不重吗?我说这就是我们为什么要发给中心统一的企业微信告警发送机器人工具的原因,而不是直接调用api把消息推到负责人的企业微信上。由于线上策略多,请求量大,QPS摆在那里,我们的目的从直接发告警消息,退化到了给告警机器人工具减负。追问那如果让你重新设计一个架构,你怎么设计?我:把告警服务接入到组内的clickhouse库里面。线上实例收到RPC请求后,先以时间窗口(5分钟)和告警信息的指纹(业务上将一条告警的层次和错误码聚合并哈希成一条唯一指纹,实质是一个int64,我们有专门的告警指纹工具)查询clickhouse数据库,查到了就不发了。追问为什么用clickhouse而不用mysql,redis等中间件,我先比较了clickhouse和mysql,说了clickhouse的一些优势(写CK的append-only,底层存储的分区有序,按列存储便于用几个属性查询,自带TTL功能可以让老告警条目按时过期)然后说了mysql对应方面的不足;然后又简单说了一下redis的属性,比如内存中的缓存数据库,容量有限扛不住高QPS服务的频繁写入,如果有持久化需求的话rdb和aof的额外开销等等。然后又追问你觉得这么做,你这个服务的时间性能瓶颈在哪里,楼主说QPS较高时,多个线上实例同时查询CK集群,导致查询在CK集群排队,从而平均响应时间大幅增加,部分线上实例因长期查不到数据而饿死在去重步骤。解决方案是加一个消息队列,其消费速随着QPS的增加而增加,QPS到达阈值后消费速率恒定。追问你用过什么消息队列,我说我们组里用Pulsar比较多,不容实例可以用shared模式来消费。
2.继续追问:为什么用共享内存+进程并发来做并发去重,为什么不使用线程+unordered_map+线程?我说去重表的大小将直接影响发往下游告警工具的包体的大小和数量。在去重表本身有容限限制,超限要LRU淘汰的前提下,我们的去重表越大,发给下游的告警信息就越少。g3框架对线上服务进程的最大内存容量有限制,限制了2个GB,因此我们额外开了共享内存做去重。
3.继续追问你们那个g3框架的是微服务RPC吧,我说是。追问什么是RPC,我把RPC的概念背了一遍。然后追问我你们的微服务之间是怎么通信的,我说用的是tdr协议。追问什么是tdr,我说是一个类似pb这样的协议,然后做了公司内部的本土化。追问以Pb为例子,说明它和http的区别。我说了两个区别,一个是http的各种选项参数在请求头里面,请求体的格式没有规定;Pb的格式是实现有规定的,其中严格定义了两方赖以通信的rpc方法,以及收发双方发送信息的结构体,包括应该有哪些数据项,每个数据项的类型等等。另一个是http的底层时tcp提供的可靠字节流服务,所以http是一个传递流式消息的协议;Pb在传输过程中的实质是二进制数据,传输前后需要序列化和反序列化。追问字节流和二进制有什么区别,这个问题我不太清楚,我临场发挥的,我说字节流传输的是字节数据本身,接收方读了之后只要保证顺序和正确性就能直接用;二进制数据在原始数据的基础上可能经过了压缩或者其他变换,收到不能直接用,需要反序列化。
然后做了一个算法题,题目不难,就是搜索旋转排序数组,简单的二分查找而已。但是做的时候对方非常不耐烦,不停的催我赶紧做,说他订的会议室要到期了
然后是反问环节,楼主问:我报的是agent开发岗位,贵岗位对候选者有哪些方面的要求,agent在贵部门中充当了什么作用? 回答是他们说是招的agent岗位,其实部门是做变现业务的后端,agent是部门内部用来提效的工具。组内的技术栈以go为主。然后楼主又问你们日常后端开发的过程中对候选者有什么要求,答除了基本的编码能力以外,需求你会传统的后端中间件三大件(MQ,Redis,Mysql)。除此以外,他们需要和大数据相关的工作(如Hive)打交道。
然后就结束了