2021技术盘点

Posted by jabin on December 18, 2021

一、项目经验 22

1.1 Go框架 3 1

go框架

  1. 选型: go-micro go-kit go-zero gin
  2. 特性: 开箱即用工具丰富、中文社区活跃
  3. 新支持的特性: 常用库; 链路追踪注入; nacos/rmq 的client二次封装; 健康检查; 脚手架脚本修改(Dockerfile, .gitlab-ci.yaml); 统一返回格式; 日志修改等

1.2 ServiceMesh 4 1

ServiceMesh特性表

1.2.1 代码框架

1. 不同语言的代码框架,通过gRpc+http打通

1.2.2 流量治理

1. 服务发现(k8s)
2. 负载均衡(istio,默认轮询)
3. 服务容错(超时、重试、熔断、限流)
4. 网关(业务网关seed)
5. 发布模式(灰度/AB)

1.2.3 可见性

可见性之指标监控0-1

  1. 日志。 蓝鲸+KS
  2. 调用链。 Istio+KS
  3. 指标监控。 Promethus
  4. 监控面板。 Grafana

1.2.4 安全

1. mTls

1.2.5 基础组件

1. Rmq
2. Nacos

1.2.6 DevOps

1. Gitlab-ci
2. KubeSphere

1.3 Serverless 4 2

Serverless实践笔记

1.3.1 HPA

1. K8s自带
2. 扩容指标类型有限(cpu、内存)
3. 实例数无法0-1/1-0

1.3.2 Knative

1. 基于HPA(k8s)
2. 支持基于请求量的Autoscal
3. Activator。0-1的扩容,流量先在Activator持有,websocket通知AutoScaler对服务实例扩容
4. AutoScaler。接受来自Activator和Queue-Proxy指标, 对服务实例扩容
5. Queue-Proxy。请求统计、流量转发等
6. 冷启动问题。实例预留(失去serverless能力)、镜像大小优化等

1.3.3 KEDA

1. 基于HPA
2. 较轻量
3. 稳定版还不支持基于请求量的0-1/1-0扩缩

1.3.4 Admission Webhook

1. 背景。 knative不支持initContainer和volume
2. 解决。 通过mutating webhook, 在调用api server创建服务时, 匹配对应的label, 满足则进行注入

1.4 监控告警 2

指标监控

  1. 特性。 项目和Metric级别的邮件&钉钉告警配置、告警推送
  2. Promethus+alertmanager套件
  3. KubeSphere的告警页面配置 以及命令行的告警推送配置
  4. 开源告警中转服务。 告警消息的模板配置, 多样的推送目标支持(钉钉、邮件、企微等)
  5. 告警监控面板。 Grafana

1.5 边缘推理 3

1.5.1 架构(KubeEdge)

1. CloudCore
2. EdgeCore
3. Device
4. 通信协议。 MQTT

1.5.2 流程

1. 边缘节点/终端设备管理、边缘镜像的部署、边缘节点监控
2. 边缘设备->边缘推理节点->边缘汇聚节点->云端推理结果处理/云端推理->MQ->各类应用场景(事件告警、监控视图、智能统计)

1.6 全自动AI流程SDK 2 1

1.6.1 OAuth2.0鉴权

鉴权机制

  1. 应用创建
  2. token生成
  3. api校验

1.6.2 python-SDK封装

MLOps SDK

  1. 基础类的封装
  2. 数据集、项目、训练、离线预测、推理服务部署抽象

1.7 英雄联盟手游 3 1

1.7.1 负责的游戏模块

1. 排行榜。 段位榜/王者榜;  榜单分布式缓存;Apollo(proxy、双主机、check处理双主机的数据同步、最终一致性。 跳表) 
2. 排位赛

2.7.2 核心模块

1. 匹配。 匹配池: 先进先出的双向链表, HashTable(方便找符合能力队伍,key为elo+grade), tick驱动(各种判断条件,匹配范围扩增); 匹配失败(+AI/温暖局), 匹配成功(创建选英雄房间、从匹配池删除、遍历下个节点)
2. 战场。 

2.7.3 框架

1. 底层驱动。TSF4G
2. 封装业务的通用逻辑。 如资源表加载、服务状态的感知、Eventlog、开关等

1.7.4 自动化部署

1. 分支服务器,数量多,部署流程复杂(各类配置、开关、N个必要服务)
2. 资源。 DB、机器、分支服务
3. (DB+机器)绑定分支   演变为  (DB+分支)部署任意未分配的机器。 3天不活跃,回收机器(回收前告警,可续期)
4. 结果。 节省部署工作量,节约机器成本

1.7.5 自动化压测

1. 效果。 流水线,每周跑一次,上报web管理后台,生成在线压测报告,并发送邮件
2. 压测报告内容。 服务器的cpu/内存数据、热点函数、函数耗时、函数火焰图、内存泄漏检测
3. 压测源。 wetest压测平台,依据协议,构造请求
4. 工具。 gperf, 编译时开启开关,start stop(control命令注入)。 默认100次/秒

二、后端技能 33

2.1 操作系统 3 2

参考

2.1.1 进程管理

1. 进程与线程。 线程是独立调度的基本单位, 进程是资源分配的基本单位。 进程内的不同线程共享进程的资源。   线程的系统开销小很多(创建+切换)
2. 进程的状态。 创建、就绪、运行、阻塞
3. 进程调度算法。 批处理系统:先来先服务、短作业优先、最短剩余时间。  交互系统:时间片轮转、优先级、多级反馈队列(时间片时间不同、时间片越小优先级越高)
4. 进程间通信。 管道、共享内存、消息队列、套接字

2.1.2 内存管理

1. 虚拟内存。 每个进程的地址空间中的块(页),映射到物理内存, 按需加载
2. 页面的置换算法(内存更新)。 LRU、NRU(优先淘汰被修改的脏数据)、FIFO及其优化(第二次机会+链表优化)

2.1.3 文件管理

2.2 编程语言 4 4

2.2.1 Golang

1. GMP。M物理线程(线程是系统最小调度单位)。 GP关系:P先从自己的G队列拿,没有则全局拿,或者去其它P偷;PM关系:若当前绑定的M阻塞了, 会寻找其它空闲的,或者新建一个M(MAX数量范围内);  G之间通信可通过channel,亦可通过context上下文。 用户态,无切换成本,效率高。 [参考](https://zhuanlan.zhihu.com/p/356739568)
2. Map。1.7支持并发安全的map。 两个数据结构(读读不加锁的read和写写加锁的dirty), read若miss则到dirty读, dirty同步到read->读多写少考虑用sync map
3. Slice。对一段连续数组的引用,当数组比较大时,可避免大量内存拷贝。  append实现: 若长度小于旧的, 则直接在原来的数组上操作, 若长度大于旧且小于2倍旧, 则扩容至2倍,若大于2倍旧, 则扩容到新的实际长度 。 [参考](https://halfrost.com/go_slice/)

```
type slice struct {
	array unsafe.Pointer
	len   int
	cap   int
}
```

4. Channel。 环形队列。 有缓冲和无缓冲。  阻塞->挂起对应的G
5. Interface。接口。struct可实现Interface的方法;   应用场景:抽象参数传递
6. 内存管理。相比C, 增加逃逸分析和GC。 区分堆、栈上分配,内存管理主要是堆上分配的内存。  层级: mcache, mcentral, mheap。 小中对象(32k)先到mcache, 线程级别(P), 无需加锁, 不够再去mcentral, 要加锁, 不够再去mheap, 要加锁; 大对象直接到mheap。 [参考](https://segmentfault.com/a/1190000020338427)
7. GC。三色标记。 初始白->root和关联对象灰->所有引用都扫描完成的为黑->剩下的白色对象为需要GC的。 STW解决扫描过程,有未被引用的对象被新引用, 通过分散到n次小规模GC,解决STW时间过长问题。 [参考](https://zhuanlan.zhihu.com/p/297177002)
8. Context。goroutine上下文传递(信息+控制), 用于并发控制、超时控制。 Select-case。 关闭协程通过Channel+select,在如一个请求包含多个协程,比较麻烦,可能需要定义/监听多个channel, 而context在父协程取消后,所有的字写成都会退出。 [参考](https://zhuanlan.zhihu.com/p/68792989)
9. 逃逸分析。 传参结构,则在栈上分配; 若参数通过指针传递, 则逃逸到堆上, 增加GC压力

2.2.2 Python

2.2.3 C

1. 编译过程。 预编译(预处理,如宏展开等)->编译(代码到汇编代码)->汇编(汇编代码到机器码, 得到多个目标文件)->链接(链接多个目标文件, 得到可执行文件)

2.2.4 PHP

2.3 网络 4 2

2.3.1 网络分层

1. 应用层。 http
2. 传输层。 Tcp/udp
3. 网络层。IP、路由器
4. 链路层。 以太网

2.3.2 TCP

1. 建立和断开。三次握手。 四次挥手:TIME_WAIT既为了实现可靠的断开, 假设client的ack, server没有收到, 那么server回再次发FIN, 此时如果client没有等待, 则报错; 也为了防止出现老的重复报文, TIME_WAIT状态的ip端口无法建立新的连接, 而过了2MSL, 已经可以确保老的报文已经不存在。     [参考](https://zhuanlan.zhihu.com/p/73726369)
2. 粘包问题: 固定消息长度; 消息显示增加边界; 消息头和消息体,消息头包含消息体的长度  
3. 滑动窗口。 发送方根据接收方同步的窗口大小, 设置自己的滑动窗口大小。  
4. 流量控制。 接收方通过同步窗口的大小, 达到流量控制的目的
5. 拥塞控制。拥塞窗口。 慢开始探测(1 2 4 8…), 成倍的增长需要设个上限,上限后只+1的速度增长; 若出现拥塞, 则直接把倍数增长的上限设置为当前的拥塞窗口的一半, 拥塞窗口从1重新开始, 从而实现拥塞避免; 快重传/快恢复
6. Http&https。   Tls/ssl加密。 先通过公私钥交换对称密钥, 然后用对称密钥加密后续的传输数据

2.3.3 UDP

1. 可靠性提高:冗余包、重传、根据传输速率调整滑动窗口
2. 支持广播、多播

2.3.4 网络模型

1. Select。 select每次需要把所有fd拷贝到内核态, 然后轮询所有的fd;  上限
2. Epoll。 只轮询就绪的fd列表; 边缘触发:系统状态发生变化, 即空到有/满到空。 水平触发:系统调用比较多, 只要有数据就回一直通知

2.4 安全 3 1

2.4.1 常见WEB安全问题

1. Xss。 不相信用户的输入, xss过滤函数
2. sql注入。 web应用的db操作权限; 对用户的输入数据检查; 检测工具
3. Csrf。 恶意网站在用户不知情的情况下, 拿着用户的cookie请求服务器。 加随机数校验

2.4.2 常见加密过程(TSL)

1. client向server请求非对称密钥的公钥
2. client端生成随机密钥, 并用server端的公钥加密,传输给server
3. server用私钥解密拿到随机密钥
4. 后续的交互数据都通过这个随机密钥进行对称加密

2.5 分布式 3 3

2.5.1 CAP 和 BASE

1. CAP。一致性、可用性、分区容错性
2. BASE。基本可用、软状态、最终一致

2.5.2 一致性

1. 两阶段。准备阶段(执行事务不提交)+提交阶段(commit or  rollback)。协调者的单点问题、数据不一致的问题。 引入协调者的超时机制和参与者的互询机制 
2. 三阶段。第一阶段不执行事务;    2CP和3CP都可能存在数据一致问题
3. TCC。 Try阶段:预留资源; Confirm阶段:默认不会失败,失败则重试,超过阈值告警;  Cancel:执行错误,回滚,释放预留的资源。 侵入性较高
4. Paxos
5. Raft。Leader:同步, Fllower:执行Leader同步的消息, Candidate:选举过程的临时角色。 选举过程:当没有收到leader的心跳, 递增自己的term, 给自己投票; 广播给其它followers, 若是Leader,且term大于自己的,把自己转变为follower; 超时是随机的,从而有效避免同一时刻多个follower同时发起选举

2.5.3 缓存

1. 基于缓存key的一致性hash
2. 主备
3. 缓存雪崩。 大量缓存同时过期,请求都到后端存储服务
4. 缓存穿透。 请求了缓存和DB都不存在的Key(一般恶意)。 缓存空对象+布隆过滤器

2.6 锁 2 2

2.6.1 分布式锁

1. Redis

2.6.2 常见锁类型

1. 乐观锁
2. 读写锁
3. 互斥锁。 获取锁失败的话,进入休眠, 待内核唤起
4. 自旋锁。忙等待一小段时间

2.7 数据库 5 3

2.7.1 mysql

1. 引擎:innodb,支持事务 ; myisam
2. B+树: b树的话本质是多路二叉树; b+树是b树的变种, 只有叶子节点存数据, 且增加了叶子节点的指针连接,方便范围查找(如10<a<20, 找到10顺着指针就能找到20 ), 二分
3. 索引:聚类索引, innodb的叶子节点保留完整的数据记录; 非聚类索引,入myisam的索引文件和数据文件分离, b+树的叶子节点只保留了数据的地址
4. 事务隔离级别: mysql支持可重复读,存在幻读问题, insert 情况下, 两个事务, 一个insert了, 另外一个select不到,且insert也会失败
5. 锁机制。 类型:表锁, 行锁; 粒度大的话,并发性小。 innodb支持到行锁, myisam只到表锁

2.7.2 redis

1. 五种数据结构及底层实现。String:简单动态字符串;   Hash:冲突解决--链式哈希; 链表过长,需要rehash, 两个hash表,渐进式rehash(对老的hash表操作时,同步一份到新的,add操作只在新);   List:双端链表;   Set: hash表, value为空;       Sorted set: 跳表。 多个forward指针(跳跃指向后续的), 一个backward指针,一个score(用来排序); 查找位置时间时间复杂度logn; 类似二分
2. 网络模型。   单机8w并发。     i/o多路复用: epoll:fd回调函数把就绪的fd加入就绪的fd列表, 遍历时,只要遍历就绪列表;  et:系统调用少,状态变化才触发,read/write到出错,否则会出现还有数据但是没有通知;LT模式,系统调用多, 有数据就一直通知。   select:用户态到内核态的拷贝,要遍历所有的fd,且有上限1024个。    单线程: 避免了上下文切换,  锁竞争
3. 过期策略。 惰性删除(设置过期时间,访问时判断),长久无访问的key, 耗内存;     定期删除, cpu消耗比较大
4. 持久化。 Rdb: 数据快照。子进程处理。 按照一定的循环策略, 把内存的数据dump一份到rdb文件。 数据恢复快,但是断电,数据易丢失。  aof:增量策略。 命令写入文件。 不易丢失, 但恢复慢
5. 事务:队列, 只会检查语法
6. 分布式集群部署。  Key hash环。 虚拟节点。 主备

2.8 中间件 3

2.8.1 rmq

2.8.2 etcd

2.9 业务架构设计 3 2

2.9.1 解法框架

1. 难点
2. 映射的后端技术点
3. 如何解决

2.9.2 秒杀活动设计

1. 特点。 短时高并发;   数据一致性;  后期的数据分析
2. 隔离。 秒杀服务单独部署、单独数据库,不影响正常的业务
3. 流量过滤。 小白:前端按钮置灰; 高手:接口做访问频率限制; 读多写少,使用缓存, 写的话排队
4. 数据一致性。 排队;   事务(DB+缓存)
5. 压测(熔断、限流)、监控

2.9.3 朋友圈设计

1. 特点。 好友数比较小,适用写扩散。  主要包括发布、图片、评论点赞、时间线
2. 流程。 发布(上传图片到COS,写发布表)、触发通知好友(写好友的时间线表)、评论点赞对应动态的(包含过滤非共同好友)。  相比读扩散,写扩散比较收敛(朋友圈场景)
3. 容灾。  多个园区 +  多数据中心

2.9.4 聊天服务

1. 特点。 一对一聊天+群聊
2. 通信。 Websocket
3. 服务。 登录+在线服务,通知服务,存储服务(kv)

2.10 云原生 3 1

2.10.1 容器

1. 雪花服务器,环境一致
2. 镜像的构建,指令创建新的镜像层提交,docker build,  push, 分阶段构建
3. 编排。 k8s
4. 资源的隔离: 命名空间, cgroups

2.10.2 K8s

1. 声明式api, 定义最终的状态
2. 架构。 MasterNode: API server(增删改查指令), scheduler(pod调度到满足条件的Node上), controllmanager(维护集群的状态);    WorkNode: kubelet(维护node上的生命周期),pod: 最小的调度单元
3. 网络: Pod内通信, 共享;  同个主机不同pod: bridge, ip段; 同个集群内不同的node, flannel, 不同主机ip上的podip为不同的网段(通过etcd存储网段和主机ip的映射);   外部的流量:service, 通过主机端口, ingress, 域名+路径路由到不同的service
4. Service 到 pod转发。   servervice维护一个Endpoints, Endpoints包含Podip列表, 有pod消亡/新增, 更新Endpoints。     轮询/固定去转发请求到pod