Project 1
你最有成就感的项目是什么?
四旋翼绕障飞行器开发。
有没有用过gpt啊一些大模型?(有没有用过大模型?)page 17
我在agentUniverse这个开源多智能体协作框架曾贡献过pr,大模型在这个框架中扮演了“决策引擎”的角色,用大模型进行任务拆解,通过制定合理的计划和反馈机制来提高整个系统的推理。
RAG技术。先通过大模型生成初步响应,再结合知识库中的数据进行二次生成,以此来降低大模型的幻觉。
agentUniverse 采用工厂模式,允许开发者以标准化的模板构建智能体协同模式。
为什么近两年大模型突然火起来的?page 17
Transformer 架构。2017年提出的 Transformer能捕捉远距离依赖关系。模型在参数达到一定量级后,会表现出很强能力。
数据和计算资源的提升。互联网产生的海量数据为大模型提供了训练数据,而硬件性能(尤其是 GPU、TPU)的迅速提升让训练和推理大模型变得可行。
应用场景的突破和商业化驱动。不仅在学术上取得了突破,更在实际应用中展现了巨大潜力。如豆包等。
大模型对传统岗位的影响有哪些?page 17
替代重复性、规则性任务如数据录入、标准化客服。
工作内容和能力要求的转型比如更加注重创新能力。
新岗位的涌现。模型开发、微调、维护和应用等技术岗位。
说说Zookeeper底层原理。page 2
架构。用主从结构,Leader负责处理所有写请求(事务操作)、生成全局唯一的事务编号(zxid),并将写请求以提案(Proposal)的形式广播给所有 Follower。Observer只处理读请求和跟随 Leader 同步数据,但不参与选举与投票。
ZooKeeper 把所有数据都存储在内存中,并以树形结构管理,这与 Unix 文件系统类似。数据的基本单位称为 ZNode。
Zab 协议。包括两个阶段:1.恢复(Recovery)阶段 当集群初启动或 Leader 故障时,所有节点进入选举状态(LOOKING 状态),通过互相投票(每个节点首先投票给自己,然后根据 zxid 和节点 ID 对比)选出新的 Leader。只有当某个候选者获得超过半数的选票时,就正式成为 Leader,并且进入恢复阶段,让所有 Follower 与 Leader 完全同步状态。2.广播(Broadcast)阶段 Leader 接收到写请求后,生成一个提案并赋予全局递增的事务编号 zxid(zxid 的高 32 位表示 leader 的任期 epoch,低 32 位为事务序列号),然后将提案发给所有 Follower。Follower 写入本地事务日志后返回 ACK,Leader 在收到过半数确认后发送 Commit 消息,最终所有节点按相同顺序提交这个操作。
讲讲你的实习的项目?(讲讲实习做了什么)page 1
我主要做的是投放引擎的升级项目。
第一个是对租户结构的改变,将租户改为租户组加子服务的结构,按业务维度将多个真实租户归为一组,每个租户有独立资源配额。k8s编排时,为不同租户组的子服务打不同标签,绑定不同resource quota。在api网关层,根据请求头中的x-tenant-group将流量路由到对应租户组的子服务实例池。
第二个是二级缓存的引入。以及缓存维护滑动窗口内,活跃租户组和算子实例映射,首次没命中时,由二级缓存或数据库加载这个租户组的算子列表,放入本地缓存。
二级缓存存储算子元数据。
泳道化。泳道元数据用Zookeeper管理,存储配置,当前状态和已分配的请求列表。
每个算子继承自AbstractOperator类,有自己的输入输出接口,用自定义线程池控制DAG算子的并行。用Completablefuture处理DAG的节点间的连接。
实习的项目怎么实现降级?page 1
在 Sentinel 中定义熔断规则,超过错误率阈值自动降级到返回静态推荐列表。
并行 DAG 调度如何保证不同 lane 之间互不干扰?page 1
每个 lane 独立分配线程池与上下文对象。DAG 中节点通过事件驱动或回调异步执行。
服务如何平滑扩容 page 1
K8s HPA 基于自定义指标扩缩容,利用 Prometheus Adapter。结合 Pod Disruption Budget,保证最小可用实例数。
介绍一下自己做了哪些?
为什么要做这个项目?
后续需要大量ab实验并观察结果,然后现有的投放引擎后端模块就会成为项目卡点。
是什么意思?展开讲一下。
你用到了哪些设计模式?
展开讲一下。
项目介绍一下?某功能怎么实现的?
技术栈:SpringBoot+Redis+grpc+MySQL。
多人协同参考:https://help.aliyun.com/zh/asm/use-cases/define-routing-rules-based-on-traffic-labels-1694487146614?spm=5176.28426678.J_HeJR_wZokYt378dwP-lLl.736.365a5181trASqb&scm=20140722.S_help@@%E6%96%87%E6%A1%A3@@2549873.S_RQW@ag0+BB2@ag0+BB1@ag0+os0.ID_2549873-RL_%E6%B5%81%E9%87%8F%E6%A0%87-LOC_search~UND~helpdoc~UND~item-OR_ser-V_4-P0_2
问一下业务细节,租户组,租户,子服务什么意思?(字节)
租户 与k8s租户相关 ,是 服务的独立实体 ,比如快手电商,快手主站,一甜相机,每个租户有 自己的数据和配置 ,但共享相同的基础设施。 租户组是有 相似业务逻辑的集合 ,这样做的好处是可以更灵活进行 策略管理 。
租户划分为租户组,是根据什么逻辑进行划分的呢?(网易)
业务需求。不同租户属于不同业务线,比如快手主站,快手电商,一甜相机,这些业务线或部门有不同的需求和优先级。
资源隔离。不同租户组需要不同的资源配置,如计算资源,存储资源。
k8s 怎么实现租户隔离的呢?
命名空间。每个命名空间相当于一个虚拟集群,资源比如pod,service,configMap在命名空间内是独立的。
网络策略可以控制pod之间的网络流量,限制命名空间之间的通信。
对于你实习的项目,去掉技术相关的,业务是什么呢?(饿了么)
投放,即将招选出来的物料有策略的给到消费者,目标是人货场的高效匹配。
参考:https://developer.aliyun.com/article/787513
不同租户之间的数据会做隔离吗?(童心制物)
不会隔离,因为他们处在同一个租户组下面,共享流量。
多租户组之间是隔离的吗?隔离怎么做的?(在多租户架构中,怎么处理多租户资源隔离问题?)(网易)
是隔离的。
最理想的情况是全部单独部署,隔离性最好,但是成本最高,我们主要是db/kafka等中间件(存储)上的隔离,以及流量(计算资源)上的单独部署。
在投放引擎中,我们有路由engine引擎负责对用户流量的负载均衡,然后交给具体的实例执行业务代码,最后返回,这个过程中逻辑隔离是通过仓库隔离实现的,投放和业务中台有不同的代码仓库。然后存储隔离通过独立的数据库库名,kafka不同租户不同topic,redis key前缀不同实现。
实习中多租户技术方案是如何确定的(小红书)
(要讲一下备选方案如何被刷下去的。) 讨论了三个方案。
独立数据库:一个租户一个库,但是连接池可以服用,隔离级别最高。
共享库,每个租户一个表:逻辑隔离。
共享库,共享表:表中新增tenant_id。
由于租户之间流量差异较大,我们选择独立数据库方案。
项目中缓存一致性怎么保证的?
两级分布式缓存:第一级存储算子和租户 的对应,存储N分钟滑动窗口中活跃的租户。第二级缓存加速数据库查询。
更新逻辑: MySQL binlog:日志记录修改,
rocketMQ消息:生成数据变更信息,发送到rocketMQ,
消息接收器:下游组件,如缓存更新服务,搜索服务,订阅rocketMQ特定主题,接收并处理这些变更消息。
搜索:搜索服务收到消息,更新索引库。
更新缓存:redis更新缓存数据。
项目开发过程中有遇到困难吗?怎么解决的?(科大讯飞)
LoadingCache失效的问题,流程已经流转,QA提测,有不命中的问题,会爆NPE异常,当时排查了很久。
主要就是借助Arthas去看调用日志,通过trace查看调用信息,具体是getTenantFromCacheByPlanId接口出了故障,最后发现是LoadingCache没命中导致的。最后通过设置缓存不命中回db源解决,同时异步更新LoadingCache。
项目怎么上线的?
先在预发环境部署测试,测试准入后,提交发布单,写基线。
protobuf会不会存储数据类型?(小红书)
不会。
protobuf中,消息是键值对,编码后只有tag序列号和value值,序列号中有三个位存储类型。
比如对于json数据{“name”:”张三”},JSON需要18字节序列化,他要保存整个字符串,而protobuf只需要存储name的字段号和张三的类型是字符串,而这两个信息只存在一个字节中。
为什么你的项目要有租户组的概念?直接水平扩容不行吗?(小红书)
因为一个租户组下两个租户,在处理用户流量时,他们不是隔离的,我们要对流量进行分配,类似于网关,调度的东西。
protobuf的优点是什么?protobuf内部怎么实现的?
优点。protobuf使用二进制格式进行序列化,相比于json或xml,他占用的空间更小,传输速度更快。
向后兼容性。protobuf设计时考虑了版本控制,可以不破坏现有客户端的情况下,添加或删除字段。
protobuf内部实现。编码方式,protobuf使用一种称为 Varint 的编码方式表示整数,Varint是一种可变长度的编码,较小的数字使用较少字节,从而节省空间。
字段标识符和类型。在protobuf中,每个字段都有一个唯一的标识符和一个类型。标识符用于在解码时识别字段,类型则用于确定如何解析字段的数据。比如标识符为1的字段可能是一个整数。
消息结构。protobuf消息时由一系列字段组成的,每个字段都有一个类型和一个标识符。在编码时,protobuf会按照字段的标识符进行编码,解码时也会按照相同的顺序解码。
投放是什么?
投放的流程可以抽象为读取浏览记录,输出商品列表,过滤,排序,写浏览记录。
在Arthas里,我想看一个方法的调用链路以及方法每个代码行的执行时间,命令是?
时间的话是看那个火焰图,查看调用链路,trace [方法全名],查看每行代码的执行时间,monitor [方法全名]
项目怎么部署的?
在k8s部署。
聊一聊你对如何改进这个项目的看法?
这个项目有可以改进的地方,就是投放引擎的需求流转没有和需求业务中台打通,后续可以考虑适配中台。
你负责了哪些模块?
我负责后端模块,修改以及新增了一些接口,比如创建租户,根据租户组列出租户。后端模块是研发人员修改投放引擎的入口,负责方案新增修改发布功能,他直接关系到系统的安全性。
项⽬中实践过 JVM 调优吗?怎么做的?(非常重要)(百度,腾讯,阿里巴巴)
在公司投放引擎系统中每次发版启动后会进行手动预热,流量切入后,偶尔出现长达2秒的年轻代GC暂停,影响业务。通过GC日志发现每次年轻代GC都会有大量对象晋升,大概600MB。JVM的 年轻代GC阶段会根据survivor区的对象总大小动态调整对象晋升年龄阈值 ,而在启动时,大量新对象在survivor区占据大空间,导致年龄阈值调低为1,意外的晋升到老年代。解决方法,通过调整-XX: SurvivorRatio 改变Survivor区的大小,如将8改成3,使得survivor占新生代内存比例从20%提升40%,确保容纳大部分对象。修改JVM参数后,再次进行发版和手动预热,年轻代GC暂停花了30毫秒左右,长暂停问题得到解决。
参考:JVM调优
你在项目中重新设计了多租户架构,引入租户组和子服务,能解释一下这样设计的好处吗?
租户是服务的实体,租户组是具有类似业务逻辑的集合,通过租户组,可以实现租户组之间隔离流量,租户之间共享流量,灵活性更强。
介绍下项目的整体架构?(网易)
你在项⽬中遇到过 GC 问题吗?怎么分析和解决的?
上线后,发现接口调用频繁导致新生代 GC频繁告警。新生代 GC次数增多,同时老年代内存快速升高,最终触发了Full GC。分析发现Guava Cache的Map对象占用大量内存。问题分析:Guava Cache没有设置最大缓存数量,仅设置了过期时间。这导致缓存中存储了大量对象。解决方法,通过为Guava Cache设置最大缓存数量限制,控制缓存中对象的数量,减少内存占用。
多租户隔离,为什么不用两个进程?
需要下沉容器层,有插件层消除重复。 表现为同一个应用,然后只注册到注册中心一次。两个应用可以使用相同端口号。 另外进程就更重了,要消耗更多的资源,而且不好管控。
参考:https://juejin.cn/post/7253809748318109755
https://help.aliyun.com/zh/polardb/polardb-for-mysql/user-guide/multi-tenant-resource-isolation-usage-example?spm=5176.28426678.J_HeJR_wZokYt378dwP-lLl.11.4b4651816Tjf8f&scm=20140722.S_help@@%E6%96%87%E6%A1%A3@@2698281.S_BB2@bl+RQW@ag0+BB1@ag0+hot+os0.ID_2698281-RL_%E7%A7%9F%E6%88%B7%E9%9A%94%E7%A6%BB-LOC_search~UND~helpdoc~UND~item-OR_ser-V_4-P0_1
https://help.aliyun.com/zh/rds/apsaradb-rds-for-postgresql/implementation-of-saas-tenant-data-isolation-solution-based-on-row-level?spm=5176.28426678.J_HeJR_wZokYt378dwP-lLl.12.4b4651816Tjf8f&scm=20140722.S_help@@%E6%96%87%E6%A1%A3@@2526158.S_BB2@bl+RQW@ag0+BB1@ag0+hot+os0.ID_2526158-RL_%E7%A7%9F%E6%88%B7%E9%9A%94%E7%A6%BB-LOC_search~UND~helpdoc~UND~item-OR_ser-V_4-P0_2
https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/benefits-of-sandboxed-container?spm=5176.28426678.J_HeJR_wZokYt378dwP-lLl.33.4b4651816Tjf8f&scm=20140722.S_help@@%E6%96%87%E6%A1%A3@@160288.S_RQW@ag0+BB2@ag0+BB1@ag0+hot+os0.ID_160288-RL_%E7%A7%9F%E6%88%B7%E9%9A%94%E7%A6%BB-LOC_search~UND~helpdoc~UND~item-OR_ser-V_4-P0_3
流程编排分支条件如何实现?
业务身份,这个有问题,如果大量增加分支,会拷贝多份,会有很多重复的规则文件,但是只有一两个组件不一样。 目前做法时在组件中可能有业务条件判断。后续会使用表达式语言增加分支条件支持,业务身份只支持大粒度的区分。
流程编排如何避免大量调用下游服务,是否做了隔离?
感觉调用下游要做熔断,例如hystrix。但是这个有点重了。sdk要做薄。
流量隔离
动态调度:动态加载和卸载
扩展点
组件化编程
编排
需要支持不同的分支条件,不能只靠增加业务身份,解决分支问题,不然规则文件很多
后续多个聚合业务共用同一个业务中台应用,一个聚合应用发布,另一个聚合应用也得跟着发布,如何解决这个问题?
动态部署
参考:https://help.aliyun.com/document_detail/149601.html?spm=5176.28426678.J_HeJR_wZokYt378dwP-lLl.121.7e7f5181f0SkBg&scm=20140722.S_help@@%E6%96%87%E6%A1%A3@@149601.S_RQW@ag0+BB2@ag0+BB1@ag0+os0.ID_149601-RL_%E5%8A%A8%E6%80%81%E9%83%A8%E7%BD%B2-LOC_search~UND~helpdoc~UND~item-OR_ser-V_4-P0_2
SaaS租户数据隔离是怎么实现的
数据库隔离,成本高。
schema隔离,每个租户独立的schema。
表级隔离,在表中增加租户ID。
行级隔离,记录中增加租户ID字段。
<!– ```java
// 示例:通过租户ID进行数据隔离
public class TenantService {
private static final ThreadLocal
// 设置当前租户ID
public static void setCurrentTenant(String tenantId) {
currentTenant.set(tenantId);
}
// 获取当前租户ID
public static String getCurrentTenant() {
return currentTenant.get();
}
// 查询租户数据
public List<User> getTenantUsers() {
String tenantId = getCurrentTenant();
if (tenantId == null) {
throw new RuntimeException("Tenant ID is not set.");
}
// 在查询时加入租户ID过滤条件
return userRepository.findByTenantId(tenantId);
} } ``` -->
用户首次使用的时候怎么让用户知道应该在哪个pod?
ingress负载均衡到service,service负责路由到pod,pod可以用labels和Selector选择。 <!– 第一点:用户->后端根据请求参数判断AB桶,选择算子->算子id->推荐系统返回物料给用户
第二点:用户->后端根据请求获取标头,分配一个pod->算子id->推荐系统返回物料 –> 服务类型有三种: 虚拟集群IP:通过集群的内部IP 暴露服务,选择该值时服务只能够在集群内部访问 负载均衡:使用云提供商的负载均衡器向外部暴露服务 节点端口:通过每个节点上的IP和静态端口nodeport暴露服务
服务关联:Service 通过选择器来关联其成员Pod。为使 Pod 成为 Service 的成员该 Pod 必须具有选择器中指定的所有标签。
外部流量策略:Local和Cluster。Local仅Pod所在的节点会挂载到负载均衡后端,适用对需要保留客户端原始IP地址的应用程序,例如基于原始IP地址的日志记录。Cluster所有集群内的节点都将挂载到负载均衡的后端,适用于当需要保证服务的高可用性,并且对源IP保存不敏感时,例如大型Web应用集群。