上传项目说明文档补充
This commit is contained in:
parent
4372d4d283
commit
7e8bafb965
336
README.md
336
README.md
@ -542,3 +542,339 @@ func (this *Api_Comp) QueryUserPackReq(ctx context.Context, session comm.IUserSe
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### lego 微服务构架 服务发现 registry 注册表系统
|
||||||
|
- 服务节点定义 registry/core.go
|
||||||
|
```go
|
||||||
|
//服务发现系统 定义每一个服务节点的结构对象
|
||||||
|
ServiceNode struct {
|
||||||
|
Tag string `json:"Tag"` //服务集群标签
|
||||||
|
Type string `json:"Type"` //服务类型
|
||||||
|
Category core.S_Category `json:"Category"` //服务类别
|
||||||
|
Id string `json:"Id"` //服务Id
|
||||||
|
Version string `json:"Version"` //服务版本
|
||||||
|
IP string `json:"Ip"` //服务Ip
|
||||||
|
Port int `json:"Port"` //端口
|
||||||
|
RpcId string `json:"RpcId"` //服务通信Id
|
||||||
|
PreWeight float64 `json:"PreWeight"` //服务负载权重
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- 集群服务启动时 底层会默认启动 registry 系统 实现集群内的服务节点互相发现
|
||||||
|
```go
|
||||||
|
// lego/base/rpcx/service.go
|
||||||
|
func (this *RPCXService) InitSys() {
|
||||||
|
//初始化日志系统
|
||||||
|
if err := log.OnInit(this.opts.Setting.Sys["log"]); err != nil {
|
||||||
|
panic(fmt.Sprintf("Sys log Init err:%v", err))
|
||||||
|
} else {
|
||||||
|
log.Infof("Sys log Init success !")
|
||||||
|
}
|
||||||
|
//初始化事件系统
|
||||||
|
if err := event.OnInit(this.opts.Setting.Sys["event"]); err != nil {
|
||||||
|
log.Panicf(fmt.Sprintf("Sys event Init err:%v", err))
|
||||||
|
} else {
|
||||||
|
log.Infof("Sys event Init success !")
|
||||||
|
}
|
||||||
|
//初始化注册表系统
|
||||||
|
if err := registry.OnInit(this.opts.Setting.Sys["registry"], registry.SetService(this.rpcxService), registry.SetListener(this.rpcxService.(registry.IListener))); err != nil {
|
||||||
|
log.Panicf(fmt.Sprintf("Sys registry Init err:%v", err))
|
||||||
|
} else {
|
||||||
|
log.Infof("Sys registry Init success !")
|
||||||
|
}
|
||||||
|
//初始化rpcx 系统
|
||||||
|
if err := rpcx.OnInit(this.opts.Setting.Sys["rpcx"], rpcx.SetServiceId(this.GetId()), rpcx.SetPort(this.GetPort())); err != nil {
|
||||||
|
log.Panicf(fmt.Sprintf("Sys rpcx Init err:%v", err))
|
||||||
|
} else {
|
||||||
|
log.Infof("Sys rpcx Init success !")
|
||||||
|
}
|
||||||
|
//监听服务初始化完毕后 启动注册表和rpc服务
|
||||||
|
event.Register(core.Event_ServiceStartEnd, func() { //阻塞 先注册服务集群 保证其他服务能及时发现
|
||||||
|
if err := rpcx.Start(); err != nil {
|
||||||
|
log.Panicf(fmt.Sprintf("Sys rpcx Start err:%v", err))
|
||||||
|
}
|
||||||
|
if err := registry.Start(); err != nil {
|
||||||
|
log.Panicf(fmt.Sprintf("Sys registry Start err:%v", err))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//registry/coire.go 注册表系统的接口定义
|
||||||
|
ISys interface {
|
||||||
|
///启动注册表系统 向第三方服务注册当前服务信息
|
||||||
|
Start() error
|
||||||
|
///停止注册表系统 向第三方服务注销当前服务
|
||||||
|
Stop() error
|
||||||
|
///推送当前服务信息到 第三方服务
|
||||||
|
PushServiceInfo() (err error)
|
||||||
|
///通过id 获取集群内服务的节点信息
|
||||||
|
GetServiceById(sId string) (n *ServiceNode, err error)
|
||||||
|
///通过服务类型 获取当前集群下的所有服务节点信息
|
||||||
|
GetServiceByType(sType string) (n []*ServiceNode)
|
||||||
|
///获取当前集群下所有的服务节点信息
|
||||||
|
GetAllServices() (n []*ServiceNode)
|
||||||
|
///通过服务类别 获取当前集群下的所有服务节点信息
|
||||||
|
GetServiceByCategory(category core.S_Category) (n []*ServiceNode)
|
||||||
|
///通过RPC接口获取 提供此接口的所有服务节点信息
|
||||||
|
GetRpcSubById(rId core.Rpc_Key) (n []*ServiceNode)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- registry 发现集群下服务变动 通知 service
|
||||||
|
```go
|
||||||
|
//registry/options.go 启动是需要设置监听对象
|
||||||
|
registry.SetListener(this.rpcxService.(registry.IListener))
|
||||||
|
|
||||||
|
// /registry/coire.go 监听注册表发送的集群变更信息
|
||||||
|
IListener interface {
|
||||||
|
FindServiceHandlefunc(snode ServiceNode)
|
||||||
|
UpDataServiceHandlefunc(snode ServiceNode)
|
||||||
|
LoseServiceHandlefunc(sId string)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// lego/base/rpcx/service.go 服务对象实现上面三个接口 既可以接收到集群变化事件
|
||||||
|
//注册服务会话 当有新的服务加入时
|
||||||
|
func (this *RPCXService) FindServiceHandlefunc(node registry.ServiceNode) {
|
||||||
|
this.lock.Lock()
|
||||||
|
if _, ok := this.serverList.Load(node.Id); !ok {
|
||||||
|
if s, err := NewServiceSession(&node); err != nil {
|
||||||
|
log.Errorf("创建服务会话失败【%s】 err:%v", node.Id, err)
|
||||||
|
} else {
|
||||||
|
this.serverList.Store(node.Id, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.lock.Unlock()
|
||||||
|
if this.IsInClustered {
|
||||||
|
event.TriggerEvent(core.Event_FindNewService, node) //触发发现新的服务事件
|
||||||
|
} else {
|
||||||
|
if node.Id == this.opts.Setting.Id { //发现自己 加入集群成功
|
||||||
|
this.IsInClustered = true
|
||||||
|
event.TriggerEvent(core.Event_RegistryStart)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新服务会话 当有新的服务加入时
|
||||||
|
func (this *RPCXService) UpDataServiceHandlefunc(node registry.ServiceNode) {
|
||||||
|
if ss, ok := this.serverList.Load(node.Id); ok { //已经在缓存中 需要更新节点信息
|
||||||
|
session := ss.(base.IRPCXServiceSession)
|
||||||
|
if session.GetRpcId() != node.RpcId {
|
||||||
|
if s, err := NewServiceSession(&node); err != nil {
|
||||||
|
log.Errorf("更新服务会话失败【%s】 err:%v", node.Id, err)
|
||||||
|
} else {
|
||||||
|
this.serverList.Store(node.Id, s)
|
||||||
|
}
|
||||||
|
event.TriggerEvent(core.Event_FindNewService, node) //触发发现新的服务事件
|
||||||
|
} else {
|
||||||
|
if session.GetVersion() != node.Version {
|
||||||
|
session.SetVersion(node.Version)
|
||||||
|
}
|
||||||
|
if session.GetPreWeight() != node.PreWeight {
|
||||||
|
session.SetPreWeight(node.PreWeight)
|
||||||
|
}
|
||||||
|
event.TriggerEvent(core.Event_UpDataOldService, node) //触发发现新的服务事件
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//注销服务会话
|
||||||
|
func (this *RPCXService) LoseServiceHandlefunc(sId string) {
|
||||||
|
this.lock.Lock()
|
||||||
|
session, ok := this.serverList.Load(sId)
|
||||||
|
if ok && session != nil {
|
||||||
|
session.(base.IRPCXServiceSession).Done()
|
||||||
|
this.serverList.Delete(sId)
|
||||||
|
}
|
||||||
|
this.lock.Unlock()
|
||||||
|
event.TriggerEvent(core.Event_LoseService, sId) //触发发现新的服务事件
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### lego 微服务构架 服务通信 rpcx
|
||||||
|
- 服务启动时启动rpcx服务 提供rpcx服务监听
|
||||||
|
```go
|
||||||
|
//rpcx 系统接口定义
|
||||||
|
ISys interface {
|
||||||
|
IRPCXServer
|
||||||
|
NewRpcClient(addr, sId string) (clent IRPCXClient, err error) //创建rpc客户端对象
|
||||||
|
}
|
||||||
|
|
||||||
|
IRPCXServer interface {
|
||||||
|
Start() (err error) //启动rpcx服务
|
||||||
|
Stop() (err error) //停止rpcx服务
|
||||||
|
Register(rcvr interface{}) (err error) //注册rpc服务接口对象
|
||||||
|
RegisterFunction(fn interface{}) (err error) //注册rpc服务接口
|
||||||
|
RegisterFunctionName(name string, fn interface{}) (err error) //注册rpc服务接口
|
||||||
|
UnregisterAll() (err error) //注销全部rpc服务接口
|
||||||
|
}
|
||||||
|
//rpc客户端对象接口定义
|
||||||
|
IRPCXClient interface {
|
||||||
|
Stop() (err error)
|
||||||
|
Call(ctx context.Context, serviceMethod string, args interface{}, reply interface{}) error
|
||||||
|
Go(ctx context.Context, serviceMethod string, args interface{}, reply interface{}, done chan *client.Call) (*client.Call, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
//lego/sys/rpcx/service.go
|
||||||
|
/*RPC 服务对象*/
|
||||||
|
type Service struct {
|
||||||
|
server *server.Server
|
||||||
|
options Options
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Service) Start() (err error) {
|
||||||
|
go this.server.Serve("tcp", fmt.Sprintf(":%d", this.options.Port))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Service) Stop() (err error) {
|
||||||
|
err = this.server.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Service) Register(rcvr interface{}) (err error) {
|
||||||
|
err = this.server.RegisterName(this.options.ServiceId, rcvr, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (this *Service) RegisterFunction(fn interface{}) (err error) {
|
||||||
|
err = this.server.RegisterFunction(this.options.ServiceId, fn, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (this *Service) RegisterFunctionName(name string, fn interface{}) (err error) {
|
||||||
|
err = this.server.RegisterFunctionName(this.options.ServiceId, name, fn, "")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (this *Service) UnregisterAll() (err error) {
|
||||||
|
err = this.server.UnregisterAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- 发现新的服务节点信息是 创建服务会话对象 lego/base/rpcx/servicesession.go
|
||||||
|
```go
|
||||||
|
//注册服务会话 当有新的服务加入时 lego/base/rpcx/service.go
|
||||||
|
func (this *RPCXService) FindServiceHandlefunc(node registry.ServiceNode) {
|
||||||
|
this.lock.Lock()
|
||||||
|
if _, ok := this.serverList.Load(node.Id); !ok {
|
||||||
|
if s, err := NewServiceSession(&node); err != nil {
|
||||||
|
log.Errorf("创建服务会话失败【%s】 err:%v", node.Id, err)
|
||||||
|
} else {
|
||||||
|
this.serverList.Store(node.Id, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.lock.Unlock()
|
||||||
|
if this.IsInClustered {
|
||||||
|
event.TriggerEvent(core.Event_FindNewService, node) //触发发现新的服务事件
|
||||||
|
} else {
|
||||||
|
if node.Id == this.opts.Setting.Id { //发现自己 加入集群成功
|
||||||
|
this.IsInClustered = true
|
||||||
|
event.TriggerEvent(core.Event_RegistryStart)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//创建服务会话 lego/base/rpcx/servicesession.go
|
||||||
|
func NewServiceSession(node *registry.ServiceNode) (ss base.IRPCXServiceSession, err error) {
|
||||||
|
session := new(ServiceSession)
|
||||||
|
session.node = node
|
||||||
|
session.client, err = rpcx.NewRpcClient(fmt.Sprintf("%s:%d", node.IP, node.Port), node.Id)
|
||||||
|
ss = session
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
- service对象注册rpc服务接口 和调用其他服务的rpc接口 lego/base/rpcx/service.go
|
||||||
|
```go
|
||||||
|
//注册服务对象
|
||||||
|
func (this *RPCXService) Register(rcvr interface{}) (err error) {
|
||||||
|
err = rpcx.Register(rcvr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//注册服务方法
|
||||||
|
func (this *RPCXService) RegisterFunction(fn interface{}) (err error) {
|
||||||
|
err = rpcx.RegisterFunction(fn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//注册服务方法 自定义方法名称
|
||||||
|
func (this *RPCXService) RegisterFunctionName(name string, fn interface{}) (err error) {
|
||||||
|
err = rpcx.RegisterFunctionName(name, fn)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//同步 执行目标远程服务方法
|
||||||
|
func (this *RPCXService) RpcCallById(sId string, serviceMethod string, ctx context.Context, args interface{}, reply interface{}) (err error) {
|
||||||
|
defer lego.Recover(fmt.Sprintf("RpcCallById sId:%s rkey:%v arg %v", sId, serviceMethod, args))
|
||||||
|
this.lock.RLock()
|
||||||
|
defer this.lock.RUnlock()
|
||||||
|
ss, ok := this.serverList.Load(sId)
|
||||||
|
if !ok {
|
||||||
|
if node, err := registry.GetServiceById(sId); err != nil {
|
||||||
|
log.Errorf("未找到目标服务【%s】节点 err:%v", sId, err)
|
||||||
|
return fmt.Errorf("No Found " + sId)
|
||||||
|
} else {
|
||||||
|
ss, err = NewServiceSession(node)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(fmt.Sprintf("创建服务会话失败【%s】 err:%v", sId, err))
|
||||||
|
} else {
|
||||||
|
this.serverList.Store(node.Id, ss)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = ss.(base.IRPCXServiceSession).Call(ctx, serviceMethod, args, reply)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//异步 执行目标远程服务方法
|
||||||
|
func (this *RPCXService) RpcGoById(sId string, serviceMethod string, ctx context.Context, args interface{}, reply interface{}) (call *client.Call, err error) {
|
||||||
|
defer lego.Recover(fmt.Sprintf("RpcGoById sId:%s rkey:%v arg %v", sId, serviceMethod, args))
|
||||||
|
this.lock.RLock()
|
||||||
|
defer this.lock.RUnlock()
|
||||||
|
ss, ok := this.serverList.Load(sId)
|
||||||
|
if !ok {
|
||||||
|
if node, err := registry.GetServiceById(sId); err != nil {
|
||||||
|
log.Errorf("未找到目标服务【%s】节点 err:%v", sId, err)
|
||||||
|
return nil, fmt.Errorf("No Found " + sId)
|
||||||
|
} else {
|
||||||
|
ss, err = NewServiceSession(node)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(fmt.Sprintf("创建服务会话失败【%s】 err:%v", sId, err))
|
||||||
|
} else {
|
||||||
|
this.serverList.Store(node.Id, ss)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
call, err = ss.(base.IRPCXServiceSession).Go(ctx, serviceMethod, args, reply)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
DefauleRpcRouteRules 此方法采用的是默认负载方式 版本信息和权重信息排序 找到最佳服务节点
|
||||||
|
新版本正在偶合rpcx系统中的 selector 设计 支持 随机 轮询 权重 和 网络质量 等 服务策略
|
||||||
|
*/
|
||||||
|
func (this *RPCXService) RpcCallByType(sType string, serviceMethod string, ctx context.Context, args interface{}, reply interface{}) (err error) {
|
||||||
|
defer lego.Recover(fmt.Sprintf("RpcCallByType sType:%s rkey:%s arg %v", sType, serviceMethod, args))
|
||||||
|
this.lock.RLock()
|
||||||
|
defer this.lock.RUnlock()
|
||||||
|
ss, err := this.rpcxService.DefauleRpcRouteRules(sType, core.AutoIp)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("未找到目标服务【%s】节点 err:%v", sType, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ss.Call(ctx, serviceMethod, args, reply)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RPCXService) RpcGoByType(sType string, serviceMethod string, ctx context.Context, args interface{}, reply interface{}) (call *client.Call, err error) {
|
||||||
|
defer lego.Recover(fmt.Sprintf("RpcCallByType sType:%s rkey:%s arg %v", sType, serviceMethod, args))
|
||||||
|
this.lock.RLock()
|
||||||
|
defer this.lock.RUnlock()
|
||||||
|
ss, err := this.rpcxService.DefauleRpcRouteRules(sType, core.AutoIp)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("未找到目标服务【%s】节点 err:%v", sType, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
call, err = ss.Go(ctx, serviceMethod, args, reply)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
```
|
Loading…
Reference in New Issue
Block a user