P202 raft选主实现
候选人遇到 3种情况会结束:
1.当选leadr
2.其他服务器成为leader
3.卡死
go实现raft选举,raft可以定义一个结构体,根据结构体写代码
1.使用代码实现3节点选举
2.改造代码成分布式选举代码,加入 rpc调用
3.演示完整代码
定义三个节点常量 ,声明leader对象,任期和leaader id编号
**声明raft结构体,
锁nri sync.Mutex
节点编号me int
当前任期current term
为哪个节点投票 voteFor int
3个状态:state 0 follower 1 candidate 2 leader
**
lastMessageTime 发送 最后一条数据的时间‘
currentleader 当前的节点的领导
message 节点间发信息的通道
electch 选举通道
heartbeat 心跳信号的通道
heartbeatre 返回心跳信号的通道
timeout 超时时间
创建一个leader对象。0没上任,-1 没有编号
main函数需要做,三个节点,都是follower。
若有candidate状态,进行投票拉票
会产生leader
创建三个节点
0,1,2作为三个节点的编号
通道也需要初始化。
节点最开始是follower,state=0
超时和领导都没有,就设置0和-1
设置节点任期setTerm,初始化没有任期就写0
设置一个随机数。
可以另起选举和心跳检测的协程
写一个选举的函数
写一个获取当前时间的函数
在循环外部设置标记,判断是否选出了leader
写一个选主逻辑
一个节点想要成为candidate就需要修改状态,candidate状态的时候也是有任期的
遍历所有节点拉选票
设置一个投票数量
设置一个布尔值用于接收投票数是否大于一半的选举者
若选票数大于节点数/2,则成功
成为leader后,向其他节点发送 心跳信号
P203 raft选举完成
有了主以后,可以做一个检查工作,选出领导leader的时候,整个 程序可以break
发心跳也是不能停的
P204 raft分布式选举
make函数进行初始化数据 ,创建三个节点
全局的leader传进去
除了选举,还有心跳检测
有一点错误
分布式选举需要rpc通信,客户端服务端通信,需要之间定义一个结构体。
rpc规范:首字母大写。
心跳检查替换成rpc通信,而不是单机的
心跳里存的数据
加入服务监听,rpc绑定到http上,进行监听
应该还有一个锁的问题
整个一个分布式raft代码‘
传的参数大于1才能跑起来
创建完了注册rpc
parseForm解析form参数
启动多节点,传一个1跟2
已经选举出leader,然后2节点在发送 心跳。
传递一个值,通过日志去进行数据同步
P205 选项设计模式
euerka是aws开发的,不是分布式存储,是主从存储(主从具有延迟问题)。
paxos是从raft里抽取的。
zookeeper是比consul和etcd重量级一些的。是偏向reids,组件注册上去,整个架构的
写一个可变参数,类型也不确定
上面的还是写死的,应该引入选项设计模式解决问题
优化选项设计模式
用这种方式赋值也是很容易的
也就是调用这个方法的时候,考虑怎么传参的问题,只是传了一个option方法类型
现在这些都没有值
比如做etcd,需要初始化etcd的时候传一些参数,参数如果像以前做法(那就是对象,地址),对组件扩展无好处,因为组件扩展性要求建一个传参的对象,之后不管是调etcd还是consul的,这个对象是不变的
现在结构怎么变,都是用下面 的初始化函数
P206 注册组件的分析
调用方根据带的参数调用不同的注册方
反注册的时候,应该是服务宕机了,从注册列表自动删除
P207 注册组件接口实现
etcd存东西,就相当于进行服务注册,目录规划consul和etcd实现,总的接口是registry。
先定义一个interface,传一个插件 名字
第二个初始化init
定义选项设计模式,定义一个options。定义一个函数类型的变量
定义好之后,具体怎么给对象进行初始化,前面的init调用这些就传参了
做其他的就实现一个init,这样传参,接口就不需要动了
** 建一个服务对象,Name stng `json:“”name,后面的是tag **
服务注册接口,和服务反注册接口,服务发现应该返回一个总的service对象
P208 服务组件上层架构
声明一个管理者结构体,里面维护一个map所有插件
没有的进行注册,有的进行初始化
注册往map里加东西,那就要锁
锁,解锁,先看看map里有没有具体的名字
进行注册中心的初始化,总的初始化去调具体的初始化。
1.先查看 服务列表,服务是否存在,若不存在,就没的初始化,报错
2.存在,返回值赋值
3.进行 组件初始化
外部调用initRegistry
P209 一个s惹的祸
整个流程大致如下
设置续期和设置kv对到etcd,keepalive一直保持一个续期
启动etcd
存进去了,这就是这个id
连接etcd的时候要设置一个版本,linux和windows不一样
如果是使用github上的etcd包就会报错
这里是etcd具体实现
P210 面试题
调用函数,结构体赋值
for循环的问题,开了多个携程,性能好的电脑,一下就执完了
这样就不会乱了
相当于每次都引用外部的,所以值恢复正常
因为这个map是随机数,时好时坏,加上一个锁 就行
make初始化chnnel,map,new初始化对象
除了可以改等于号还可以改地址
接口有值类型和指针类型。
值类型的接口,指针类型可以存进去
指针类型接口,值类型存不进去
这样就存进去了,map里结构体无法直接寻址,必须取址
打印一个result结构体
其实是因为这个S需要大写
堆就等于储物间,栈就等于小柜子,变量名会分配在栈中,值会在堆中,也就是a会指向堆里的xxx
区别
栈stack,由编译器自动分配和转发,存变量名、各种名
堆:在C里有程序员分配和释放内存,go自动了、存栈变量的数据值
make(xxx) a:=3 a就在栈,3在堆
P211 服务发现的原理
map底层是一种树,红黑树,比较重量级,所以造成map效率比切片小的多。
注册就相当于往etcd里写数据
P212 gRPC
grpc客户端 和服务端可以在多个环境运行。
数据格式是protobuf,需要用定义proto files创建服务,用message类型来定义方法参数和返回类型
proto files其实就是把不同语言的交互,翻译成一种语言
如果google下载不下来,可以把编译好的包放到bin下
proto语法就是三个修饰词,required就是必须,optional可选,repeated可以包含0-N个元素,可选的
使用service定义就相当于一个接口,会自己翻成go语言的方法
proto3是版本,2跟3翻译出来的代码有些不一样
proto3支持map类型
可以试着写一个服务
写一个grpc服务一般两个文件,proto文件夹存proto文件
repeated是一个可变数组
接口需要这个方法
根据文件生产具体代码
定义的时候字段名如果小写,翻译成GO会自动变成大写,序列化和反序列化的过程
它也有服务端调用,和客户端调用的思路
P213 gRPC客户端服务端
根据之前生成的服务接口的参数复制下来
通过用户名查用户信息
grpc服务先监听
定义一个空接口
注册服务
注册完服务可以启动server
写一个客户端调用服务端
实例化客户端,传的是连接
客户端启动,就查到了用户
P214 go-micro介绍
gomicro是一个插件化的基础框架,可以构建微服务。之前实现了consul服务发现,新的改成了mdns,通过http协议,数据传输协议使用protobf和json
跟grpc对比,差别在于可插拔接口
这里就是一些插件
跟之前定义的接口一样,里面定义方法
通信相关接口,这里代码就是定义一些interface
编解码接口
根据不同算法请求主机列表
推pull拉push,watch
P215 go-micro HelloWorld
写一个go-micro的helloworld
go_out代表这是i一个go语言的输出
接口下定义方法名
具体操作都是在handler里调用
写一个服务
name就是设置服务注册的服务名,用来在注册中心进行访问,上面定义了请求响应的结构体,下面new了一个微服务实例
使用编译好的go工具
可以点进去查看初始化传的参数
注册时候 100微妙判断就超时
注册服务,启动服务
现在启动,地址和端口注册的时候 都有默认值,基于mdns做服务发现
现在就可以使用micro命令访问
P216 go-micro案例
proto目录就是放protobuf文件的.
写了一个call方法,下面还可以加其他方法
两个接口,两个方法
micro_out是生成的gomicro文件,点代表输出当前目录,–go_out输出pb.go文件,点代表当前目录。这里是pb和生成micro文件
一个example结构体,还有一个foo结构体,call绑到example上
有值就进行处理,没值就报错
有一个通信 接口是需要监听传输数据的,这里就是把要用的服务注册中心都初始化了
第一启动api服务,第二运行服务端代码
连接到api服务,基于mdns进行注册
加一个数据,以json格式
收到请求
P217 项目搭建
请求fool接口
做一个卖票的项目
查看user定义,写一个service,service下有各种接口
登录的结构体,使用 email和密码,登录之后返回useid,username和email,phone。
每个功能都有请求和 响应的结构体
pb下就是各种生成的go文件
这些都是服务模块
用户服务其实就是用户一个模块
share是工具文件夹,放一些pd文件,db.go数据库初始化
数据库配置当成一个配置文件
一些公共定义的异常
建立一个库,执行db.go会创建user表
也需要在src下创建一个vender,项目需要用到的包
创建一个api-srv作为api网关
utils是一些工具包
一个打印日志和找路径的工具就够了
在专门的proto文件夹下写proto文件
package pb:把包安装到pd目录下
定义需要的结构体,对应之前的4个字段
除了表结构的结构体,增删改查也需要定义请求传参和响应的结构体
响应结构体
删除用户结构体
改用户结构体
查用户结构体
方法的参数返回就用上面的结构体就可以
这就是生成的
下面就可以开始具体编码
P218 go-micro项目
增加entity目录放实体类,handler处理user的事情
三层架构思想,1结构体定义,
2.定义方法绑定结构体,返回结构体对象
返回*号,才能成功赋值
db做一些初始化操作
user.go就是一些增删改查
handler写user方法
也是先申明结构体
P219 docker介绍
配置中心
系统指标
宕机检测程序
硬件故障探测
故障迁移流程
网易云