寻找好的方法,只要方向对了,剩下的只是时间问题,做时间的朋友!
2020-11-23
从答辩PPT内看到的关键信息
- 金字塔PPT设计
- 框图规整
- 技术影响力(内部:码客、开源协同、工蜂,外部:Infq、StackOverFlow、Github)
- 系统、框图成体系化
- 对团队贡献(招聘、带新人、分享),解决团队痛点问题
Tips:多参与、产出、总结,内化为自己的能力,帮助团队和自己成功!一定要做好总结材料收集,日常工作中,多记录内容;
2020-11-26
微服务基础设施
- 分布式系统中,进程如何通信
- RPC框架选项:社区活跃、文档、多语言、开源、
- 性能:序列化协议 Hession
- 替换成本
- 微服务组件、生态:通信、注册、配置、负载均衡、断路器
- ServerMesh
- 实践经验
- 规范化、标准化
- 服务保护:过载保护(做限流、做熔断)、降级、异常处理
- 服务健壮:
- 流量容错(failfast、failover、backup request)
- 调用方对服务状态感知、框架端到端心跳弹活检测
- 多样化调用方式支持:异步、Oneway调用、泛化调用
- 服务集群流量管理
- 服务调用,调用方如何找到对端地址
- 服务扩容,调用方如何发现新节点
- 服务保存,如何让故障节点失效
- 注册中心
- 服务注册中心:服务节点向注册中心登记(ServiceName、IP、Port)->客户端订阅(ServiceName)->中心推送(IP、Port)->业务调用
- 服务扩容:新注册节点注册->中心推送->业务调用
- 服务节点异常:服务节点周期与注册中心健康检测、中心异常推送给客户端、客户端摘除异常流量节点
- 路由策略:
- 选项:ETCD、Zookeeper、Eureka、Consul、Nacos
- 注册中心搭建经验:
- 弱化注册中心依赖
- 减少不必要数据交互
- 优先保证可用而非一致(AP > CP)
- 问题定位
- 分布式链路复杂
- 监控:https://peter.bourgon.org/blog/2017/02/21/metrics-tracing-and-logging.html
- 日志分散,将日志进行集中化
- Metric指标:QPS、分位数延时等
- 分布式链路追踪Tracing
- 团队如何协作
- 业务职能组织(产品、设、前、后、运维)
- 康威定律
Go并发编程实战
- 互斥锁解决方案:Go通过使用Mutex互斥锁/排它锁实现对临界区访问解决,解决多个GoRoutine同时访问临界区导致的并发问题
- 同步原语/并发原语,解决并发的数据结构,Mutex、读写RWMutex、并发编程WaitGroup、条件变量Cond、Channel都是同步原语
- 场景
- 共享资源:数据竟态条件,并发共享资源,需要通过Mutex、RWMutex来保护共享资源
- 任务编排:让Goroutine按一定规律执行,通常使用WaitGroup或者Channel实现
- 消息传递:不同Goroutine之间通过Channel通信
Locker接口
,包含Lock()
与Unlock()
方法,Mutex、与RWMutex都实现了Locker接口,一个Goroutine持有Lock()
锁后,其他Goroutine再执行Lock()
会被阻塞- 经典并发问题,
count++
非原子操作,成为了竟态资源,参考:https://blog.golang.org/race-detector, 编译器通过探测所有内存访问,加入代码对内存地址读写访问的监控,代码运行时候,race detector
就可以监控到对共享变量的非同步访问,出现race时候告警;race detector
已成为Go持续集过程中的一部分。
|
|
race detector
检测与分析- 在编译、测试、运行Go代码时候加上
race
参数,就可能发现并发问题 go run -race counter.go
,可以发现不同Goroutine对同一内存地址有读写操作- 因为要通过真实的地址进行读写访问,所以并不能在编译时候发现,只有在触发了
data race
时候才能检测到 - 开启
data race
比较影响性能 - 查看编译后的汇编代码:
go tool compile -race -S counter.go
,可以发现runtime的racefunceter、raceread、racewrite、racefuncexit
等方法
- 在编译、测试、运行Go代码时候加上
Mutex
- 零值表示未加锁状态
- 支持将Mutex嵌入到其他struct结构体中
- 通常将Mutex放在控制共享字段之上,并加行空格(风格问题)
- 可以将获取锁、计算逻辑、释放锁封装成一个方法
- 释放锁通常基于
defer mu.unlock()
实现,但注意如果跨度很大,锁定时间会比较长,考虑拎出来
- 锁释放,等待锁的哪个Goroutine被唤醒?
- tradeoff:复杂度、性能、结构设计权衡
- 简单实现:flag标记是否持有锁,基于CAS(
compare-and-swap
或者compare-and-set
)将flag设置成1,标志当前goroutine持有锁 - 给个机会:新goroutine有机会竞争锁
- 多些机会:新的和被唤醒会有更多机会竞争锁
- 解决饥饿:防止gorotuine等待太久
- 简单实现:flag标记是否持有锁,基于CAS(