之前去过几次相关 go 的线下 meetup,这次相对来说比较大型一些,两天的听下来还是比较烧脑的,光是记录的笔记都有近千行了,整体来说收获很大。
有的人问,值票价吗?我回答:对喜欢的投资没有不值得的。对我来说值了~
有的人问,值得去吗?我回答:不一定,因为可能在很多大佬看来能听到的点不多(采访了几位现场的大厂观众,普遍表示只有其中 1 到 2 场满足他们的要求)但是如果你的小白或者一年到两年左右,还是能见识很多东西的。可能是我听多了,和之前自己学到的有点重复…
下面是个人精炼总结,全是个人总结,自己如果对这个知识或者相关点比较清晰的我就没有记录了。其中会伴随一些个人思考和疑问,可以小声 bb 。大会分 1和 2 会场,所以只能选其中一个听,我也是记录我自己听到的,另外一个会场不清楚(我交叉穿来穿去的)注意并不是有的老师讲的真的不好,而是对我个人来说意义不明显,可能由于知识点已经掌握,也可能是由于工作上确实用不到哦
最后会附上会上笔记,仅做个人使用,乱了也不管~ 最后无论如何,感谢每一位老师的付出~~~
我建议下面几场没听的可以去听下,至少对我来说收获比较大:
当然还有几场我没听到的据说也有很多金子,后面再想办法看看吧。 PS:英文的那场普罗米修斯真的对我来说太难了,语速真的超过我的理解能力了,抱歉是我不行。
-/以下为 大会上 笔记 边听边盲打 易错体质/-
结合业务需求需要一个轮子,需要一个分布式存储
业务:其实更多的业务场景不需要分布式事务,更多是通过补偿机制来完成的。是否需要强一致性的业务?
解析 sql
逻辑优化器:列裁剪、谓词下推、聚合下推、topN 下推
执行器优化:从“火山执行器”走到“向量执行器” 以列为单位去处理
hash:使用 hash 之后之后取余之后存储
rehash:需要将机器上的数据扫一遍,有点慢
中心化:超时,网络分区,使用的是这个
无中心化:gossip 收敛会慢
其实就是通过心跳检测去监控故障检测
使用分布式锁,直接进行选举,没必要讲究什么公平性,只要抢占的越快负载越低,直接当选即可
当故障进行恢复的时候,所有的请求直接打到一个新的从节点从而导致峰值,解决方式是偶尔将请求发送给从节点,从而保持从节点的热数据
时延从 19ms - 3ms
有针对磁盘的存储进行优化
词法分析的优化暂不考虑
goroutine 限制和泄露,使用 goleak 来进行检测 http://github.com/uber-go/goleak
忘记 defer cancel 导致 context 泄露
主要还是依赖 pprof
尽量减少对象分配,进行逃逸分析,尽量分配到 stack 上去,在外部申请对象,将对象的指针传入到 function
将在 2021 年开源,物理优化,同步复制,Range 分区(因为分区的原因,其实是去每一台机器上去查一遍然后进行聚合,暂时没有好的解决),生态
对于 join 的查询支持是不好的,还是有可能出现所有机器进行扫描全量数据的可能性
左耳朵
推荐使用 receiver 进行
使用 对象 进行实现 接口,进行解耦 EX: io.Reaed / ioutil.ReadAll
使用 RFC3339 的时间格式进行交互
使用嵌入或者聚合来做设计
使用 IOC 进行控制翻转来设计
if err ≠ nil
使用 closure for error
bufio.NewScanner(
想法还是包装一次,使用一个 error 的一个局部变量,当有错误直接 return,否则进行处理
使用包装 error %w
使用 config 进行传入,使用 withOption 进行
使用 Mapreduce 进行函数式编程
SumIf、CountIF,FileterIn
使用反射进行 transform 进行处理更加优雅
Verify function signature
可以用它来去类型
使用类型检查和反射来使泛型操作
go generate,使用代码生成来生成你的不同类型的操作
可以使用 gen
别 cv 了,类型检查比较慢,使用 gen 有成本(代码量膨胀),reflection 代码比较难
使用包装函数来包装一个函数的前后方法
还可以使用 defer 进行包装调用
EX:http server
visitor,使用嵌套进行包装,并且进行内部进行调用装饰处理,这样的就可以实现一个 receiver,进行多个 function 的调用
确实比较绕一点,优雅
使用一个函数的输入输出来进行 pipe
或者使用一个 channel 进行解耦,可以写出 类似 linux pipeline 的编程模式
tree - model
api pool
grab-kit
可伸缩、容错、观察
支持 http/rpc
目标就是去简化 go-kit 的开发过程
datadog,商用的,通过启动时进行注册,打点会直接相关数据直接扔到上面去
会有一个默认的 dashboard 的进行展示
候选集合 - 过滤 - 重排序 - 后排序
从移动端的日志流,进入数据湖,train 会生成模型,然后不断进行训练修改,deploy 到线上,然后提供 api 进行调用
模型很复杂、训练样本,特征,都会有影响
模型和模型之间有很多关联关系
训练样本很多,很多时候特征不是很重要,但是计算复杂
特征还好发生变化,模型和系统之间的交互很复杂,对于你的环境造成很多影响
反馈环导致准确率不高,很难评估和验证
需要提供完备的监控来保证这个
将所有的 CI\CT\CD 持续训练,通过 devops 来的想法,将整个流程自动化起来,降低交付成本;
准备数据,训练,实验,部署,监控
Hierarchiacal Temporal-Contextrual
LightGBM
*使用 kubebuilder 进行 build 构建
注册发现:
交付的不只有业务,包括监控,告警,中间件,限流,跨域,认证,调用链追踪等等,插件的部署
交付角度:
http://github.com/go-chassis/go-chassis
把你的后端服务作为一个资源使用;注意这个并不是一个微服务的体系,这个还是有区别的;
面向用户来说,定义接口,定义插件安装api,然后提供 api;
将不同的请求转换成一个一致的协议,然后到一个统一的中间件进行治理;所有的请求都将转换到一个 invocation 进行调用;
通过申明试的调用,对自己的流量进行描述,然后限流策略,那些接口等;
熔断,复杂均衡等都是通过申明式实现的
收益:其他的业务团队可以减少开发,很多提供的能力都可以复用来看
单体对于配置管理很简单,但是分布式的时候配置管理就需要进行配置治理;
source 概念:当发生一些配置变更的时候,将触发不同的 event 然后分发到不同 listeners
统一的接口层,运行你注册业务逻辑,有基本的 start 和 stop
支持不同的编程模型
利用一个装饰器的模式,进行一个修饰,将框架的东西加进去,利用插件的方式安装进去,利用配置文件,指定不同的协议,都可以
优雅停机:基本的系统信号都会捕捉,保证所有业务请求都处理完成才会真正的 shutdown
提供 pre、post 等自定义之后
go 1.8 之后已经支持优雅停机了
最小化容器的大小
最小化安全漏洞
最小化代码量
最小化复杂度
其实是将很多依赖都搬运到了 extention 中
bootstrap功能:任意替换默认实现,加载并允许新的模块供运行时提供和使用
跟流量相关的治理功能都可以沉降到服务网格中
后面可以将功能进行云原生
毛剑
初始化 api 定义;将所有的初始化的方法都来一遍,很麻烦
需要将所有的配置对外暴露,其实就是搞个 config 一个对象来进行初始化
*对于一个 public 方法不要传递一个 nil 来进行
每一个 withoption 都是可以进行使用的
当 option 为 nil 使用 default 进行替换
独立去维护每个 option 文档
还可以保留状态,使用 defer 进行状态还原,-vvv
还定义 Option interface 在 before 进行前后进行操作
你的 api 和你的配置文件不应该强绑定
*google sre 运维
将你的配置文件转换成 Config 对象,然后让 Config 对象提供一个 Options 方法,然后将配置返回成 Options slice
这样就能保证使用 json 或者 yaml 格式的配置文件,也能支持 option 方法的 function 设计
配置中心方便了配置变动,那么更加容易出错;
配置分为动态配置和静态配置
静态配置热加载是很有风险的,所以不要进行配置热加载,任何一次配置变更都走一个迭代版本;
动态配置还是通过后端数据进行拉取更加靠谱;
讲如何做一个 BFE 的,是怎么构成的?
一个统一的七层流量转发平台,在内网跨机房的调度
一个专用的转发引擎
对于流量的转发
支持春晚的红包
对技术足够痴迷,一个东西做 5 年做 6 年去做,寻找的真正的 SE
30 开始只是写代码无数必备素质之一
看中寻找和培养人才,只有把人培养好
看中过程:如果没有正确的方法,成功只是偶然
只需要 975,需要聪明的工作,平衡了工作和生活
意识 =》看见 =》行动
研发方向的确立
以一个研究问题的角度,去解决,直接对标了国际上的论文去专门研究
通过趋势的判断,来指定产品的角度
正确、性能、可读、可维护、共享、重用、运维、运营
一个 commit 添加 187 条 commet
不断地抽离可以复用的基础库
建立基础库的前提 → 知道怎么切分模块 还是需要抽象的能力
文档本身也是产出:codeing 时间少于30%
写文档是整理思路的过程:打字的速度应该快于思考的速度
没有文档后期会花费更多的维护成本
简单的项目也需要文档
文档不是补出来的
《软件开发的 201 个原则》
文档和代码都是一种沟通方式
好的管理比好的技术更重要
项目的规划和启动
周报
迭代管理
项目总结和回顾
lite weight process
正规科学的研发方法,提升工程能力,才是解决之道
复杂系统并不是的技术无法实现,而是因为工程能力没有正确的
单一目的 single purpose
数据封装
《代码艺术》
https://github.com/didi/nightingale
在流量转发层做文章
统一机器初始化
统一权限,统一日志,统一审计
自动化工单,知识库构建,答疑
资源占用少,适合开发 agent
静态编译依赖少
运维相关的东西都是用的 go
安全稳定高效低成本
监控标准
故障的响应原则
漏报率是一个比较重要的指标
预防、发现、定位、止损、富婆
应急备案
带外装机管理、堡垒机跳板、机器初始化
日常工作平台化
重复工作自动化
ChatOps 各类聊天机器人
知识库
夜莺
任务执行更新
支持 ansible saltstack 批量执行脚本,权限可以控制的更针对一些,审计方面,轻量级一些
主要还是一个运维工单的能力来进行的一个构建,能够帮助一个新的公司快速构建一个运维体系
想要支持 M3
所有的模块都是高可用的,体系化程度更高
http 接口的成功率,延时,产品化程度更高一些
对于物理机虚拟机的监控更加支持一些
七牛
作用于有限的领域
作用于科学领域
数据规模非常的大
python 让数据软件平民化
python 做不了基础设施?
在 go+ 之上做数学软件
和 go 完全兼容
语法、代码简洁
所有 go 的包都可以直接引用
go+ 源码 - ast - 双引擎 - 字节码或者 go 源码
token 和 parser 是生成拓扑序列的
冷板凳?其实做语言本身是很难得,很少有人愿意去学习解析语法等等一些功能
runtime 相关问题
案例:
多个 goroutine 向 channel 写消息,一个 for 循环去处理这个消息,发现延迟很高
调查:
从网络可读到到 goroutine 被调度唤醒可以处理请求,出现 4.x ms
在混合负载中 由公平调度导致的
找操作系统分配内存,都是 runtime 决定的;真正用到的就是 inused memery
runtime 会估算自己要用多少,不会马上归还操作系统,会保留一些
操作系统有一个快表,TLB,默认的一个页大小是 4k,经过虚拟地址和物理地址的映射
透明大页:它把每页的大小改大
案例:
开启透明大页之后发现内存很大
从操作系统层面看到内存量很高,但是实际使用不高
anonHugePage
和 transparent huge page 开启相关
分析:
当开启之后 THP 在 go 的视角里面其实释放了,但是因为页大,所有操作系统看来,有的页还有内存碎片,所以无法回收
操作系统会有对内存进行调整
go gc 有一个优化,写屏障;
当垃圾回收的速度跟不上分配的速度怎么办?
go 会拿 25% CPU 时间,超过 25 之后就会让分配慢下来,进行清扫工作
案例:
请求响应不正常,cpu、io、网络都没问题
抓 go 的 trace,发现请求有被 GC 占用了很多时间
即使没有 STW,但是 runtime 还是会让它慢下来
发现扫描了 1G 的内存,但是只是发现只有 8k 被回收
依然会有抖动
*抢占主要解决 for 死循环导致 STW 时间过长的问题
在多核下的单一进程,没有多进程绑核来的快
资源没有被耗尽但是还是有瓶颈,CPU 使用率变高了,NUMA
分析:
pprof/mutex 去查了一下,优化了一下
是不是和 NUMA 绑定核心有关?
单个改动的性能提升最大
发现 67% 时间没有在干活
runtime 在页分配器是有锁的,会有锁的争抢,在多核的情况下会遇到
现在的 go 的版本已经优化了
现在 CPU 核数很多,每个 NUMA 核心上尽量会分配到和自己近的
gc is not numa aware
所以在多核上的调度不是特别
汇编语言无法构建大型系统
计算机复杂度理论
将不同的语言增加,需要有不同的机器,将不同的语言编译成不同的机器需要很多任务
简化:
将别的语言编译成 C 然后再编译成别的语言
将别的机器先编译成 x86,然后再编译成目标机器的语言
高级语言先生成 AST 然后再 SSA IR 单一静态赋值
基于 SSA 的优化
LLVM
中断接受中间表示进行优化,对每种机器机械能优化
将源代码翻译成 AST
编译器会进行常量折叠,会将 2*3 → 6
内联:会将 B 函数调用 A 函数的函数方法直接内联到函数内部,为了提高效率
更像汇编语言
赋值,goto,if。。。
公共子表达式消除,将重复运算减少;
运算强度消除,将乘法进行优化成位操作,或者是取余操作替换为&操作
常量折叠:将两次乘法合成一次乘法
-循环不变量外提、将乘法变成加法
将 IR 映射到汇编
go 在云原生中的应用
标准化技术,标准化运维
从资源统筹规划,大规模的自动化运维
让云更经济的被用户使用
go 在 CNCF 中占据了很大的部分
策略是做事的概念和计划,坐火车和坐飞机是一种策略
机制是面向内部实现的,机制是追求稳定和复用
策略:部署策略,负载均衡策略,路由规则,工作负载
直接面向机制很难;
认知成本高,k8s 没有统一的使用方式,我们需要学习复杂的申明字段,各种申明
对开发者很好的使用这个平台,融入云原生
label 是一等公民:通过它去寻找
事件触发闭环反馈
由很多的控制器组合来完成的
阿里云云原生 PAAS 平台
将所有平台的运维能力,将所有的控制器都部署到了 k8s 的平台;
open application model 微软和阿里
一个应用是由很多个组件构成,每个组件都有自己的工作负载去描述运行时(有状态/无状态…),有了不同的运维特征
路由策略,基于 QPS 的自动弹性,这些都是运维特征
多个组件可以通过一个作用域来描述,这几个组件的资源限制
组件间依赖
内置 workloads Traits 和 Scopes
其实还是通过一个控制器模式,将上面模型中的所有资源进行初始化,配置,调度,向上包装一层
声明试资源的设计,一定要一个终态;
可重构的状态机,期望状态,你状态是可重构的,事件驱动+主动轮询
重试和幂等,自愈
有一个资源是成功,很多人同时修改,利用 version 和 resoureveriosn 做乐观 observeVersion
如果应用没有到终态,是因为什么原因;
抛出 k8s 的事件和消息
控制器的管控平台,来管控制器的状态
通过应用模型描述好了,我们只需要提交代码即可
运行时的依赖也标准化
轻量可观测,开发和运维的区别就是观测上的区别
*datr,全部都已 sidecar 的进行封装了
*将噪音在前面就消除,宁愿什么都不动,也不要动错
基本就是将代码解析成语句
初始化的时候就将不同的数据库版本来生成不同的配置,对于 sql 进行不同的版本生成
hits 对前后进行封装
对于不同的数据库实现都是不一样的
读写分离的支持,加入一些判断
指定字段,通过传入一个 map 也可以
直接指定字段
使用 map 或者 struct 去创建
支持自定义类型就可以支持 json 类型的数据
自定义分页逻辑
支持全局关闭事务
使用 transaction 块
支持事务嵌套,使用安全点实现
可读,可写,禁止操作等