Compare commits

..

67 Commits

Author SHA1 Message Date
boyce
6c44ba180c 优化kafkamoudule日志 2025-05-21 21:38:36 +08:00
boyce
ecfd42bdec 优化消息队列日志 2025-05-21 21:34:32 +08:00
boyce
01d3b3e535 优化RankService日志 2025-05-21 21:22:24 +08:00
boyce
550d65a354 优化mysql模块日志 2025-05-21 21:19:03 +08:00
boyce
15580ffce9 新增wss证书配置支持 2025-04-21 21:23:34 +08:00
boyce
bd467a219b 废弃掉HttpService、TcpService、WSService 2025-03-28 10:33:51 +08:00
boyce
af15615345 优化日志生成路径 2025-03-14 18:03:01 +08:00
boyce
50dd80b082 整理代码 2025-03-10 11:35:19 +08:00
boyce
a6487dd41e 将默认日志改为rotatelogs 2025-01-25 00:14:18 +08:00
boyce
d5299294d8 优化日志,新增rotatelogs库支持 2025-01-25 00:04:31 +08:00
boyce
4d36e525a5 优化配置读取,去消默认cluster目录 2025-01-16 13:45:06 +08:00
duanhf2012
3a4350769c 新增etcd认证配置 2025-01-08 18:11:20 +08:00
duanhf2012
d4966ea129 优化ws模块 2024-12-17 14:46:00 +08:00
duanhf2012
3b10eeb792 优化日志 2024-12-16 18:00:26 +08:00
duanhf2012
e3275e9f2a 优化模块释放顺序 2024-12-11 18:31:37 +08:00
duanhf2012
16745b34f0 优化日志 2024-12-11 17:49:59 +08:00
duanhf2012
f34dc7d53f 优化日志自定义Writer 2024-12-11 17:24:06 +08:00
duanhf2012
0a09dc2fee 优化日志 2024-12-11 17:14:29 +08:00
duanhf2012
f01a93c446 优化日志 2024-12-11 17:03:21 +08:00
duanhf2012
4d2ab4ee4f 优化代码 2024-12-11 16:44:09 +08:00
duanhf2012
ffcc5a3489 1.优化服务配置检查
2.废弃SetGoRoutineNum接口
3.释放Module优化
2024-12-06 16:05:25 +08:00
duanhf2012
cf6ca0483b Merge branch 'v2' of https://github.com/duanhf2012/origin into v2 2024-12-05 10:19:24 +08:00
duanhf2012
97a21e6f71 新增Skip接口 2024-12-05 10:19:15 +08:00
duanhf2012
f60a55d03a 优化异步RPC,去掉error返回值 2024-12-04 18:33:53 +08:00
duanhf2012
2c32d6eec9 RPC与日志优化 2024-12-03 17:21:21 +08:00
duanhf2012
da45f97fa8 优化日志 2024-11-29 15:55:35 +08:00
duanhf2012
d29abc0813 新增配置文件环境变量支持 2024-11-29 14:39:04 +08:00
duanhf2012
c9507f9ee9 替换slog日志为zap 2024-11-29 13:47:51 +08:00
duanhf2012
61de4bba3a 替换slog日志为zap 2024-11-29 13:47:27 +08:00
duanhf2012
000853b479 网络库优化 2024-11-25 17:44:08 +08:00
duanhf2012
387e83d65c Deprecated一些定时器接口 2024-10-12 17:49:59 +08:00
duanhf2012
07a102c6ea 新增发布订阅模式 2024-10-11 09:00:12 +08:00
duanhf2012
e9bbf5b592 优化配置读取 2024-10-10 09:11:29 +08:00
duanhf2012
3f4189fd40 扩展支持yaml格式配置 2024-10-09 18:14:13 +08:00
duanhf2012
c72f2e4582 1.新增yml文件支持
2.优化网络模块日志
3.新增类型转换函数
2024-10-09 17:38:44 +08:00
duanhf2012
f600c2a573 优化module位置 2024-10-09 11:26:37 +08:00
duanhf2012
6a29ba2c88 新增网络模块 2024-10-09 10:50:54 +08:00
duanhf2012
64c14eb326 优化readme文档 2024-10-09 10:08:17 +08:00
duanhf2012
75790302ec 优化tcpservice 2024-10-09 09:50:11 +08:00
duanhf2012
b943ea9a83 1.优化网络模块
2.新增kcp模块
2024-09-30 14:31:24 +08:00
duanhf2012
39116c4402 优化代码规范 2024-09-20 17:25:08 +08:00
duanhf2012
1cf071a444 优化日志 2024-09-20 15:17:44 +08:00
duanhf2012
e6c09064bf 美化代码 2024-09-18 16:19:20 +08:00
duanhf2012
84ab0cb84a 新增定时器组关闭接口 2024-09-18 11:51:17 +08:00
duanhf2012
22fe00173b 新增FrameTimer模块,支持暂停、恢复、加速 2024-09-18 11:35:43 +08:00
duanhf2012
8e0ed62fca 优化smath模块 2024-09-11 15:06:33 +08:00
duanhf2012
7116b509e9 新增权重随机相关函数 2024-09-11 14:50:31 +08:00
duanhf2012
73d384361d 优化Service多协程模式 2024-08-30 16:56:48 +08:00
boyce
ce56b19fe8 优化服务筛选 2024-06-29 14:58:41 +08:00
boyce
1367d776e6 优化readme事件说明 2024-06-29 12:02:13 +08:00
boyce
987d35ff15 优化origin服务发现 2024-06-28 12:29:58 +08:00
boyce
d225bb4bd2 优化启动参数logchannelcap默认值 2024-06-25 09:20:03 +08:00
boyce
ea37fb5081 新增日志接口--SetSkip/GetSkip 2024-06-24 15:29:54 +08:00
boyce
0a92f48d0b 优化node状态 2024-06-20 09:10:18 +08:00
boyce
f5e86fee02 新增Stop接口,断开mongo连接 2024-06-19 15:51:31 +08:00
boyce
166facc959 优化mongodb驱动 2024-06-18 10:07:54 +08:00
boyce
5bb747201b 补充readme说明 2024-06-14 17:46:58 +08:00
boyce
1014bc54e4 优化网络处理器 2024-06-14 16:21:52 +08:00
boyce
9c26c742fe 优化协程池退出 2024-06-14 15:42:23 +08:00
boyce
d1935b1bbc 优化日志 2024-05-27 18:09:37 +08:00
boyce
90d54bf3e2 1.新增服务和Global配置接口,支持通过结构体解析
2.优化日志
2024-05-15 10:06:50 +08:00
boyce
78cc33c84e 优化服务模板的配置读取 2024-05-11 15:11:24 +08:00
boyce
9cf21bf418 1.新增模板服务
2.优化消息队列
3.优化相关日志
2024-05-11 14:42:34 +08:00
boyce
c6d0bd9a19 优化gin模块 2024-05-08 14:18:39 +08:00
boyce
61bf95e457 优化RankService 2024-05-07 18:57:38 +08:00
boyce
8b2a551ee5 优化gin模块 2024-05-06 10:51:51 +08:00
boyce
927c2ffa37 优化gin模块 2024-05-06 10:36:04 +08:00
93 changed files with 5468 additions and 3592 deletions

188
README.md
View File

@@ -14,17 +14,7 @@ origin 解决的问题:
Hello world! Hello world!
------------ ------------
下面我们来一步步的建立origin服务器,先下载[origin引擎](https://github.com/duanhf2012/origin "origin引擎"),或者使用如下命令 下面我们来一步步的建立origin服务器,建议使用origin v2版本内容如下
```go
go get -v -u github.com/duanhf2012/origin/v2
```
建议使用origin v2版本import引用中都加入v2
[README.md](README.md)
于是下载到GOPATH环境目录中,在src中加入main.go,内容如下:
```go ```go
package main package main
@@ -43,11 +33,19 @@ func main() {
一个origin进程需要创建一个node对象,Start开始运行。您也可以直接下载origin引擎示例: 一个origin进程需要创建一个node对象,Start开始运行。您也可以直接下载origin引擎示例:
``` ```
go get -v -u github.com/duanhf2012/originserver_v2 git clone https://github.com/duanhf2012/originserver_v2.git
``` ```
本文所有的说明都是基于该示例为主。 本文所有的说明都是基于该示例为主。
我们也提供了示例项目,包含网络模块(支持tcp,kcp,websocket)、角色加载登录流程,存档,配置读取等功能。请参照:
```
git clone https://github.com/duanhf2012/origingame.git
```
origin引擎三大对象关系 origin引擎三大对象关系
---------------------- ----------------------
@@ -69,16 +67,10 @@ origin的配置文件以json格式主要包含Discovery、RpcMode、NodeList
} }
``` ```
### Discovery部分 ### Discovery部分
origin目前支持etcd与origin自带的服务发现类型。 origin目前支持etcd与origin自带的服务发现类型。
Etcd方式示例 Etcd方式示例
```json ```json
@@ -106,8 +98,6 @@ NetworkName所在的网络名称可以配置多个。node会往对应的
EndpointsEtcd服务器地址 EndpointsEtcd服务器地址
Origin方式示例 Origin方式示例
```json ```json
@@ -130,8 +120,6 @@ TTLSecond表示健康检查TTL失效时间10秒
MasterNodeList指定哪些Node为服务发现Master结点需要配置NodeId与ListenAddr注意它们要与实际的Node配置一致。 MasterNodeList指定哪些Node为服务发现Master结点需要配置NodeId与ListenAddr注意它们要与实际的Node配置一致。
### RpcMode部分 ### RpcMode部分
默认模式 默认模式
@@ -146,8 +134,6 @@ MasterNodeList指定哪些Node为服务发现Master结点需要配置NodeI
默认模式下origin的node之前通过tcp连接组网。 默认模式下origin的node之前通过tcp连接组网。
Nats模式 Nats模式
```json ```json
@@ -167,8 +153,6 @@ NatsUrlNats连接url串
NoRandomize:在多连接集群模式下连接nats节点是否顺序策略。false表示随机连接true表示顺序连接。 NoRandomize:在多连接集群模式下连接nats节点是否顺序策略。false表示随机连接true表示顺序连接。
### NodeList部分 ### NodeList部分
``` ```
@@ -212,8 +196,6 @@ NoRandomize:在多连接集群模式下连接nats节点是否顺序策略。f
在启动程序命令originserver -start nodeid="node_1"中nodeid就是根据该配置装载服务。 在启动程序命令originserver -start nodeid="node_1"中nodeid就是根据该配置装载服务。
更多参数使用请使用originserver -help查看。 更多参数使用请使用originserver -help查看。
### Service 部分 ### Service 部分
service.json如下 service.json如下
@@ -232,7 +214,7 @@ service.json如下
"Certfile":"", "Certfile":"",
"Keyfile":"" "Keyfile":""
}] }]
}, },
"TcpService":{ "TcpService":{
"ListenAddr":"0.0.0.0:9030", "ListenAddr":"0.0.0.0:9030",
@@ -318,8 +300,6 @@ service.json如下
* PendingWriteNum发送网络队列最大数量 * PendingWriteNum发送网络队列最大数量
* MaxMsgLen:包最大长度 * MaxMsgLen:包最大长度
### Global部分 ### Global部分
```json ```json
@@ -342,8 +322,6 @@ if ok == false {
areaId, ok := mapGlobal["AreaId"] areaId, ok := mapGlobal["AreaId"]
``` ```
--- ---
第一章origin基础: 第一章origin基础:
@@ -510,7 +488,6 @@ func (slf *TestService1) OnInit() error {
} }
``` ```
性能监控功能: 性能监控功能:
------------- -------------
@@ -661,51 +638,7 @@ Module1 Release.
第四章:事件使用 第四章:事件使用
---------------- ----------------
事件是origin中一个重要的组成部分可以在同一个node中的service与service或者与module之间进行事件通知。系统内置的几个服务TcpService/HttpService等都是通过事件功能实现。他也是一个典型的观察者设计模型。在event中有两个类型的interface一个是event.IEventProcessor它提供注册与卸载功能另一个是event.IEventHandler提供消息广播等功能。 事件是origin中一个重要的组成部分可以在服务与各module之间进行事件通知。它也是一个典型的观察者设计模型。在event中有两个类型的interface一个是event.IEventProcessor它提供注册与卸载功能另一个是event.IEventHandler提供消息广播等功能。
在目录simple_event/TestService4.go中
```
package simple_event
import (
"github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/node"
"github.com/duanhf2012/origin/v2/service"
"time"
)
const (
//自定义事件类型必需从event.Sys_Event_User_Define开始
//event.Sys_Event_User_Define以内给系统预留
EVENT1 event.EventType =event.Sys_Event_User_Define+1
)
func init(){
node.Setup(&TestService4{})
}
type TestService4 struct {
service.Service
}
func (slf *TestService4) OnInit() error {
//10秒后触发广播事件
slf.AfterFunc(time.Second*10,slf.TriggerEvent)
return nil
}
func (slf *TestService4) TriggerEvent(){
//广播事件传入event.Event对象类型为EVENT1,Data可以自定义任何数据
//这样,所有监听者都可以收到该事件
slf.GetEventHandler().NotifyEvent(&event.Event{
Type: EVENT1,
Data: "event data.",
})
}
```
在目录simple_event/TestService5.go中 在目录simple_event/TestService5.go中
@@ -713,53 +646,68 @@ func (slf *TestService4) TriggerEvent(){
package simple_event package simple_event
import ( import (
"fmt" "fmt"
"github.com/duanhf2012/origin/v2/event" "github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/node" "github.com/duanhf2012/origin/v2/node"
"github.com/duanhf2012/origin/v2/service" "github.com/duanhf2012/origin/v2/service"
"github.com/duanhf2012/origin/v2/util/timer"
"time"
) )
func init(){ func init() {
node.Setup(&TestService5{}) node.Setup(&TestService5{})
} }
const (
//自定义事件类型必需从event.Sys_Event_User_Define开始
//event.Sys_Event_User_Define以内给系统预留
EVENT1 event.EventType = event.Sys_Event_User_Define + 1
)
type TestService5 struct { type TestService5 struct {
service.Service service.Service
} }
type TestModule struct { type TestModule struct {
service.Module service.Module
} }
func (slf *TestModule) OnInit() error{ func (slf *TestModule) OnInit() error {
//在当前node中查找TestService4 //在TestModule中注册监听EVENT1事件
pService := node.GetService("TestService4") slf.GetEventProcessor().RegEventReceiverFunc(EVENT1, slf.GetEventHandler(), slf.OnModuleEvent)
//在TestModule中往TestService4中注册EVENT1类型事件监听 return nil
pService.(*TestService4).GetEventProcessor().RegEventReciverFunc(EVENT1,slf.GetEventHandler(),slf.OnModuleEvent)
return nil
} }
func (slf *TestModule) OnModuleEvent(ev event.IEvent){ // OnModuleEvent 模块监听事件回调
event := ev.(*event.Event) func (slf *TestModule) OnModuleEvent(ev event.IEvent) {
fmt.Printf("OnModuleEvent type :%d data:%+v\n",event.GetEventType(),event.Data) event := ev.(*event.Event)
fmt.Printf("OnModuleEvent type :%d data:%+v\n", event.GetEventType(), event.Data)
} }
// OnInit 服务初始化函数在安装服务时服务将自动调用OnInit函数
//服务初始化函数在安装服务时服务将自动调用OnInit函数
func (slf *TestService5) OnInit() error { func (slf *TestService5) OnInit() error {
//通过服务名获取服务对象 //在服务中注册监听EVENT1类型事件
pService := node.GetService("TestService4") slf.RegEventReceiverFunc(EVENT1, slf.GetEventHandler(), slf.OnServiceEvent)
slf.AddModule(&TestModule{})
////在TestModule中往TestService4中注册EVENT1类型事件监听 slf.AfterFunc(time.Second*10, slf.TriggerEvent)
pService.(*TestService4).GetEventProcessor().RegEventReciverFunc(EVENT1,slf.GetEventHandler(),slf.OnServiceEvent) return nil
slf.AddModule(&TestModule{})
return nil
} }
func (slf *TestService5) OnServiceEvent(ev event.IEvent){ // OnServiceEvent 服务监听事件回调
event := ev.(*event.Event) func (slf *TestService5) OnServiceEvent(ev event.IEvent) {
fmt.Printf("OnServiceEvent type :%d data:%+v\n",event.Type,event.Data) event := ev.(*event.Event)
fmt.Printf("OnServiceEvent type :%d data:%+v\n", event.Type, event.Data)
}
func (slf *TestService5) TriggerEvent(t *timer.Timer) {
//广播事件传入event.Event对象类型为EVENT1,Data可以自定义任何数据
//这样,所有监听者都可以收到该事件
slf.GetEventHandler().NotifyEvent(&event.Event{
Type: EVENT1,
Data: "event data.",
})
} }
@@ -768,8 +716,8 @@ func (slf *TestService5) OnServiceEvent(ev event.IEvent){
程序运行10秒后调用slf.TriggerEvent函数广播事件于是在TestService5中会收到 程序运行10秒后调用slf.TriggerEvent函数广播事件于是在TestService5中会收到
``` ```
OnServiceEvent type :1001 data:event data. OnServiceEvent type :2 data:event data.
OnModuleEvent type :1001 data:event data. OnModuleEvent type :2 data:event data.
``` ```
在上面的TestModule中监听的事情当这个Module被Release时监听会自动卸载。 在上面的TestModule中监听的事情当这个Module被Release时监听会自动卸载。
@@ -854,8 +802,8 @@ func (slf *TestService7) CallTest(){
}else{ }else{
fmt.Printf("Call output %d\n",output) fmt.Printf("Call output %d\n",output)
} }
//自定义超时,默认rpc超时时间为15s,以下设置1秒钟超过 //自定义超时,默认rpc超时时间为15s,以下设置1秒钟超过
err = slf.CallWithTimeout(time.Second*1, "TestService6.RPC_Sum", &input, &output) err = slf.CallWithTimeout(time.Second*1, "TestService6.RPC_Sum", &input, &output)
if err != nil { if err != nil {
@@ -894,7 +842,7 @@ func (slf *TestService7) AsyncCallTest(){
}) })
//rpcCancel() //rpcCancel()
fmt.Println(err, rpcCancel) fmt.Println(err, rpcCancel)
} }
func (slf *TestService7) GoTest(){ func (slf *TestService7) GoTest(){
@@ -916,20 +864,22 @@ func (slf *TestService7) GoTest(){
您可以把TestService6配置到其他的Node中比如NodeId为2中。只要在一个子网origin引擎可以无差别调用。开发者只需要关注Service关系。同样它也是您服务器架构设计的核心需要思考的部分。 您可以把TestService6配置到其他的Node中比如NodeId为2中。只要在一个子网origin引擎可以无差别调用。开发者只需要关注Service关系。同样它也是您服务器架构设计的核心需要思考的部分。
第六章:并发函数调用 第六章:并发函数调用
--------------- --------------------
在开发中经常会有将某些任务放到其他协程中并发执行,执行完成后,将服务的工作线程去回调。使用方式很简单,先打开该功能如下代码: 在开发中经常会有将某些任务放到其他协程中并发执行,执行完成后,将服务的工作线程去回调。使用方式很简单,先打开该功能如下代码:
``` ```
//以下通过cpu数量来定开启协程并发数量建议:(1)cpu密集型计算使用1.0 (2)i/o密集型使用2.0或者更高 //以下通过cpu数量来定开启协程并发数量建议:(1)cpu密集型计算使用1.0 (2)i/o密集型使用2.0或者更高
slf.OpenConcurrentByNumCPU(1.0) slf.OpenConcurrentByNumCPU(1.0)
//以下通过函数打开并发协程数以下协程数最小5最大10任务管道的cap数量1000000 //以下通过函数打开并发协程数以下协程数最小5最大10任务管道的cap数量1000000
//origin会根据任务的数量在最小与最大协程数间动态伸缩 //origin会根据任务的数量在最小与最大协程数间动态伸缩
//slf.OpenConcurrent(5, 10, 1000000) //slf.OpenConcurrent(5, 10, 1000000)
``` ```
使用示例如下: 使用示例如下:
``` ```
func (slf *TestService13) testAsyncDo() { func (slf *TestService13) testAsyncDo() {
@@ -983,9 +933,8 @@ func (slf *TestService13) testAsyncDo() {
} }
``` ```
第七章:服务发现 第七章:服务发现
-------------------- ----------------
origin引擎默认使用读取所有结点配置的进行确认结点有哪些Service。引擎也支持动态服务发现的方式支持etcd与origin类型具体请参照【配置说明】部分Node结点可以配置只发现某些服务如下示例 origin引擎默认使用读取所有结点配置的进行确认结点有哪些Service。引擎也支持动态服务发现的方式支持etcd与origin类型具体请参照【配置说明】部分Node结点可以配置只发现某些服务如下示例
@@ -1008,12 +957,11 @@ origin引擎默认使用读取所有结点配置的进行确认结点有哪些Se
}] }]
} }
``` ```
DiscoveryService在当前nodeid为nodeid_test的结点中只发现 MasterNodeId为nodeid_1或NetworkName为networkname1网络中的TestService8服务。 DiscoveryService在当前nodeid为nodeid_test的结点中只发现 MasterNodeId为nodeid_1或NetworkName为networkname1网络中的TestService8服务。
**注意**MasterNodeId与NetworkName只配置一个分别在模式为origin或者etcd服务发现类型时。 **注意**MasterNodeId与NetworkName只配置一个分别在模式为origin或者etcd服务发现类型时。
第八章HttpService使用 第八章HttpService使用
----------------------- -----------------------
@@ -1181,6 +1129,8 @@ func (slf *TestTcpService) OnRequest (clientid string,msg proto.Message){
* log/log.go:日志的封装,可以使用它构建对象记录业务文件日志 * log/log.go:日志的封装,可以使用它构建对象记录业务文件日志
* util:在该目录下有常用的uuid,hash,md5,协程封装等工具库 * util:在该目录下有常用的uuid,hash,md5,协程封装等工具库
* https://github.com/duanhf2012/originservice: 其他扩展支持的服务可以在该工程上看到目前支持firebase推送的封装。 * https://github.com/duanhf2012/originservice: 其他扩展支持的服务可以在该工程上看到目前支持firebase推送的封装。
* https://github.com/duanhf2012/origingame: 基础游戏服务器的框架
* etcd与nats开发环境搭建可以从https://github.com/duanhf2012/originserver_v2下的docker-compose获取
备注: 备注:
----- -----

View File

@@ -1,13 +1,15 @@
package cluster package cluster
import ( import (
"errors"
"fmt" "fmt"
"github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/rpc" "github.com/duanhf2012/origin/v2/rpc"
"github.com/duanhf2012/origin/v2/service" "github.com/duanhf2012/origin/v2/service"
"reflect"
"strings" "strings"
"sync" "sync"
"github.com/duanhf2012/origin/v2/event"
) )
var configDir = "./config/" var configDir = "./config/"
@@ -22,24 +24,22 @@ const (
) )
type DiscoveryService struct { type DiscoveryService struct {
MasterNodeId string //要筛选的主结点Id如果不配置或者配置成0表示针对所有的主结点 MasterNodeId string //要筛选的主结点Id如果不配置或者配置成0表示针对所有的主结点
NetworkName string //如果是etcd指定要筛选的网络名中的服务不配置表示所有的网络 NetworkName string //如果是etcd指定要筛选的网络名中的服务不配置表示所有的网络
ServiceList []string //只发现的服务列表 ServiceList []string //只发现的服务列表
} }
type NodeInfo struct { type NodeInfo struct {
NodeId string NodeId string
Private bool Private bool
ListenAddr string ListenAddr string
MaxRpcParamLen uint32 //最大Rpc参数长度 MaxRpcParamLen uint32 //最大Rpc参数长度
CompressBytesLen int //超过字节进行压缩的长度 CompressBytesLen int //超过字节进行压缩的长度
ServiceList []string //所有的有序服务列表 ServiceList []string //所有的有序服务列表
PublicServiceList []string //对外公开的服务列表 PublicServiceList []string //对外公开的服务列表
DiscoveryService []DiscoveryService //筛选发现的服务,如果不配置,不进行筛选 DiscoveryService []DiscoveryService //筛选发现的服务,如果不配置,不进行筛选
status NodeStatus status NodeStatus
Retire bool Retire bool
NetworkName string
} }
type NodeRpcInfo struct { type NodeRpcInfo struct {
@@ -50,21 +50,22 @@ type NodeRpcInfo struct {
var cluster Cluster var cluster Cluster
type Cluster struct { type Cluster struct {
localNodeInfo NodeInfo //本结点配置信息 localNodeInfo NodeInfo //本结点配置信息
discoveryInfo DiscoveryInfo //服务发现配置 discoveryInfo DiscoveryInfo //服务发现配置
rpcMode RpcMode rpcMode RpcMode
globalCfg interface{} //全局配置 globalCfg interface{} //全局配置
localServiceCfg map[string]interface{} //map[serviceName]配置数据* localServiceCfg map[string]interface{} //map[serviceName]配置数据*
serviceDiscovery IServiceDiscovery //服务发现接口 serviceDiscovery IServiceDiscovery //服务发现接口
locker sync.RWMutex //结点与服务关系保护锁 locker sync.RWMutex //结点与服务关系保护锁
mapRpc map[string]*NodeRpcInfo //nodeId mapRpc map[string]*NodeRpcInfo //nodeId
mapServiceNode map[string]map[string]struct{} //map[serviceName]map[NodeId] mapServiceNode map[string]map[string]struct{} //map[serviceName]map[NodeId]
mapTemplateServiceNode map[string]map[string]struct{} //map[templateServiceName]map[serviceName]nodeId
callSet rpc.CallSet callSet rpc.CallSet
rpcNats rpc.RpcNats rpcNats rpc.RpcNats
rpcServer rpc.IServer rpcServer rpc.IServer
rpcEventLocker sync.RWMutex //Rpc事件监听保护锁 rpcEventLocker sync.RWMutex //Rpc事件监听保护锁
@@ -83,7 +84,7 @@ func SetServiceDiscovery(serviceDiscovery IServiceDiscovery) {
cluster.serviceDiscovery = serviceDiscovery cluster.serviceDiscovery = serviceDiscovery
} }
func (cls *Cluster) Start() error{ func (cls *Cluster) Start() error {
return cls.rpcServer.Start() return cls.rpcServer.Start()
} }
@@ -94,7 +95,7 @@ func (cls *Cluster) Stop() {
func (cls *Cluster) DiscardNode(nodeId string) { func (cls *Cluster) DiscardNode(nodeId string) {
cls.locker.Lock() cls.locker.Lock()
nodeInfo, ok := cls.mapRpc[nodeId] nodeInfo, ok := cls.mapRpc[nodeId]
bDel := (ok == true) && nodeInfo.nodeInfo.status == Discard bDel := (ok == true) && nodeInfo.nodeInfo.status == Discard
cls.locker.Unlock() cls.locker.Unlock()
if bDel { if bDel {
@@ -110,22 +111,22 @@ func (cls *Cluster) DelNode(nodeId string) {
cls.locker.Lock() cls.locker.Lock()
defer cls.locker.Unlock() defer cls.locker.Unlock()
rpc, ok := cls.mapRpc[nodeId] nodeRpc, ok := cls.mapRpc[nodeId]
if ok == false { if ok == false {
return return
} }
cls.TriggerDiscoveryEvent(false,nodeId,rpc.nodeInfo.ServiceList) cls.TriggerDiscoveryEvent(false, nodeId, nodeRpc.nodeInfo.ServiceList)
for _, serviceName := range rpc.nodeInfo.ServiceList { for _, serviceName := range nodeRpc.nodeInfo.ServiceList {
cls.delServiceNode(serviceName, nodeId) cls.delServiceNode(serviceName, nodeId)
} }
delete(cls.mapRpc, nodeId) delete(cls.mapRpc, nodeId)
if ok == true { if ok == true {
rpc.client.Close(false) nodeRpc.client.Close(false)
} }
log.Info("remove node ",log.String("NodeId", rpc.nodeInfo.NodeId),log.String("ListenAddr", rpc.nodeInfo.ListenAddr)) log.Info("remove node ", log.String("NodeId", nodeRpc.nodeInfo.NodeId), log.String("ListenAddr", nodeRpc.nodeInfo.ListenAddr))
} }
func (cls *Cluster) serviceDiscoveryDelNode(nodeId string) { func (cls *Cluster) serviceDiscoveryDelNode(nodeId string) {
@@ -137,6 +138,20 @@ func (cls *Cluster) delServiceNode(serviceName string, nodeId string) {
return return
} }
//处理模板服务
splitServiceName := strings.Split(serviceName, ":")
if len(splitServiceName) == 2 {
serviceName = splitServiceName[0]
templateServiceName := splitServiceName[1]
mapService := cls.mapTemplateServiceNode[templateServiceName]
delete(mapService, serviceName)
if len(cls.mapTemplateServiceNode[templateServiceName]) == 0 {
delete(cls.mapTemplateServiceNode, templateServiceName)
}
}
mapNode := cls.mapServiceNode[serviceName] mapNode := cls.mapServiceNode[serviceName]
delete(mapNode, nodeId) delete(mapNode, nodeId)
if len(mapNode) == 0 { if len(mapNode) == 0 {
@@ -161,7 +176,7 @@ func (cls *Cluster) serviceDiscoverySetNodeInfo(nodeInfo *NodeInfo) {
} }
} }
cluster.TriggerDiscoveryEvent(true,nodeInfo.NodeId,nodeInfo.PublicServiceList) cluster.TriggerDiscoveryEvent(true, nodeInfo.NodeId, nodeInfo.PublicServiceList)
//再重新组装 //再重新组装
mapDuplicate := map[string]interface{}{} //预防重复数据 mapDuplicate := map[string]interface{}{} //预防重复数据
for _, serviceName := range nodeInfo.PublicServiceList { for _, serviceName := range nodeInfo.PublicServiceList {
@@ -171,14 +186,27 @@ func (cls *Cluster) serviceDiscoverySetNodeInfo(nodeInfo *NodeInfo) {
continue continue
} }
mapDuplicate[serviceName] = nil mapDuplicate[serviceName] = nil
if _, ok := cls.mapServiceNode[serviceName]; ok == false {
//如果是模板服务,则记录模板关系
splitServiceName := strings.Split(serviceName, ":")
if len(splitServiceName) == 2 {
serviceName = splitServiceName[0]
templateServiceName := splitServiceName[1]
//记录模板
if _, ok = cls.mapTemplateServiceNode[templateServiceName]; ok == false {
cls.mapTemplateServiceNode[templateServiceName] = map[string]struct{}{}
}
cls.mapTemplateServiceNode[templateServiceName][serviceName] = struct{}{}
}
if _, ok = cls.mapServiceNode[serviceName]; ok == false {
cls.mapServiceNode[serviceName] = make(map[string]struct{}, 1) cls.mapServiceNode[serviceName] = make(map[string]struct{}, 1)
} }
cls.mapServiceNode[serviceName][nodeInfo.NodeId] = struct{}{} cls.mapServiceNode[serviceName][nodeInfo.NodeId] = struct{}{}
} }
if lastNodeInfo != nil { if lastNodeInfo != nil {
log.Info("Discovery nodeId",log.String("NodeId", nodeInfo.NodeId),log.Any("services:", nodeInfo.PublicServiceList),log.Bool("Retire",nodeInfo.Retire)) log.Info("Discovery nodeId", log.String("NodeId", nodeInfo.NodeId), log.Any("services:", nodeInfo.PublicServiceList), log.Bool("Retire", nodeInfo.Retire))
lastNodeInfo.nodeInfo = *nodeInfo lastNodeInfo.nodeInfo = *nodeInfo
return return
} }
@@ -188,19 +216,18 @@ func (cls *Cluster) serviceDiscoverySetNodeInfo(nodeInfo *NodeInfo) {
rpcInfo.nodeInfo = *nodeInfo rpcInfo.nodeInfo = *nodeInfo
if cls.IsNatsMode() { if cls.IsNatsMode() {
rpcInfo.client = cls.rpcNats.NewNatsClient(nodeInfo.NodeId, cls.GetLocalNodeInfo().NodeId,&cls.callSet,cls.NotifyAllService) rpcInfo.client = cls.rpcNats.NewNatsClient(nodeInfo.NodeId, cls.GetLocalNodeInfo().NodeId, &cls.callSet, cls.NotifyAllService)
}else{ } else {
rpcInfo.client =rpc.NewRClient(nodeInfo.NodeId, nodeInfo.ListenAddr, nodeInfo.MaxRpcParamLen,cls.localNodeInfo.CompressBytesLen,&cls.callSet,cls.NotifyAllService) rpcInfo.client = rpc.NewRClient(nodeInfo.NodeId, nodeInfo.ListenAddr, nodeInfo.MaxRpcParamLen, cls.localNodeInfo.CompressBytesLen, &cls.callSet, cls.NotifyAllService)
} }
cls.mapRpc[nodeInfo.NodeId] = &rpcInfo cls.mapRpc[nodeInfo.NodeId] = &rpcInfo
if cls.IsNatsMode() == true || cls.discoveryInfo.discoveryType!=OriginType { if cls.IsNatsMode() == true || cls.discoveryInfo.discoveryType != OriginType {
log.Info("Discovery nodeId and new rpc client",log.String("NodeId", nodeInfo.NodeId),log.Any("services:", nodeInfo.PublicServiceList),log.Bool("Retire",nodeInfo.Retire)) log.Info("Discovery nodeId and new rpc client", log.String("NodeId", nodeInfo.NodeId), log.Any("services:", nodeInfo.PublicServiceList), log.Bool("Retire", nodeInfo.Retire))
}else{ } else {
log.Info("Discovery nodeId and new rpc client",log.String("NodeId", nodeInfo.NodeId),log.Any("services:", nodeInfo.PublicServiceList),log.Bool("Retire",nodeInfo.Retire),log.String("nodeListenAddr",nodeInfo.ListenAddr)) log.Info("Discovery nodeId and new rpc client", log.String("NodeId", nodeInfo.NodeId), log.Any("services:", nodeInfo.PublicServiceList), log.Bool("Retire", nodeInfo.Retire), log.String("nodeListenAddr", nodeInfo.ListenAddr))
} }
} }
func (cls *Cluster) Init(localNodeId string, setupServiceFun SetupServiceFun) error { func (cls *Cluster) Init(localNodeId string, setupServiceFun SetupServiceFun) error {
//1.初始化配置 //1.初始化配置
err := cls.InitCfg(localNodeId) err := cls.InitCfg(localNodeId)
@@ -210,18 +237,18 @@ func (cls *Cluster) Init(localNodeId string, setupServiceFun SetupServiceFun) er
cls.callSet.Init() cls.callSet.Init()
if cls.IsNatsMode() { if cls.IsNatsMode() {
cls.rpcNats.Init(cls.rpcMode.Nats.NatsUrl,cls.rpcMode.Nats.NoRandomize,cls.GetLocalNodeInfo().NodeId,cls.localNodeInfo.CompressBytesLen,cls,cluster.NotifyAllService) cls.rpcNats.Init(cls.rpcMode.Nats.NatsUrl, cls.rpcMode.Nats.NoRandomize, cls.GetLocalNodeInfo().NodeId, cls.localNodeInfo.CompressBytesLen, cls, cluster.NotifyAllService)
cls.rpcServer = &cls.rpcNats cls.rpcServer = &cls.rpcNats
}else{ } else {
s := &rpc.Server{} s := &rpc.Server{}
s.Init(cls.localNodeInfo.ListenAddr,cls.localNodeInfo.MaxRpcParamLen,cls.localNodeInfo.CompressBytesLen,cls) s.Init(cls.localNodeInfo.ListenAddr, cls.localNodeInfo.MaxRpcParamLen, cls.localNodeInfo.CompressBytesLen, cls)
cls.rpcServer = s cls.rpcServer = s
} }
//2.安装服务发现结点 //2.安装服务发现结点
err = cls.setupDiscovery(localNodeId, setupServiceFun) err = cls.setupDiscovery(localNodeId, setupServiceFun)
if err != nil { if err != nil {
log.Error("setupDiscovery fail",log.ErrorAttr("err",err)) log.Error("setupDiscovery fail", log.ErrorField("err", err))
return err return err
} }
service.RegRpcEventFun = cls.RegRpcEvent service.RegRpcEventFun = cls.RegRpcEvent
@@ -244,44 +271,47 @@ func (cls *Cluster) FindRpcHandler(serviceName string) rpc.IRpcHandler {
return pService.GetRpcHandler() return pService.GetRpcHandler()
} }
func (cls *Cluster) getRpcClient(nodeId string) (*rpc.Client,bool) { func (cls *Cluster) getRpcClient(nodeId string) (*rpc.Client, bool) {
c, ok := cls.mapRpc[nodeId] c, ok := cls.mapRpc[nodeId]
if ok == false { if ok == false {
return nil,false return nil, false
} }
return c.client,c.nodeInfo.Retire return c.client, c.nodeInfo.Retire
} }
func (cls *Cluster) GetRpcClient(nodeId string) (*rpc.Client,bool) { func (cls *Cluster) GetRpcClient(nodeId string) (*rpc.Client, bool) {
cls.locker.RLock() cls.locker.RLock()
defer cls.locker.RUnlock() defer cls.locker.RUnlock()
return cls.getRpcClient(nodeId) return cls.getRpcClient(nodeId)
} }
func GetRpcClient(nodeId string, serviceMethod string,filterRetire bool, clientList []*rpc.Client) (error, int) { func GetNodeIdByTemplateService(templateServiceName string, rpcClientList []*rpc.Client, filterRetire bool) (error, []*rpc.Client) {
return GetCluster().GetNodeIdByTemplateService(templateServiceName, rpcClientList, filterRetire)
}
func GetRpcClient(nodeId string, serviceMethod string, filterRetire bool, clientList []*rpc.Client) (error, []*rpc.Client) {
if nodeId != rpc.NodeIdNull { if nodeId != rpc.NodeIdNull {
pClient,retire := GetCluster().GetRpcClient(nodeId) pClient, retire := GetCluster().GetRpcClient(nodeId)
if pClient == nil { if pClient == nil {
return fmt.Errorf("cannot find nodeid %d!", nodeId), 0 return fmt.Errorf("cannot find nodeid %s", nodeId), nil
} }
//如果需要筛选掉退休结点 //如果需要筛选掉退休结点
if filterRetire == true && retire == true { if filterRetire == true && retire == true {
return fmt.Errorf("cannot find nodeid %d!", nodeId), 0 return fmt.Errorf("cannot find nodeid %s", nodeId), nil
} }
clientList[0] = pClient clientList = append(clientList, pClient)
return nil, 1 return nil, clientList
} }
findIndex := strings.Index(serviceMethod, ".") findIndex := strings.Index(serviceMethod, ".")
if findIndex == -1 { if findIndex == -1 {
return fmt.Errorf("servicemethod param %s is error!", serviceMethod), 0 return fmt.Errorf("servicemethod param %s is error!", serviceMethod), nil
} }
serviceName := serviceMethod[:findIndex] serviceName := serviceMethod[:findIndex]
//1.找到对应的rpcNodeid
return GetCluster().GetNodeIdByService(serviceName, clientList, filterRetire) return GetCluster().GetNodeIdByService(serviceName, clientList, filterRetire)
} }
@@ -290,7 +320,7 @@ func GetRpcServer() rpc.IServer {
} }
func (cls *Cluster) IsNodeConnected(nodeId string) bool { func (cls *Cluster) IsNodeConnected(nodeId string) bool {
pClient,_ := cls.GetRpcClient(nodeId) pClient, _ := cls.GetRpcClient(nodeId)
return pClient != nil && pClient.IsConnected() return pClient != nil && pClient.IsConnected()
} }
@@ -298,18 +328,18 @@ func (cls *Cluster) IsNodeRetire(nodeId string) bool {
cls.locker.RLock() cls.locker.RLock()
defer cls.locker.RUnlock() defer cls.locker.RUnlock()
_,retire :=cls.getRpcClient(nodeId) _, retire := cls.getRpcClient(nodeId)
return retire return retire
} }
func (cls *Cluster) NotifyAllService(event event.IEvent){ func (cls *Cluster) NotifyAllService(event event.IEvent) {
cls.rpcEventLocker.Lock() cls.rpcEventLocker.Lock()
defer cls.rpcEventLocker.Unlock() defer cls.rpcEventLocker.Unlock()
for serviceName, _ := range cls.mapServiceListenRpcEvent { for serviceName := range cls.mapServiceListenRpcEvent {
ser := service.GetService(serviceName) ser := service.GetService(serviceName)
if ser == nil { if ser == nil {
log.Error("cannot find service name "+serviceName) log.Error("cannot find service name " + serviceName)
continue continue
} }
@@ -369,42 +399,86 @@ func GetNodeByServiceName(serviceName string) map[string]struct{} {
} }
mapNodeId := map[string]struct{}{} mapNodeId := map[string]struct{}{}
for nodeId,_ := range mapNode { for nodeId := range mapNode {
mapNodeId[nodeId] = struct{}{} mapNodeId[nodeId] = struct{}{}
} }
return mapNodeId return mapNodeId
} }
// GetNodeByTemplateServiceName 通过模板服务名获取服务名,返回 map[serviceName真实服务名]NodeId
func GetNodeByTemplateServiceName(templateServiceName string) map[string]string {
cluster.locker.RLock()
defer cluster.locker.RUnlock()
mapServiceName := cluster.mapTemplateServiceNode[templateServiceName]
mapNodeId := make(map[string]string, 9)
for serviceName := range mapServiceName {
mapNode, ok := cluster.mapServiceNode[serviceName]
if ok == false {
return nil
}
for nodeId := range mapNode {
mapNodeId[serviceName] = nodeId
}
}
return mapNodeId
}
func (cls *Cluster) GetGlobalCfg() interface{} { func (cls *Cluster) GetGlobalCfg() interface{} {
return cls.globalCfg return cls.globalCfg
} }
func (cls *Cluster) GetNodeInfo(nodeId string) (NodeInfo,bool) { func (cls *Cluster) ParseGlobalCfg(cfg interface{}) error {
if cls.globalCfg == nil {
return errors.New("no service configuration found")
}
rv := reflect.ValueOf(cls.globalCfg)
if rv.Kind() == reflect.Ptr && rv.IsNil() {
return errors.New("no service configuration found")
}
bytes, err := json.Marshal(cls.globalCfg)
if err != nil {
return err
}
return json.Unmarshal(bytes, cfg)
}
func (cls *Cluster) GetNodeInfo(nodeId string) (NodeInfo, bool) {
cls.locker.RLock() cls.locker.RLock()
defer cls.locker.RUnlock() defer cls.locker.RUnlock()
nodeInfo,ok:= cls.mapRpc[nodeId] nodeInfo, ok := cls.mapRpc[nodeId]
if ok == false || nodeInfo == nil { if ok == false || nodeInfo == nil {
return NodeInfo{},false return NodeInfo{}, false
} }
return nodeInfo.nodeInfo,true return nodeInfo.nodeInfo, true
} }
func (dc *Cluster) CanDiscoveryService(fromMasterNodeId string,serviceName string) bool{ func (cls *Cluster) CanDiscoveryService(fromMasterNodeId string, serviceName string) bool {
canDiscovery := true canDiscovery := true
for i:=0;i<len(dc.GetLocalNodeInfo().DiscoveryService);i++{ splitServiceName := strings.Split(serviceName, ":")
masterNodeId := dc.GetLocalNodeInfo().DiscoveryService[i].MasterNodeId if len(splitServiceName) == 2 {
serviceName = splitServiceName[0]
}
for i := 0; i < len(cls.GetLocalNodeInfo().DiscoveryService); i++ {
masterNodeId := cls.GetLocalNodeInfo().DiscoveryService[i].MasterNodeId
//无效的配置,则跳过 //无效的配置,则跳过
if masterNodeId == rpc.NodeIdNull && len(dc.GetLocalNodeInfo().DiscoveryService[i].ServiceList)==0 { if masterNodeId == rpc.NodeIdNull && len(cls.GetLocalNodeInfo().DiscoveryService[i].ServiceList) == 0 {
continue continue
} }
canDiscovery = false canDiscovery = false
if masterNodeId == fromMasterNodeId || masterNodeId == rpc.NodeIdNull { if masterNodeId == fromMasterNodeId || masterNodeId == rpc.NodeIdNull {
for _,discoveryService := range dc.GetLocalNodeInfo().DiscoveryService[i].ServiceList { for _, discoveryService := range cls.GetLocalNodeInfo().DiscoveryService[i].ServiceList {
if discoveryService == serviceName { if discoveryService == serviceName {
return true return true
} }
@@ -413,4 +487,4 @@ func (dc *Cluster) CanDiscoveryService(fromMasterNodeId string,serviceName strin
} }
return canDiscovery return canDiscovery
} }

View File

@@ -3,24 +3,23 @@ package cluster
import "github.com/duanhf2012/origin/v2/rpc" import "github.com/duanhf2012/origin/v2/rpc"
type ConfigDiscovery struct { type ConfigDiscovery struct {
funDelNode FunDelNode funDelNode FunDelNode
funSetNode FunSetNode funSetNode FunSetNode
localNodeId string localNodeId string
} }
func (discovery *ConfigDiscovery) InitDiscovery(localNodeId string, funDelNode FunDelNode, funSetNode FunSetNode) error {
func (discovery *ConfigDiscovery) InitDiscovery(localNodeId string,funDelNode FunDelNode,funSetNode FunSetNode) error{
discovery.localNodeId = localNodeId discovery.localNodeId = localNodeId
discovery.funDelNode = funDelNode discovery.funDelNode = funDelNode
discovery.funSetNode = funSetNode discovery.funSetNode = funSetNode
//解析本地其他服务配置 //解析本地其他服务配置
_,nodeInfoList,_,err := GetCluster().readLocalClusterConfig(rpc.NodeIdNull) _, nodeInfoList, _, err := GetCluster().readLocalClusterConfig(rpc.NodeIdNull)
if err != nil { if err != nil {
return err return err
} }
for _,nodeInfo := range nodeInfoList { for _, nodeInfo := range nodeInfoList {
if nodeInfo.NodeId == localNodeId { if nodeInfo.NodeId == localNodeId {
continue continue
} }
@@ -30,5 +29,3 @@ func (discovery *ConfigDiscovery) InitDiscovery(localNodeId string,funDelNode Fu
return nil return nil
} }

View File

@@ -5,17 +5,17 @@ import (
"github.com/duanhf2012/origin/v2/service" "github.com/duanhf2012/origin/v2/service"
) )
func (cls *Cluster) setupDiscovery(localNodeId string, setupServiceFun SetupServiceFun) error{ func (cls *Cluster) setupDiscovery(localNodeId string, setupServiceFun SetupServiceFun) error {
if cls.discoveryInfo.getDiscoveryType() == OriginType { //origin类型服务发现 if cls.discoveryInfo.getDiscoveryType() == OriginType { //origin类型服务发现
return cls.setupOriginDiscovery(localNodeId,setupServiceFun) return cls.setupOriginDiscovery(localNodeId, setupServiceFun)
}else if cls.discoveryInfo.getDiscoveryType() == EtcdType{//etcd类型服务发现 } else if cls.discoveryInfo.getDiscoveryType() == EtcdType { //etcd类型服务发现
return cls.setupEtcdDiscovery(localNodeId,setupServiceFun) return cls.setupEtcdDiscovery(localNodeId, setupServiceFun)
} }
return cls.setupConfigDiscovery(localNodeId,setupServiceFun) return cls.setupConfigDiscovery(localNodeId, setupServiceFun)
} }
func (cls *Cluster) setupOriginDiscovery(localNodeId string, setupServiceFun SetupServiceFun) error{ func (cls *Cluster) setupOriginDiscovery(localNodeId string, setupServiceFun SetupServiceFun) error {
if cls.serviceDiscovery != nil { if cls.serviceDiscovery != nil {
return errors.New("service discovery has been setup") return errors.New("service discovery has been setup")
} }
@@ -27,6 +27,7 @@ func (cls *Cluster) setupOriginDiscovery(localNodeId string, setupServiceFun Set
} }
cls.serviceDiscovery = getOriginDiscovery() cls.serviceDiscovery = getOriginDiscovery()
//2.如果为动态服务发现安装本地发现服务 //2.如果为动态服务发现安装本地发现服务
if localMaster == true { if localMaster == true {
setupServiceFun(&masterService) setupServiceFun(&masterService)
@@ -36,11 +37,10 @@ func (cls *Cluster) setupOriginDiscovery(localNodeId string, setupServiceFun Set
setupServiceFun(&clientService) setupServiceFun(&clientService)
cls.AddDiscoveryService(OriginDiscoveryClientName, true) cls.AddDiscoveryService(OriginDiscoveryClientName, true)
return nil return nil
} }
func (cls *Cluster) setupEtcdDiscovery(localNodeId string, setupServiceFun SetupServiceFun) error{ func (cls *Cluster) setupEtcdDiscovery(localNodeId string, setupServiceFun SetupServiceFun) error {
if cls.serviceDiscovery != nil { if cls.serviceDiscovery != nil {
return errors.New("service discovery has been setup") return errors.New("service discovery has been setup")
} }
@@ -48,12 +48,12 @@ func (cls *Cluster) setupEtcdDiscovery(localNodeId string, setupServiceFun Setup
//setup etcd service //setup etcd service
cls.serviceDiscovery = getEtcdDiscovery() cls.serviceDiscovery = getEtcdDiscovery()
setupServiceFun(cls.serviceDiscovery.(service.IService)) setupServiceFun(cls.serviceDiscovery.(service.IService))
cls.AddDiscoveryService(cls.serviceDiscovery.(service.IService).GetName(),false) cls.AddDiscoveryService(cls.serviceDiscovery.(service.IService).GetName(), false)
return nil return nil
} }
func (cls *Cluster) setupConfigDiscovery(localNodeId string, setupServiceFun SetupServiceFun) error{ func (cls *Cluster) setupConfigDiscovery(localNodeId string, setupServiceFun SetupServiceFun) error {
if cls.serviceDiscovery != nil { if cls.serviceDiscovery != nil {
return errors.New("service discovery has been setup") return errors.New("service discovery has been setup")
} }

View File

@@ -1,7 +1,11 @@
package cluster package cluster
import ( import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"github.com/duanhf2012/origin/v2/event" "github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/rpc" "github.com/duanhf2012/origin/v2/rpc"
@@ -10,46 +14,45 @@ import (
"go.etcd.io/etcd/api/v3/mvccpb" "go.etcd.io/etcd/api/v3/mvccpb"
"go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/client/v3"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
"time" "os"
"context"
"errors"
"fmt"
"go.uber.org/zap"
"path" "path"
"runtime"
"strings" "strings"
"sync/atomic" "sync/atomic"
"time"
) )
const originDir = "/origin" const originDir = "/origin"
const testKey = originDir+"/_inner/_test_7501f3ed-b716-44c2-0090-fc1ed0166d7a"
type etcdClientInfo struct { type etcdClientInfo struct {
watchKeys []string watchKeys []string
leaseID clientv3.LeaseID leaseID clientv3.LeaseID
keepAliveChan <-chan *clientv3.LeaseKeepAliveResponse keepAliveChan <-chan *clientv3.LeaseKeepAliveResponse
} }
type EtcdDiscoveryService struct { type EtcdDiscoveryService struct {
service.Service service.Service
funDelNode FunDelNode funDelNode FunDelNode
funSetNode FunSetNode funSetNode FunSetNode
localNodeId string localNodeId string
byteLocalNodeInfo string byteLocalNodeInfo string
mapClient map[*clientv3.Client]*etcdClientInfo mapClient map[*clientv3.Client]*etcdClientInfo
isClose int32 isClose int32
bRetire bool bRetire bool
mapDiscoveryNodeId map[string]map[string]struct{} //map[networkName]map[nodeId] mapDiscoveryNodeId map[string]map[string]struct{} //map[networkName]map[nodeId]
} }
func getEtcdDiscovery() (IServiceDiscovery) { var etcdDiscovery *EtcdDiscoveryService
etcdDiscovery := &EtcdDiscoveryService{}
func getEtcdDiscovery() IServiceDiscovery {
if etcdDiscovery == nil {
etcdDiscovery = &EtcdDiscoveryService{}
}
return etcdDiscovery return etcdDiscovery
} }
func (ed *EtcdDiscoveryService) InitDiscovery(localNodeId string,funDelNode FunDelNode,funSetNode FunSetNode) error { func (ed *EtcdDiscoveryService) InitDiscovery(localNodeId string, funDelNode FunDelNode, funSetNode FunSetNode) error {
ed.localNodeId = localNodeId ed.localNodeId = localNodeId
ed.funDelNode = funDelNode ed.funDelNode = funDelNode
@@ -58,24 +61,24 @@ func (ed *EtcdDiscoveryService) InitDiscovery(localNodeId string,funDelNode FunD
return nil return nil
} }
const( const (
eeGets = 0 eeGets = 0
eePut = 1 eePut = 1
eeDelete = 2 eeDelete = 2
) )
type etcdDiscoveryEvent struct { type etcdDiscoveryEvent struct {
typ int typ int
watchKey string watchKey string
Kvs []*mvccpb.KeyValue Kvs []*mvccpb.KeyValue
} }
func (ee *etcdDiscoveryEvent) GetEventType() event.EventType{ func (ee *etcdDiscoveryEvent) GetEventType() event.EventType {
return event.Sys_Event_EtcdDiscovery return event.Sys_Event_EtcdDiscovery
} }
func (ed *EtcdDiscoveryService) OnInit() error { func (ed *EtcdDiscoveryService) OnInit() error {
ed.mapClient = make(map[*clientv3.Client]*etcdClientInfo,1) ed.mapClient = make(map[*clientv3.Client]*etcdClientInfo, 1)
ed.mapDiscoveryNodeId = make(map[string]map[string]struct{}) ed.mapDiscoveryNodeId = make(map[string]map[string]struct{})
ed.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_EtcdDiscovery, ed.GetEventHandler(), ed.OnEtcdDiscovery) ed.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_EtcdDiscovery, ed.GetEventHandler(), ed.OnEtcdDiscovery)
@@ -90,28 +93,56 @@ func (ed *EtcdDiscoveryService) OnInit() error {
return errors.New("etcd discovery config is nil.") return errors.New("etcd discovery config is nil.")
} }
for i:=0;i<len(etcdDiscoveryCfg.EtcdList);i++{ for i := 0; i < len(etcdDiscoveryCfg.EtcdList); i++ {
client, cerr := clientv3.New(clientv3.Config{ var client *clientv3.Client
Endpoints: etcdDiscoveryCfg.EtcdList[i].Endpoints, var tlsConfig *tls.Config
DialTimeout: etcdDiscoveryCfg.DialTimeoutMillisecond,
Logger: zap.NewNop(),
})
if cerr != nil { if etcdDiscoveryCfg.EtcdList[i].Cert != "" {
log.Error("etcd discovery init fail",log.ErrorAttr("err",cerr)) // load cert
return cerr cert, cErr := tls.LoadX509KeyPair(etcdDiscoveryCfg.EtcdList[i].Cert, etcdDiscoveryCfg.EtcdList[i].CertKey)
if cErr != nil {
log.Error("load cert error", log.ErrorField("err", cErr))
return cErr
}
// load root ca
caData, cErr := os.ReadFile(etcdDiscoveryCfg.EtcdList[i].Ca)
if cErr != nil {
log.Error("load root ca error", log.ErrorField("err", cErr))
return cErr
}
pool := x509.NewCertPool()
pool.AppendCertsFromPEM(caData)
tlsConfig = &tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: pool,
}
} }
ctx,_:=context.WithTimeout(context.Background(),time.Second*3) client, err = clientv3.New(clientv3.Config{
_,err = client.Leases(ctx) Endpoints: etcdDiscoveryCfg.EtcdList[i].Endpoints,
DialTimeout: etcdDiscoveryCfg.DialTimeoutMillisecond,
Username: etcdDiscoveryCfg.EtcdList[i].UserName,
Password: etcdDiscoveryCfg.EtcdList[i].Password,
Logger: log.GetLogger().Logger,
TLS: tlsConfig,
})
if err != nil { if err != nil {
log.Error("etcd discovery init fail",log.Any("endpoint",etcdDiscoveryCfg.EtcdList[i].Endpoints),log.ErrorAttr("err",err)) log.Error("etcd discovery init fail", log.ErrorField("err", err))
return err
}
ctx, _ := context.WithTimeout(context.Background(), time.Second*3)
_, err = client.Leases(ctx)
if err != nil {
log.Error("etcd discovery init fail", log.Any("endpoint", etcdDiscoveryCfg.EtcdList[i].Endpoints), log.ErrorField("err", err))
return err return err
} }
ec := &etcdClientInfo{} ec := &etcdClientInfo{}
for _, networkName := range etcdDiscoveryCfg.EtcdList[i].NetworkName { for _, networkName := range etcdDiscoveryCfg.EtcdList[i].NetworkName {
ec.watchKeys = append(ec.watchKeys,fmt.Sprintf("%s/%s",originDir,networkName)) ec.watchKeys = append(ec.watchKeys, fmt.Sprintf("%s/%s", originDir, networkName))
} }
ed.mapClient[client] = ec ed.mapClient[client] = ec
@@ -120,36 +151,36 @@ func (ed *EtcdDiscoveryService) OnInit() error {
return nil return nil
} }
func (ed *EtcdDiscoveryService) getRegisterKey(watchkey string) string{ func (ed *EtcdDiscoveryService) getRegisterKey(watchkey string) string {
return watchkey+"/"+ed.localNodeId return watchkey + "/" + ed.localNodeId
} }
func (ed *EtcdDiscoveryService) registerServiceByClient(client *clientv3.Client,etcdClient *etcdClientInfo) { func (ed *EtcdDiscoveryService) registerServiceByClient(client *clientv3.Client, etcdClient *etcdClientInfo) {
// 创建租约 // 创建租约
var err error var err error
var resp *clientv3.LeaseGrantResponse var resp *clientv3.LeaseGrantResponse
resp, err = client.Grant(context.Background(), cluster.GetEtcdDiscovery().TTLSecond) resp, err = client.Grant(context.Background(), cluster.GetEtcdDiscovery().TTLSecond)
if err != nil { if err != nil {
log.Error("etcd registerService fail",log.ErrorAttr("err",err)) log.Error("etcd registerService fail", log.ErrorField("err", err))
ed.tryRegisterService(client,etcdClient) ed.tryRegisterService(client, etcdClient)
return return
} }
etcdClient.leaseID = resp.ID etcdClient.leaseID = resp.ID
for _,watchKey:= range etcdClient.watchKeys { for _, watchKey := range etcdClient.watchKeys {
// 注册服务节点到 etcd // 注册服务节点到 etcd
_, err = client.Put(context.Background(), ed.getRegisterKey(watchKey), ed.byteLocalNodeInfo, clientv3.WithLease(resp.ID)) _, err = client.Put(context.Background(), ed.getRegisterKey(watchKey), ed.byteLocalNodeInfo, clientv3.WithLease(resp.ID))
if err != nil { if err != nil {
log.Error("etcd Put fail",log.ErrorAttr("err",err)) log.Error("etcd Put fail", log.ErrorField("err", err))
ed.tryRegisterService(client,etcdClient) ed.tryRegisterService(client, etcdClient)
return return
} }
} }
etcdClient.keepAliveChan,err = client.KeepAlive(context.Background(), etcdClient.leaseID) etcdClient.keepAliveChan, err = client.KeepAlive(context.Background(), etcdClient.leaseID)
if err != nil { if err != nil {
log.Error("etcd KeepAlive fail",log.ErrorAttr("err",err)) log.Error("etcd KeepAlive fail", log.ErrorField("err", err))
ed.tryRegisterService(client,etcdClient) ed.tryRegisterService(client, etcdClient)
return return
} }
@@ -159,8 +190,8 @@ func (ed *EtcdDiscoveryService) registerServiceByClient(client *clientv3.Client,
case _, ok := <-etcdClient.keepAliveChan: case _, ok := <-etcdClient.keepAliveChan:
//log.Debug("ok",log.Any("addr",client.Endpoints())) //log.Debug("ok",log.Any("addr",client.Endpoints()))
if !ok { if !ok {
log.Error("etcd keepAliveChan fail",log.Any("watchKeys",etcdClient.watchKeys)) log.Error("etcd keepAliveChan fail", log.Any("watchKeys", etcdClient.watchKeys))
ed.tryRegisterService(client,etcdClient) ed.tryRegisterService(client, etcdClient)
return return
} }
} }
@@ -168,23 +199,22 @@ func (ed *EtcdDiscoveryService) registerServiceByClient(client *clientv3.Client,
}() }()
} }
func (ed *EtcdDiscoveryService) tryRegisterService(client *clientv3.Client, etcdClient *etcdClientInfo) {
func (ed *EtcdDiscoveryService) tryRegisterService(client *clientv3.Client,etcdClient *etcdClientInfo){
if ed.isStop() { if ed.isStop() {
return return
} }
ed.AfterFunc(time.Second*3, func(t *timer.Timer) { ed.AfterFunc(time.Second*3, func(t *timer.Timer) {
ed.registerServiceByClient(client,etcdClient) ed.registerServiceByClient(client, etcdClient)
}) })
} }
func (ed *EtcdDiscoveryService) tryWatch(client *clientv3.Client,etcdClient *etcdClientInfo) { func (ed *EtcdDiscoveryService) tryWatch(client *clientv3.Client, etcdClient *etcdClientInfo) {
if ed.isStop() { if ed.isStop() {
return return
} }
ed.AfterFunc(time.Second*3, func(t *timer.Timer) { ed.AfterFunc(time.Second*3, func(t *timer.Timer) {
ed.watchByClient(client,etcdClient) ed.watchByClient(client, etcdClient)
}) })
} }
@@ -196,14 +226,14 @@ func (ed *EtcdDiscoveryService) tryLaterRetire() {
}) })
} }
func (ed *EtcdDiscoveryService) retire() error{ func (ed *EtcdDiscoveryService) retire() error {
//从etcd中更新 //从etcd中更新
for c,ec := range ed.mapClient { for c, ec := range ed.mapClient {
for _, watchKey := range ec.watchKeys { for _, watchKey := range ec.watchKeys {
// 注册服务节点到 etcd // 注册服务节点到 etcd
_, err := c.Put(context.Background(), ed.getRegisterKey(watchKey), ed.byteLocalNodeInfo, clientv3.WithLease(ec.leaseID)) _, err := c.Put(context.Background(), ed.getRegisterKey(watchKey), ed.byteLocalNodeInfo, clientv3.WithLease(ec.leaseID))
if err != nil { if err != nil {
log.Error("etcd Put fail", log.ErrorAttr("err", err)) log.Error("etcd Put fail", log.ErrorField("err", err))
return err return err
} }
} }
@@ -212,32 +242,32 @@ func (ed *EtcdDiscoveryService) retire() error{
return nil return nil
} }
func (ed *EtcdDiscoveryService) OnRetire(){ func (ed *EtcdDiscoveryService) OnRetire() {
ed.bRetire = true ed.bRetire = true
ed.marshalNodeInfo() ed.marshalNodeInfo()
if ed.retire()!= nil { if ed.retire() != nil {
ed.tryLaterRetire() ed.tryLaterRetire()
} }
} }
func (ed *EtcdDiscoveryService) OnRelease(){ func (ed *EtcdDiscoveryService) OnRelease() {
atomic.StoreInt32(&ed.isClose,1) atomic.StoreInt32(&ed.isClose, 1)
ed.close() ed.close()
} }
func (ed *EtcdDiscoveryService) isStop() bool{ func (ed *EtcdDiscoveryService) isStop() bool {
return atomic.LoadInt32(&ed.isClose) == 1 return atomic.LoadInt32(&ed.isClose) == 1
} }
func (nd *EtcdDiscoveryService) OnStart() { func (ed *EtcdDiscoveryService) OnStart() {
for c, ec := range nd.mapClient { for c, ec := range ed.mapClient {
nd.tryRegisterService(c,ec) ed.tryRegisterService(c, ec)
nd.tryWatch(c,ec) ed.tryWatch(c, ec)
} }
} }
func (ed *EtcdDiscoveryService) marshalNodeInfo() error{ func (ed *EtcdDiscoveryService) marshalNodeInfo() error {
nInfo := cluster.GetLocalNodeInfo() nInfo := cluster.GetLocalNodeInfo()
var nodeInfo rpc.NodeInfo var nodeInfo rpc.NodeInfo
nodeInfo.NodeId = nInfo.NodeId nodeInfo.NodeId = nInfo.NodeId
@@ -246,15 +276,15 @@ func (ed *EtcdDiscoveryService) marshalNodeInfo() error{
nodeInfo.PublicServiceList = nInfo.PublicServiceList nodeInfo.PublicServiceList = nInfo.PublicServiceList
nodeInfo.MaxRpcParamLen = nInfo.MaxRpcParamLen nodeInfo.MaxRpcParamLen = nInfo.MaxRpcParamLen
byteLocalNodeInfo,err := proto.Marshal(&nodeInfo) byteLocalNodeInfo, err := proto.Marshal(&nodeInfo)
if err ==nil{ if err == nil {
ed.byteLocalNodeInfo = string(byteLocalNodeInfo) ed.byteLocalNodeInfo = string(byteLocalNodeInfo)
} }
return err return err
} }
func (ed *EtcdDiscoveryService) setNodeInfo(networkName string,nodeInfo *rpc.NodeInfo) bool{ func (ed *EtcdDiscoveryService) setNodeInfo(networkName string, nodeInfo *rpc.NodeInfo) bool {
if nodeInfo == nil || nodeInfo.Private == true || nodeInfo.NodeId == ed.localNodeId { if nodeInfo == nil || nodeInfo.Private == true || nodeInfo.NodeId == ed.localNodeId {
return false return false
} }
@@ -262,8 +292,8 @@ func (ed *EtcdDiscoveryService) setNodeInfo(networkName string,nodeInfo *rpc.Nod
//筛选关注的服务 //筛选关注的服务
var discoverServiceSlice = make([]string, 0, 24) var discoverServiceSlice = make([]string, 0, 24)
for _, pubService := range nodeInfo.PublicServiceList { for _, pubService := range nodeInfo.PublicServiceList {
if cluster.CanDiscoveryService(networkName,pubService) == true { if cluster.CanDiscoveryService(networkName, pubService) == true {
discoverServiceSlice = append(discoverServiceSlice,pubService) discoverServiceSlice = append(discoverServiceSlice, pubService)
} }
} }
@@ -285,58 +315,54 @@ func (ed *EtcdDiscoveryService) setNodeInfo(networkName string,nodeInfo *rpc.Nod
return true return true
} }
func (ed *EtcdDiscoveryService) close(){ func (ed *EtcdDiscoveryService) close() {
for c, ec := range ed.mapClient { for c, ec := range ed.mapClient {
if _, err := c.Revoke(context.Background(), ec.leaseID); err != nil { if _, err := c.Revoke(context.Background(), ec.leaseID); err != nil {
log.Error("etcd Revoke fail",log.ErrorAttr("err",err)) log.Error("etcd Revoke fail", log.ErrorField("err", err))
} }
c.Watcher.Close() c.Watcher.Close()
err := c.Close() err := c.Close()
if err != nil { if err != nil {
log.Error("etcd Close fail",log.ErrorAttr("err",err)) log.Error("etcd Close fail", log.ErrorField("err", err))
} }
} }
} }
func (ed *EtcdDiscoveryService) getServices(client *clientv3.Client,etcdClient *etcdClientInfo,watchKey string) bool { func (ed *EtcdDiscoveryService) getServices(client *clientv3.Client, etcdClient *etcdClientInfo, watchKey string) bool {
// 根据前缀获取现有的key // 根据前缀获取现有的key
resp, err := client.Get(context.Background(), watchKey, clientv3.WithPrefix()) resp, err := client.Get(context.Background(), watchKey, clientv3.WithPrefix())
if err != nil { if err != nil {
log.Error("etcd Get fail", log.ErrorAttr("err", err)) log.Error("etcd Get fail", log.ErrorField("err", err))
ed.tryWatch(client, etcdClient) ed.tryWatch(client, etcdClient)
return false return false
} }
// 遍历获取得到的k和v // 遍历获取得到的k和v
ed.notifyGets(watchKey,resp.Kvs) ed.notifyGets(watchKey, resp.Kvs)
return true return true
} }
func (ed *EtcdDiscoveryService) watchByClient(client *clientv3.Client,etcdClient *etcdClientInfo){ func (ed *EtcdDiscoveryService) watchByClient(client *clientv3.Client, etcdClient *etcdClientInfo) {
//先关闭所有的watcher //先关闭所有的watcher
for _, watchKey := range etcdClient.watchKeys { for _, watchKey := range etcdClient.watchKeys {
// 监视前缀修改变更server // 监视前缀修改变更server
go ed.watcher(client,etcdClient, watchKey) go ed.watcher(client, etcdClient, watchKey)
} }
} }
// watcher 监听Key的前缀 // watcher 监听Key的前缀
func (ed *EtcdDiscoveryService) watcher(client *clientv3.Client,etcdClient *etcdClientInfo,watchKey string) { func (ed *EtcdDiscoveryService) watcher(client *clientv3.Client, etcdClient *etcdClientInfo, watchKey string) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096) log.StackError(fmt.Sprint(r))
l := runtime.Stack(buf, false) ed.tryWatch(client, etcdClient)
errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString))
ed.tryWatch(client,etcdClient)
} }
}() }()
rch := client.Watch(context.Background(), watchKey, clientv3.WithPrefix()) rch := client.Watch(context.Background(), watchKey, clientv3.WithPrefix())
if ed.getServices(client,etcdClient,watchKey) == false { if ed.getServices(client, etcdClient, watchKey) == false {
return return
} }
@@ -344,68 +370,68 @@ func (ed *EtcdDiscoveryService) watcher(client *clientv3.Client,etcdClient *etcd
for _, ev := range wresp.Events { for _, ev := range wresp.Events {
switch ev.Type { switch ev.Type {
case clientv3.EventTypePut: // 修改或者新增 case clientv3.EventTypePut: // 修改或者新增
ed.notifyPut(watchKey,ev.Kv) ed.notifyPut(watchKey, ev.Kv)
case clientv3.EventTypeDelete: // 删除 case clientv3.EventTypeDelete: // 删除
ed.notifyDelete(watchKey,ev.Kv) ed.notifyDelete(watchKey, ev.Kv)
} }
} }
} }
ed.tryWatch(client,etcdClient) ed.tryWatch(client, etcdClient)
} }
func (ed *EtcdDiscoveryService) setNode(netWorkName string,byteNode []byte) string{ func (ed *EtcdDiscoveryService) setNode(netWorkName string, byteNode []byte) string {
var nodeInfo rpc.NodeInfo var nodeInfo rpc.NodeInfo
err := proto.Unmarshal(byteNode,&nodeInfo) err := proto.Unmarshal(byteNode, &nodeInfo)
if err != nil { if err != nil {
log.Error("Unmarshal fail",log.String("netWorkName",netWorkName),log.ErrorAttr("err",err)) log.Error("Unmarshal fail", log.String("netWorkName", netWorkName), log.ErrorField("err", err))
return "" return ""
} }
ed.setNodeInfo(netWorkName,&nodeInfo) ed.setNodeInfo(netWorkName, &nodeInfo)
return nodeInfo.NodeId return nodeInfo.NodeId
} }
func (ed *EtcdDiscoveryService) delNode(fullKey string) string{ func (ed *EtcdDiscoveryService) delNode(fullKey string) string {
nodeId := ed.getNodeId(fullKey) nodeId := ed.getNodeId(fullKey)
if nodeId == ed.localNodeId { if nodeId == ed.localNodeId {
return "" return ""
} }
ed.funDelNode(nodeId) ed.funDelNode(nodeId)
return nodeId return nodeId
} }
func (ed *EtcdDiscoveryService) getNetworkNameByWatchKey(watchKey string) string{ func (ed *EtcdDiscoveryService) getNetworkNameByWatchKey(watchKey string) string {
return watchKey[strings.LastIndex(watchKey,"/")+1:] return watchKey[strings.LastIndex(watchKey, "/")+1:]
} }
func (ed *EtcdDiscoveryService) getNetworkNameByFullKey(fullKey string) string{ func (ed *EtcdDiscoveryService) getNetworkNameByFullKey(fullKey string) string {
return fullKey[len(originDir)+1:strings.LastIndex(fullKey,"/")] return fullKey[len(originDir)+1 : strings.LastIndex(fullKey, "/")]
} }
func (ed *EtcdDiscoveryService) getNodeId(fullKey string) string{ func (ed *EtcdDiscoveryService) getNodeId(fullKey string) string {
return fullKey[strings.LastIndex(fullKey,"/")+1:] return fullKey[strings.LastIndex(fullKey, "/")+1:]
} }
func (ed *EtcdDiscoveryService) OnEtcdDiscovery(ev event.IEvent){ func (ed *EtcdDiscoveryService) OnEtcdDiscovery(ev event.IEvent) {
disEvent := ev.(*etcdDiscoveryEvent) disEvent := ev.(*etcdDiscoveryEvent)
switch disEvent.typ { switch disEvent.typ {
case eeGets: case eeGets:
ed.OnEventGets(disEvent.watchKey,disEvent.Kvs) ed.OnEventGets(disEvent.watchKey, disEvent.Kvs)
case eePut: case eePut:
if len(disEvent.Kvs) == 1 { if len(disEvent.Kvs) == 1 {
ed.OnEventPut(disEvent.watchKey,disEvent.Kvs[0]) ed.OnEventPut(disEvent.watchKey, disEvent.Kvs[0])
} }
case eeDelete: case eeDelete:
if len(disEvent.Kvs) == 1 { if len(disEvent.Kvs) == 1 {
ed.OnEventDelete(disEvent.watchKey,disEvent.Kvs[0]) ed.OnEventDelete(disEvent.watchKey, disEvent.Kvs[0])
} }
} }
} }
func (ed *EtcdDiscoveryService) notifyGets(watchKey string,Kvs []*mvccpb.KeyValue) { func (ed *EtcdDiscoveryService) notifyGets(watchKey string, Kvs []*mvccpb.KeyValue) {
var ev etcdDiscoveryEvent var ev etcdDiscoveryEvent
ev.typ = eeGets ev.typ = eeGets
ev.watchKey = watchKey ev.watchKey = watchKey
@@ -413,54 +439,54 @@ func (ed *EtcdDiscoveryService) notifyGets(watchKey string,Kvs []*mvccpb.KeyValu
ed.NotifyEvent(&ev) ed.NotifyEvent(&ev)
} }
func (ed *EtcdDiscoveryService) notifyPut(watchKey string,Kvs *mvccpb.KeyValue) { func (ed *EtcdDiscoveryService) notifyPut(watchKey string, Kvs *mvccpb.KeyValue) {
var ev etcdDiscoveryEvent var ev etcdDiscoveryEvent
ev.typ = eePut ev.typ = eePut
ev.watchKey = watchKey ev.watchKey = watchKey
ev.Kvs = append(ev.Kvs,Kvs) ev.Kvs = append(ev.Kvs, Kvs)
ed.NotifyEvent(&ev) ed.NotifyEvent(&ev)
} }
func (ed *EtcdDiscoveryService) notifyDelete(watchKey string,Kvs *mvccpb.KeyValue) { func (ed *EtcdDiscoveryService) notifyDelete(watchKey string, Kvs *mvccpb.KeyValue) {
var ev etcdDiscoveryEvent var ev etcdDiscoveryEvent
ev.typ = eeDelete ev.typ = eeDelete
ev.watchKey = watchKey ev.watchKey = watchKey
ev.Kvs = append(ev.Kvs,Kvs) ev.Kvs = append(ev.Kvs, Kvs)
ed.NotifyEvent(&ev) ed.NotifyEvent(&ev)
} }
func (ed *EtcdDiscoveryService) OnEventGets(watchKey string,Kvs []*mvccpb.KeyValue) { func (ed *EtcdDiscoveryService) OnEventGets(watchKey string, Kvs []*mvccpb.KeyValue) {
mapNode := make(map[string]struct{},32) mapNode := make(map[string]struct{}, 32)
for _, kv := range Kvs { for _, kv := range Kvs {
nodeId := ed.setNode(ed.getNetworkNameByFullKey(string(kv.Key)), kv.Value) nodeId := ed.setNode(ed.getNetworkNameByFullKey(string(kv.Key)), kv.Value)
mapNode[nodeId] = struct{}{} mapNode[nodeId] = struct{}{}
ed.addNodeId(watchKey,nodeId) ed.addNodeId(watchKey, nodeId)
} }
// 此段代码为遍历并删除过期节点的逻辑。 // 此段代码为遍历并删除过期节点的逻辑。
// 对于mapDiscoveryNodeId中与watchKey关联的所有节点ID遍历该集合。 // 对于mapDiscoveryNodeId中与watchKey关联的所有节点ID遍历该集合。
// 如果某个节点ID不在mapNode中且不是本地节点ID则调用funDelNode函数删除该节点。 // 如果某个节点ID不在mapNode中且不是本地节点ID则调用funDelNode函数删除该节点。
mapLastNodeId := ed.mapDiscoveryNodeId[watchKey] // 根据watchKey获取对应的节点ID集合 mapLastNodeId := ed.mapDiscoveryNodeId[watchKey] // 根据watchKey获取对应的节点ID集合
for nodeId := range mapLastNodeId { // 遍历所有节点ID for nodeId := range mapLastNodeId { // 遍历所有节点ID
if _,ok := mapNode[nodeId];ok == false && nodeId != ed.localNodeId { // 检查节点是否不存在于mapNode且不是本地节点 if _, ok := mapNode[nodeId]; ok == false && nodeId != ed.localNodeId { // 检查节点是否不存在于mapNode且不是本地节点
ed.funDelNode(nodeId) // 调用函数删除该节点 ed.funDelNode(nodeId) // 调用函数删除该节点
delete(ed.mapDiscoveryNodeId[watchKey],nodeId) delete(ed.mapDiscoveryNodeId[watchKey], nodeId)
} }
} }
} }
func (ed *EtcdDiscoveryService) OnEventPut(watchKey string,Kv *mvccpb.KeyValue) { func (ed *EtcdDiscoveryService) OnEventPut(watchKey string, Kv *mvccpb.KeyValue) {
nodeId := ed.setNode(ed.getNetworkNameByFullKey(string(Kv.Key)), Kv.Value) nodeId := ed.setNode(ed.getNetworkNameByFullKey(string(Kv.Key)), Kv.Value)
ed.addNodeId(watchKey,nodeId) ed.addNodeId(watchKey, nodeId)
} }
func (ed *EtcdDiscoveryService) OnEventDelete(watchKey string,Kv *mvccpb.KeyValue) { func (ed *EtcdDiscoveryService) OnEventDelete(watchKey string, Kv *mvccpb.KeyValue) {
nodeId := ed.delNode(string(Kv.Key)) nodeId := ed.delNode(string(Kv.Key))
delete(ed.mapDiscoveryNodeId[watchKey],nodeId) delete(ed.mapDiscoveryNodeId[watchKey], nodeId)
} }
func (ed *EtcdDiscoveryService) addNodeId(watchKey string,nodeId string) { func (ed *EtcdDiscoveryService) addNodeId(watchKey string, nodeId string) {
if _,ok := ed.mapDiscoveryNodeId[watchKey];ok == false { if _, ok := ed.mapDiscoveryNodeId[watchKey]; ok == false {
ed.mapDiscoveryNodeId[watchKey] = make(map[string]struct{}) ed.mapDiscoveryNodeId[watchKey] = make(map[string]struct{})
} }
@@ -472,50 +498,50 @@ func (ed *EtcdDiscoveryService) OnNodeDisconnect(nodeId string) {
cluster.DiscardNode(nodeId) cluster.DiscardNode(nodeId)
} }
func (ed *EtcdDiscoveryService) RPC_ServiceRecord(etcdServiceRecord *service.EtcdServiceRecordEvent,empty *service.Empty) error{ func (ed *EtcdDiscoveryService) RPC_ServiceRecord(etcdServiceRecord *service.EtcdServiceRecordEvent, empty *service.Empty) error {
var client *clientv3.Client var client *clientv3.Client
//写入到etcd中 //写入到etcd中
for c, info := range ed.mapClient{ for c, info := range ed.mapClient {
for _,watchKey := range info.watchKeys { for _, watchKey := range info.watchKeys {
if ed.getNetworkNameByWatchKey(watchKey) == etcdServiceRecord.NetworkName { if ed.getNetworkNameByWatchKey(watchKey) == etcdServiceRecord.NetworkName {
client = c client = c
break break
}
} }
} }
}
if client == nil { if client == nil {
log.Error("etcd record fail,cannot find network name",log.String("networkName",etcdServiceRecord.NetworkName)) log.Error("etcd record fail,cannot find network name", log.String("networkName", etcdServiceRecord.NetworkName))
return errors.New("annot find network name") return errors.New("annot find network name")
} }
var lg *clientv3.LeaseGrantResponse var lg *clientv3.LeaseGrantResponse
var err error var err error
if etcdServiceRecord.TTLSecond > 0 { if etcdServiceRecord.TTLSecond > 0 {
ctx,_:=context.WithTimeout(context.Background(),time.Second*3) ctx, _ := context.WithTimeout(context.Background(), time.Second*3)
lg, err = client.Grant(ctx, etcdServiceRecord.TTLSecond) lg, err = client.Grant(ctx, etcdServiceRecord.TTLSecond)
if err != nil {
log.Error("etcd record fail,cannot grant lease",log.ErrorAttr("err",err))
return errors.New("cannot grant lease")
}
}
if lg != nil {
ctx,_:=context.WithTimeout(context.Background(),time.Second*3)
_, err = client.Put(ctx, path.Join(originDir,etcdServiceRecord.RecordKey),etcdServiceRecord.RecordInfo, clientv3.WithLease(lg.ID))
if err != nil {
log.Error("etcd record fail,cannot put record",log.ErrorAttr("err",err))
}
return errors.New("cannot put record")
}
_,err = client.Put(context.Background(), path.Join(originDir,etcdServiceRecord.RecordKey),etcdServiceRecord.RecordInfo)
if err != nil { if err != nil {
log.Error("etcd record fail,cannot put record",log.ErrorAttr("err",err)) log.Error("etcd record fail,cannot grant lease", log.ErrorField("err", err))
return errors.New("cannot put record") return errors.New("cannot grant lease")
} }
}
return nil if lg != nil {
ctx, _ := context.WithTimeout(context.Background(), time.Second*3)
_, err = client.Put(ctx, path.Join(originDir, etcdServiceRecord.RecordKey), etcdServiceRecord.RecordInfo, clientv3.WithLease(lg.ID))
if err != nil {
log.Error("etcd record fail,cannot put record", log.ErrorField("err", err))
}
return errors.New("cannot put record")
}
_, err = client.Put(context.Background(), path.Join(originDir, etcdServiceRecord.RecordKey), etcdServiceRecord.RecordInfo)
if err != nil {
log.Error("etcd record fail,cannot put record", log.ErrorField("err", err))
return errors.New("cannot put record")
}
return nil
} }

View File

@@ -1,53 +1,53 @@
package cluster package cluster
import ( import (
"time"
"container/list" "container/list"
"time"
) )
type nodeTTL struct { type nodeTTL struct {
nodeId string nodeId string
refreshTime time.Time refreshTime time.Time
} }
type nodeSetTTL struct { type nodeSetTTL struct {
l *list.List l *list.List
mapElement map[string]*list.Element mapElement map[string]*list.Element
ttl time.Duration ttl time.Duration
} }
func (ns *nodeSetTTL) init(ttl time.Duration) { func (ns *nodeSetTTL) init(ttl time.Duration) {
ns.ttl = ttl ns.ttl = ttl
ns.mapElement = make(map[string]*list.Element,32) ns.mapElement = make(map[string]*list.Element, 32)
ns.l = list.New() ns.l = list.New()
} }
func (ns *nodeSetTTL) removeNode(nodeId string) { func (ns *nodeSetTTL) removeNode(nodeId string) {
ele,ok:=ns.mapElement[nodeId] ele, ok := ns.mapElement[nodeId]
if ok == false { if ok == false {
return return
} }
ns.l.Remove(ele) ns.l.Remove(ele)
delete(ns.mapElement,nodeId) delete(ns.mapElement, nodeId)
} }
func (ns *nodeSetTTL) addAndRefreshNode(nodeId string){ func (ns *nodeSetTTL) addAndRefreshNode(nodeId string) {
ele,ok:=ns.mapElement[nodeId] ele, ok := ns.mapElement[nodeId]
if ok == false { if ok == false {
ele = ns.l.PushBack(nodeId) ele = ns.l.PushBack(nodeId)
ele.Value = &nodeTTL{nodeId,time.Now()} ele.Value = &nodeTTL{nodeId, time.Now()}
ns.mapElement[nodeId] = ele ns.mapElement[nodeId] = ele
return return
} }
ele.Value.(*nodeTTL).refreshTime = time.Now() ele.Value.(*nodeTTL).refreshTime = time.Now()
ns.l.MoveToBack(ele) ns.l.MoveToBack(ele)
} }
func (ns *nodeSetTTL) checkTTL(cb func(nodeIdList []string)){ func (ns *nodeSetTTL) checkTTL(cb func(nodeIdList []string)) {
nodeIdList := []string{} var nodeIdList []string
for{ for {
f := ns.l.Front() f := ns.l.Front()
if f == nil { if f == nil {
break break
@@ -55,17 +55,17 @@ func (ns *nodeSetTTL) checkTTL(cb func(nodeIdList []string)){
nt := f.Value.(*nodeTTL) nt := f.Value.(*nodeTTL)
if time.Now().Sub(nt.refreshTime) > ns.ttl { if time.Now().Sub(nt.refreshTime) > ns.ttl {
nodeIdList = append(nodeIdList,nt.nodeId) nodeIdList = append(nodeIdList, nt.nodeId)
}else{ } else {
break break
} }
//删除结点 //删除结点
ns.l.Remove(f) ns.l.Remove(f)
delete(ns.mapElement,nt.nodeId) delete(ns.mapElement, nt.nodeId)
} }
if len(nodeIdList) >0 { if len(nodeIdList) > 0 {
cb(nodeIdList) cb(nodeIdList)
} }
} }

View File

@@ -14,10 +14,9 @@ const OriginDiscoveryMasterName = "DiscoveryMaster"
const OriginDiscoveryClientName = "DiscoveryClient" const OriginDiscoveryClientName = "DiscoveryClient"
const RegServiceDiscover = OriginDiscoveryMasterName + ".RPC_RegServiceDiscover" const RegServiceDiscover = OriginDiscoveryMasterName + ".RPC_RegServiceDiscover"
const SubServiceDiscover = OriginDiscoveryClientName + ".RPC_SubServiceDiscover" const SubServiceDiscover = OriginDiscoveryClientName + ".RPC_SubServiceDiscover"
const AddSubServiceDiscover = OriginDiscoveryMasterName + ".RPC_AddSubServiceDiscover" const NodeRetireRpcMethod = OriginDiscoveryMasterName + ".RPC_NodeRetire"
const NodeRetireRpcMethod = OriginDiscoveryMasterName+".RPC_NodeRetire" const RpcPingMethod = OriginDiscoveryMasterName + ".RPC_Ping"
const RpcPingMethod = OriginDiscoveryMasterName+".RPC_Ping" const UnRegServiceDiscover = OriginDiscoveryMasterName + ".RPC_UnRegServiceDiscover"
const UnRegServiceDiscover = OriginDiscoveryMasterName+".RPC_UnRegServiceDiscover"
type OriginDiscoveryMaster struct { type OriginDiscoveryMaster struct {
service.Service service.Service
@@ -31,12 +30,12 @@ type OriginDiscoveryMaster struct {
type OriginDiscoveryClient struct { type OriginDiscoveryClient struct {
service.Service service.Service
funDelNode FunDelNode funDelNode FunDelNode
funSetNode FunSetNode funSetNode FunSetNode
localNodeId string localNodeId string
mapDiscovery map[string]map[string][]string //map[masterNodeId]map[nodeId]struct{} mapDiscovery map[string]map[string][]string //map[masterNodeId]map[nodeId]struct{}
bRetire bool bRetire bool
isRegisterOk bool isRegisterOk bool
} }
@@ -58,14 +57,14 @@ func (ds *OriginDiscoveryMaster) isRegNode(nodeId string) bool {
} }
func (ds *OriginDiscoveryMaster) updateNodeInfo(nInfo *rpc.NodeInfo) { func (ds *OriginDiscoveryMaster) updateNodeInfo(nInfo *rpc.NodeInfo) {
if _,ok:= ds.mapNodeInfo[nInfo.NodeId];ok == false { if _, ok := ds.mapNodeInfo[nInfo.NodeId]; ok == false {
return return
} }
nodeInfo := proto.Clone(nInfo).(*rpc.NodeInfo) nodeInfo := proto.Clone(nInfo).(*rpc.NodeInfo)
for i:=0;i<len(ds.nodeInfo);i++ { for i := 0; i < len(ds.nodeInfo); i++ {
if ds.nodeInfo[i].NodeId == nodeInfo.NodeId { if ds.nodeInfo[i].NodeId == nodeInfo.NodeId {
ds.nodeInfo[i] = nodeInfo ds.nodeInfo[i] = nodeInfo
break break
} }
} }
@@ -87,19 +86,19 @@ func (ds *OriginDiscoveryMaster) addNodeInfo(nInfo *rpc.NodeInfo) {
} }
func (ds *OriginDiscoveryMaster) removeNodeInfo(nodeId string) { func (ds *OriginDiscoveryMaster) removeNodeInfo(nodeId string) {
if _,ok:= ds.mapNodeInfo[nodeId];ok == false { if _, ok := ds.mapNodeInfo[nodeId]; ok == false {
return return
} }
for i:=0;i<len(ds.nodeInfo);i++ { for i := 0; i < len(ds.nodeInfo); i++ {
if ds.nodeInfo[i].NodeId == nodeId { if ds.nodeInfo[i].NodeId == nodeId {
ds.nodeInfo = append(ds.nodeInfo[:i],ds.nodeInfo[i+1:]...) ds.nodeInfo = append(ds.nodeInfo[:i], ds.nodeInfo[i+1:]...)
break break
} }
} }
ds.nsTTL.removeNode(nodeId) ds.nsTTL.removeNode(nodeId)
delete(ds.mapNodeInfo,nodeId) delete(ds.mapNodeInfo, nodeId)
} }
func (ds *OriginDiscoveryMaster) OnInit() error { func (ds *OriginDiscoveryMaster) OnInit() error {
@@ -107,26 +106,26 @@ func (ds *OriginDiscoveryMaster) OnInit() error {
ds.RegNodeConnListener(ds) ds.RegNodeConnListener(ds)
ds.RegNatsConnListener(ds) ds.RegNatsConnListener(ds)
ds.nsTTL.init(time.Duration(cluster.GetOriginDiscovery().TTLSecond)*time.Second) ds.nsTTL.init(time.Duration(cluster.GetOriginDiscovery().TTLSecond) * time.Second)
return nil return nil
} }
func (ds *OriginDiscoveryMaster) checkTTL(){ func (ds *OriginDiscoveryMaster) checkTTL() {
if cluster.IsNatsMode() == false { if cluster.IsNatsMode() == false {
return return
} }
interval := time.Duration(cluster.GetOriginDiscovery().TTLSecond)*time.Second interval := time.Duration(cluster.GetOriginDiscovery().TTLSecond) * time.Second
interval = interval /3 /2 interval = interval / 3 / 2
if interval < time.Second { if interval < time.Second {
interval = time.Second interval = time.Second
} }
ds.NewTicker(interval,func(t *timer.Ticker){ ds.NewTicker(interval, func(t *timer.Ticker) {
ds.nsTTL.checkTTL(func(nodeIdList []string) { ds.nsTTL.checkTTL(func(nodeIdList []string) {
for _,nodeId := range nodeIdList { for _, nodeId := range nodeIdList {
log.Info("TTL expiry",log.String("nodeId",nodeId)) log.Info("TTL expiry", log.String("nodeId", nodeId))
ds.OnNodeDisconnect(nodeId) ds.OnNodeDisconnect(nodeId)
} }
}) })
@@ -147,19 +146,25 @@ func (ds *OriginDiscoveryMaster) OnStart() {
ds.checkTTL() ds.checkTTL()
} }
func (dc *OriginDiscoveryMaster) OnNatsConnected(){ func (ds *OriginDiscoveryMaster) OnNatsConnected() {
//向所有的节点同步服务发现信息 //向所有的节点同步服务发现信息
var notifyDiscover rpc.SubscribeDiscoverNotify var notifyDiscover rpc.SubscribeDiscoverNotify
notifyDiscover.IsFull = true notifyDiscover.IsFull = true
notifyDiscover.NodeInfo = dc.nodeInfo notifyDiscover.NodeInfo = ds.nodeInfo
notifyDiscover.MasterNodeId = cluster.GetLocalNodeInfo().NodeId notifyDiscover.MasterNodeId = cluster.GetLocalNodeInfo().NodeId
dc.RpcCastGo(SubServiceDiscover, &notifyDiscover) ds.RpcCastGo(SubServiceDiscover, &notifyDiscover)
} }
func (dc *OriginDiscoveryMaster) OnNatsDisconnect(){ func (ds *OriginDiscoveryMaster) OnNatsDisconnect() {
} }
func (ds *OriginDiscoveryMaster) OnNodeConnected(nodeId string) { func (ds *OriginDiscoveryMaster) OnNodeConnected(nodeId string) {
var notifyDiscover rpc.SubscribeDiscoverNotify
notifyDiscover.IsFull = true
notifyDiscover.NodeInfo = ds.nodeInfo
notifyDiscover.MasterNodeId = cluster.GetLocalNodeInfo().NodeId
ds.GoNode(nodeId, SubServiceDiscover, &notifyDiscover)
} }
func (ds *OriginDiscoveryMaster) OnNodeDisconnect(nodeId string) { func (ds *OriginDiscoveryMaster) OnNodeDisconnect(nodeId string) {
@@ -182,7 +187,7 @@ func (ds *OriginDiscoveryMaster) OnNodeDisconnect(nodeId string) {
} }
func (ds *OriginDiscoveryMaster) RpcCastGo(serviceMethod string, args interface{}) { func (ds *OriginDiscoveryMaster) RpcCastGo(serviceMethod string, args interface{}) {
for nodeId, _ := range ds.mapNodeInfo { for nodeId := range ds.mapNodeInfo {
if nodeId == cluster.GetLocalNodeInfo().NodeId { if nodeId == cluster.GetLocalNodeInfo().NodeId {
continue continue
} }
@@ -192,7 +197,7 @@ func (ds *OriginDiscoveryMaster) RpcCastGo(serviceMethod string, args interface{
} }
func (ds *OriginDiscoveryMaster) RPC_Ping(req *rpc.Ping, res *rpc.Pong) error { func (ds *OriginDiscoveryMaster) RPC_Ping(req *rpc.Ping, res *rpc.Pong) error {
if ds.isRegNode(req.NodeId) == false{ if ds.isRegNode(req.NodeId) == false {
res.Ok = false res.Ok = false
return nil return nil
} }
@@ -202,8 +207,8 @@ func (ds *OriginDiscoveryMaster) RPC_Ping(req *rpc.Ping, res *rpc.Pong) error {
return nil return nil
} }
func (ds *OriginDiscoveryMaster) RPC_NodeRetire(req *rpc.NodeRetireReq, res *rpc.Empty) error { func (ds *OriginDiscoveryMaster) RPC_NodeRetire(req *rpc.NodeRetireReq, _ *rpc.Empty) error {
log.Info("node is retire",log.String("nodeId",req.NodeInfo.NodeId),log.Bool("retire",req.NodeInfo.Retire)) log.Info("node is retire", log.String("nodeId", req.NodeInfo.NodeId), log.Bool("retire", req.NodeInfo.Retire))
ds.updateNodeInfo(req.NodeInfo) ds.updateNodeInfo(req.NodeInfo)
@@ -253,15 +258,14 @@ func (ds *OriginDiscoveryMaster) RPC_RegServiceDiscover(req *rpc.RegServiceDisco
//加入到本地Cluster模块中将连接该结点 //加入到本地Cluster模块中将连接该结点
cluster.serviceDiscoverySetNodeInfo(&nodeInfo) cluster.serviceDiscoverySetNodeInfo(&nodeInfo)
res.IsFull = true res.IsFull = true
res.NodeInfo = ds.nodeInfo res.NodeInfo = ds.nodeInfo
res.MasterNodeId = cluster.GetLocalNodeInfo().NodeId res.MasterNodeId = cluster.GetLocalNodeInfo().NodeId
return nil return nil
} }
func (ds *OriginDiscoveryMaster) RPC_UnRegServiceDiscover(req *rpc.UnRegServiceDiscoverReq, res *rpc.Empty) error { func (ds *OriginDiscoveryMaster) RPC_UnRegServiceDiscover(req *rpc.UnRegServiceDiscoverReq, _ *rpc.Empty) error {
log.Debug("RPC_UnRegServiceDiscover",log.String("nodeId",req.NodeId)) log.Debug("RPC_UnRegServiceDiscover", log.String("nodeId", req.NodeId))
ds.OnNodeDisconnect(req.NodeId) ds.OnNodeDisconnect(req.NodeId)
return nil return nil
} }
@@ -276,7 +280,7 @@ func (dc *OriginDiscoveryClient) OnInit() error {
return nil return nil
} }
func (dc *OriginDiscoveryClient) addMasterNode(masterNodeId string, nodeId string,serviceList []string) { func (dc *OriginDiscoveryClient) addMasterNode(masterNodeId string, nodeId string, serviceList []string) {
_, ok := dc.mapDiscovery[masterNodeId] _, ok := dc.mapDiscovery[masterNodeId]
if ok == false { if ok == false {
dc.mapDiscovery[masterNodeId] = map[string][]string{} dc.mapDiscovery[masterNodeId] = map[string][]string{}
@@ -284,7 +288,7 @@ func (dc *OriginDiscoveryClient) addMasterNode(masterNodeId string, nodeId strin
dc.mapDiscovery[masterNodeId][nodeId] = serviceList dc.mapDiscovery[masterNodeId][nodeId] = serviceList
} }
func (dc *OriginDiscoveryClient) getNodePublicService(masterNodeId string,nodeId string) []string{ func (dc *OriginDiscoveryClient) getNodePublicService(masterNodeId string, nodeId string) []string {
mapNodeId, ok := dc.mapDiscovery[masterNodeId] mapNodeId, ok := dc.mapDiscovery[masterNodeId]
if ok == false { if ok == false {
return nil return nil
@@ -314,28 +318,28 @@ func (dc *OriginDiscoveryClient) findNodeId(nodeId string) bool {
return false return false
} }
func (dc *OriginDiscoveryClient) ping(){ func (dc *OriginDiscoveryClient) ping() {
interval := time.Duration(cluster.GetOriginDiscovery().TTLSecond)*time.Second interval := time.Duration(cluster.GetOriginDiscovery().TTLSecond) * time.Second
interval = interval /3 interval = interval / 3
if interval < time.Second { if interval < time.Second {
interval = time.Second interval = time.Second
} }
dc.NewTicker(interval,func(t *timer.Ticker){ dc.NewTicker(interval, func(t *timer.Ticker) {
if cluster.IsNatsMode() == false || dc.isRegisterOk == false{ if cluster.IsNatsMode() == false || dc.isRegisterOk == false {
return return
} }
var ping rpc.Ping var ping rpc.Ping
ping.NodeId = cluster.GetLocalNodeInfo().NodeId ping.NodeId = cluster.GetLocalNodeInfo().NodeId
masterNodes := GetCluster().GetOriginDiscovery().MasterNodeList masterNodes := GetCluster().GetOriginDiscovery().MasterNodeList
for i:=0;i<len(masterNodes);i++ { for i := 0; i < len(masterNodes); i++ {
if masterNodes[i].NodeId == cluster.GetLocalNodeInfo().NodeId { if masterNodes[i].NodeId == cluster.GetLocalNodeInfo().NodeId {
continue continue
} }
masterNodeId := masterNodes[i].NodeId masterNodeId := masterNodes[i].NodeId
dc.AsyncCallNodeWithTimeout(3*time.Second,masterNodeId,RpcPingMethod,&ping, func(empty *rpc.Pong,err error) { dc.AsyncCallNodeWithTimeout(3*time.Second, masterNodeId, RpcPingMethod, &ping, func(empty *rpc.Pong, err error) {
if err == nil && empty.Ok == false{ if err == nil && empty.Ok == false {
//断开master重 //断开master重
dc.regServiceDiscover(masterNodeId) dc.regServiceDiscover(masterNodeId)
} }
@@ -344,7 +348,6 @@ func (dc *OriginDiscoveryClient) ping(){
}) })
} }
func (dc *OriginDiscoveryClient) OnStart() { func (dc *OriginDiscoveryClient) OnStart() {
//2.添加并连接发现主结点 //2.添加并连接发现主结点
dc.addDiscoveryMaster() dc.addDiscoveryMaster()
@@ -375,8 +378,8 @@ func (dc *OriginDiscoveryClient) fullCompareDiffNode(masterNodeId string, mapNod
} }
//本地任何Master都不存在的放到diffNodeIdSlice //本地任何Master都不存在的放到diffNodeIdSlice
for nodeId, _ := range mapNodeId { for nodeId := range mapNodeId {
_, ok := mapNodeInfo[nodeId] _, ok = mapNodeInfo[nodeId]
if ok == false { if ok == false {
diffNodeIdSlice = append(diffNodeIdSlice, nodeId) diffNodeIdSlice = append(diffNodeIdSlice, nodeId)
} }
@@ -385,7 +388,7 @@ func (dc *OriginDiscoveryClient) fullCompareDiffNode(masterNodeId string, mapNod
return diffNodeIdSlice return diffNodeIdSlice
} }
//订阅发现的服务通知 // RPC_SubServiceDiscover 订阅发现的服务通知
func (dc *OriginDiscoveryClient) RPC_SubServiceDiscover(req *rpc.SubscribeDiscoverNotify) error { func (dc *OriginDiscoveryClient) RPC_SubServiceDiscover(req *rpc.SubscribeDiscoverNotify) error {
mapNodeInfo := map[string]*rpc.NodeInfo{} mapNodeInfo := map[string]*rpc.NodeInfo{}
for _, nodeInfo := range req.NodeInfo { for _, nodeInfo := range req.NodeInfo {
@@ -439,8 +442,8 @@ func (dc *OriginDiscoveryClient) RPC_SubServiceDiscover(req *rpc.SubscribeDiscov
//设置新结点 //设置新结点
for _, nodeInfo := range mapNodeInfo { for _, nodeInfo := range mapNodeInfo {
dc.addMasterNode(req.MasterNodeId, nodeInfo.NodeId,nodeInfo.PublicServiceList) dc.addMasterNode(req.MasterNodeId, nodeInfo.NodeId, nodeInfo.PublicServiceList)
bSet := dc.setNodeInfo(req.MasterNodeId,nodeInfo) bSet := dc.setNodeInfo(req.MasterNodeId, nodeInfo)
if bSet == false { if bSet == false {
continue continue
} }
@@ -453,7 +456,7 @@ func (dc *OriginDiscoveryClient) OnNodeConnected(nodeId string) {
dc.regServiceDiscover(nodeId) dc.regServiceDiscover(nodeId)
} }
func (dc *OriginDiscoveryClient) OnRelease(){ func (dc *OriginDiscoveryClient) OnRelease() {
log.Debug("OriginDiscoveryClient") log.Debug("OriginDiscoveryClient")
//取消注册 //取消注册
@@ -461,47 +464,47 @@ func (dc *OriginDiscoveryClient) OnRelease(){
nodeRetireReq.NodeId = cluster.GetLocalNodeInfo().NodeId nodeRetireReq.NodeId = cluster.GetLocalNodeInfo().NodeId
masterNodeList := cluster.GetOriginDiscovery() masterNodeList := cluster.GetOriginDiscovery()
for i:=0;i<len(masterNodeList.MasterNodeList);i++{ for i := 0; i < len(masterNodeList.MasterNodeList); i++ {
if masterNodeList.MasterNodeList[i].NodeId == cluster.GetLocalNodeInfo().NodeId { if masterNodeList.MasterNodeList[i].NodeId == cluster.GetLocalNodeInfo().NodeId {
continue continue
} }
err := dc.CallNodeWithTimeout(3*time.Second,masterNodeList.MasterNodeList[i].NodeId,UnRegServiceDiscover,&nodeRetireReq,&rpc.Empty{}) err := dc.CallNodeWithTimeout(3*time.Second, masterNodeList.MasterNodeList[i].NodeId, UnRegServiceDiscover, &nodeRetireReq, &rpc.Empty{})
if err!= nil { if err != nil {
log.Error("call "+UnRegServiceDiscover+" is fail",log.ErrorAttr("err",err)) log.Error("call "+UnRegServiceDiscover+" is fail", log.ErrorField("err", err))
} }
} }
} }
func (dc *OriginDiscoveryClient) OnRetire(){ func (dc *OriginDiscoveryClient) OnRetire() {
dc.bRetire = true dc.bRetire = true
masterNodeList := cluster.GetOriginDiscovery() masterNodeList := cluster.GetOriginDiscovery()
for i:=0;i<len(masterNodeList.MasterNodeList);i++{ for i := 0; i < len(masterNodeList.MasterNodeList); i++ {
var nodeRetireReq rpc.NodeRetireReq var nodeRetireReq rpc.NodeRetireReq
nodeRetireReq.NodeInfo = &rpc.NodeInfo{} nodeRetireReq.NodeInfo = &rpc.NodeInfo{}
nodeRetireReq.NodeInfo.NodeId = cluster.localNodeInfo.NodeId nodeRetireReq.NodeInfo.NodeId = cluster.localNodeInfo.NodeId
nodeRetireReq.NodeInfo.ListenAddr = cluster.localNodeInfo.ListenAddr nodeRetireReq.NodeInfo.ListenAddr = cluster.localNodeInfo.ListenAddr
nodeRetireReq.NodeInfo.MaxRpcParamLen = cluster.localNodeInfo.MaxRpcParamLen nodeRetireReq.NodeInfo.MaxRpcParamLen = cluster.localNodeInfo.MaxRpcParamLen
nodeRetireReq.NodeInfo.PublicServiceList = cluster.localNodeInfo.PublicServiceList nodeRetireReq.NodeInfo.PublicServiceList = cluster.localNodeInfo.PublicServiceList
nodeRetireReq.NodeInfo.Retire = dc.bRetire nodeRetireReq.NodeInfo.Retire = dc.bRetire
nodeRetireReq.NodeInfo.Private = cluster.localNodeInfo.Private nodeRetireReq.NodeInfo.Private = cluster.localNodeInfo.Private
err := dc.GoNode(masterNodeList.MasterNodeList[i].NodeId,NodeRetireRpcMethod,&nodeRetireReq) err := dc.GoNode(masterNodeList.MasterNodeList[i].NodeId, NodeRetireRpcMethod, &nodeRetireReq)
if err!= nil { if err != nil {
log.Error("call "+NodeRetireRpcMethod+" is fail",log.ErrorAttr("err",err)) log.Error("call "+NodeRetireRpcMethod+" is fail", log.ErrorField("err", err))
} }
} }
} }
func (dc *OriginDiscoveryClient) tryRegServiceDiscover(nodeId string){ func (dc *OriginDiscoveryClient) tryRegServiceDiscover(nodeId string) {
dc.AfterFunc(time.Second*3, func(timer *timer.Timer) { dc.AfterFunc(time.Second*3, func(timer *timer.Timer) {
dc.regServiceDiscover(nodeId) dc.regServiceDiscover(nodeId)
}) })
} }
func (dc *OriginDiscoveryClient) regServiceDiscover(nodeId string){ func (dc *OriginDiscoveryClient) regServiceDiscover(nodeId string) {
if nodeId == cluster.GetLocalNodeInfo().NodeId { if nodeId == cluster.GetLocalNodeInfo().NodeId {
return return
} }
@@ -515,14 +518,14 @@ func (dc *OriginDiscoveryClient) regServiceDiscover(nodeId string){
req.NodeInfo.NodeId = cluster.localNodeInfo.NodeId req.NodeInfo.NodeId = cluster.localNodeInfo.NodeId
req.NodeInfo.ListenAddr = cluster.localNodeInfo.ListenAddr req.NodeInfo.ListenAddr = cluster.localNodeInfo.ListenAddr
req.NodeInfo.MaxRpcParamLen = cluster.localNodeInfo.MaxRpcParamLen req.NodeInfo.MaxRpcParamLen = cluster.localNodeInfo.MaxRpcParamLen
req.NodeInfo.PublicServiceList = cluster.localNodeInfo.PublicServiceList req.NodeInfo.PublicServiceList = cluster.localNodeInfo.PublicServiceList
req.NodeInfo.Retire = dc.bRetire req.NodeInfo.Retire = dc.bRetire
req.NodeInfo.Private = cluster.localNodeInfo.Private req.NodeInfo.Private = cluster.localNodeInfo.Private
log.Debug("regServiceDiscover",log.String("nodeId",nodeId)) log.Debug("regServiceDiscover", log.String("nodeId", nodeId))
//向Master服务同步本Node服务信息 //向Master服务同步本Node服务信息
_,err := dc.AsyncCallNodeWithTimeout(3*time.Second,nodeId, RegServiceDiscover, &req, func(res *rpc.SubscribeDiscoverNotify, err error) { _, err := dc.AsyncCallNodeWithTimeout(3*time.Second, nodeId, RegServiceDiscover, &req, func(res *rpc.SubscribeDiscoverNotify, err error) {
if err != nil { if err != nil {
log.Error("call "+RegServiceDiscover+" is fail :"+ err.Error()) log.Error("call " + RegServiceDiscover + " is fail :" + err.Error())
dc.tryRegServiceDiscover(nodeId) dc.tryRegServiceDiscover(nodeId)
return return
} }
@@ -532,12 +535,12 @@ func (dc *OriginDiscoveryClient) regServiceDiscover(nodeId string){
}) })
if err != nil { if err != nil {
log.Error("call "+ RegServiceDiscover+" is fail :"+ err.Error()) log.Error("call " + RegServiceDiscover + " is fail :" + err.Error())
dc.tryRegServiceDiscover(nodeId) dc.tryRegServiceDiscover(nodeId)
} }
} }
func (dc *OriginDiscoveryClient) setNodeInfo(masterNodeId string,nodeInfo *rpc.NodeInfo) bool{ func (dc *OriginDiscoveryClient) setNodeInfo(masterNodeId string, nodeInfo *rpc.NodeInfo) bool {
if nodeInfo == nil || nodeInfo.Private == true || nodeInfo.NodeId == dc.localNodeId { if nodeInfo == nil || nodeInfo.Private == true || nodeInfo.NodeId == dc.localNodeId {
return false return false
} }
@@ -545,8 +548,8 @@ func (dc *OriginDiscoveryClient) setNodeInfo(masterNodeId string,nodeInfo *rpc.N
//筛选关注的服务 //筛选关注的服务
var discoverServiceSlice = make([]string, 0, 24) var discoverServiceSlice = make([]string, 0, 24)
for _, pubService := range nodeInfo.PublicServiceList { for _, pubService := range nodeInfo.PublicServiceList {
if cluster.CanDiscoveryService(masterNodeId,pubService) == true { if cluster.CanDiscoveryService(masterNodeId, pubService) == true {
discoverServiceSlice = append(discoverServiceSlice,pubService) discoverServiceSlice = append(discoverServiceSlice, pubService)
} }
} }
@@ -598,8 +601,8 @@ func (cls *Cluster) checkOriginDiscovery(localNodeId string) (bool, bool) {
} }
func (cls *Cluster) AddDiscoveryService(serviceName string, bPublicService bool) { func (cls *Cluster) AddDiscoveryService(serviceName string, bPublicService bool) {
addServiceList := append([]string{},serviceName) addServiceList := append([]string{}, serviceName)
cls.localNodeInfo.ServiceList = append(addServiceList,cls.localNodeInfo.ServiceList...) cls.localNodeInfo.ServiceList = append(addServiceList, cls.localNodeInfo.ServiceList...)
if bPublicService { if bPublicService {
cls.localNodeInfo.PublicServiceList = append(cls.localNodeInfo.PublicServiceList, serviceName) cls.localNodeInfo.PublicServiceList = append(cls.localNodeInfo.PublicServiceList, serviceName)
} }
@@ -610,7 +613,6 @@ func (cls *Cluster) AddDiscoveryService(serviceName string, bPublicService bool)
cls.mapServiceNode[serviceName][cls.localNodeInfo.NodeId] = struct{}{} cls.mapServiceNode[serviceName][cls.localNodeInfo.NodeId] = struct{}{}
} }
func (cls *Cluster) IsOriginMasterDiscoveryNode(nodeId string) bool { func (cls *Cluster) IsOriginMasterDiscoveryNode(nodeId string) bool {
return cls.getOriginMasterDiscoveryNodeInfo(nodeId) != nil return cls.getOriginMasterDiscoveryNodeInfo(nodeId) != nil
} }
@@ -629,12 +631,12 @@ func (cls *Cluster) getOriginMasterDiscoveryNodeInfo(nodeId string) *NodeInfo {
return nil return nil
} }
func (dc *OriginDiscoveryClient) OnNatsConnected(){ func (dc *OriginDiscoveryClient) OnNatsConnected() {
masterNodes := GetCluster().GetOriginDiscovery().MasterNodeList masterNodes := GetCluster().GetOriginDiscovery().MasterNodeList
for i:=0;i<len(masterNodes);i++ { for i := 0; i < len(masterNodes); i++ {
dc.regServiceDiscover(masterNodes[i].NodeId) dc.regServiceDiscover(masterNodes[i].NodeId)
} }
} }
func (dc *OriginDiscoveryClient) OnNatsDisconnect(){ func (dc *OriginDiscoveryClient) OnNatsDisconnect() {
} }

View File

@@ -1,33 +1,41 @@
package cluster package cluster
import ( import (
"errors"
"fmt" "fmt"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/rpc" "github.com/duanhf2012/origin/v2/rpc"
jsoniter "github.com/json-iterator/go" jsoniter "github.com/json-iterator/go"
"gopkg.in/yaml.v3"
"io/fs"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"time" "time"
"errors"
) )
var json = jsoniter.ConfigCompatibleWithStandardLibrary var json = jsoniter.ConfigCompatibleWithStandardLibrary
type EtcdList struct { type EtcdList struct {
NetworkName []string NetworkName []string
Endpoints []string Endpoints []string
UserName string
Password string
Cert string
CertKey string
Ca string
} }
type EtcdDiscovery struct { type EtcdDiscovery struct {
DialTimeoutMillisecond time.Duration DialTimeoutMillisecond time.Duration
TTLSecond int64 TTLSecond int64
EtcdList []EtcdList EtcdList []EtcdList
} }
type OriginDiscovery struct { type OriginDiscovery struct {
TTLSecond int64 TTLSecond int64
MasterNodeList []NodeInfo MasterNodeList []NodeInfo
} }
@@ -35,40 +43,71 @@ type DiscoveryType int
const ( const (
InvalidType = 0 InvalidType = 0
OriginType = 1 OriginType = 1
EtcdType = 2 EtcdType = 2
) )
const MinTTL = 3 const MinTTL = 3
type DiscoveryInfo struct { type DiscoveryInfo struct {
discoveryType DiscoveryType discoveryType DiscoveryType
Etcd *EtcdDiscovery //etcd Etcd *EtcdDiscovery //etcd
Origin *OriginDiscovery //orign Origin *OriginDiscovery //origin
} }
type NatsConfig struct { type NatsConfig struct {
NatsUrl string NatsUrl string
NoRandomize bool NoRandomize bool
} }
type RpcMode struct { type RpcMode struct {
Typ string `json:"Type"` Typ string `json:"Type"`
Nats NatsConfig Nats NatsConfig
} }
type NodeInfoList struct { type NodeInfoList struct {
RpcMode RpcMode RpcMode RpcMode
Discovery DiscoveryInfo Discovery DiscoveryInfo
NodeList []NodeInfo NodeList []NodeInfo
} }
func (d *DiscoveryInfo) getDiscoveryType() DiscoveryType{ func validConfigFile(f string) bool {
return strings.HasSuffix(f, ".json")|| strings.HasSuffix(f, ".yml") || strings.HasSuffix(f, ".yaml")
}
func yamlToJson(data []byte, v interface{}) ([]byte, error) {
mapKeyData := map[string]interface{}{}
err := yaml.Unmarshal(data, &mapKeyData)
if err != nil {
return nil, err
}
data, err = json.Marshal(mapKeyData)
if err != nil {
return nil, err
}
return data, nil
}
func unmarshalConfig(data []byte, v interface{}) error {
envData := []byte(os.ExpandEnv(string(data)))
if !json.Valid(envData) {
var err error
envData, err = yamlToJson(envData, v)
if err != nil {
return err
}
}
return json.Unmarshal(envData, v)
}
func (d *DiscoveryInfo) getDiscoveryType() DiscoveryType {
return d.discoveryType return d.discoveryType
} }
func (d *DiscoveryInfo) setDiscovery(discoveryInfo *DiscoveryInfo) error{ func (d *DiscoveryInfo) setDiscovery(discoveryInfo *DiscoveryInfo) error {
var err error var err error
err = d.setOrigin(discoveryInfo.Origin) err = d.setOrigin(discoveryInfo.Origin)
if err != nil { if err != nil {
@@ -83,30 +122,30 @@ func (d *DiscoveryInfo) setDiscovery(discoveryInfo *DiscoveryInfo) error{
return nil return nil
} }
func (d *DiscoveryInfo) setEtcd(etcd *EtcdDiscovery) error{ func (d *DiscoveryInfo) setEtcd(etcd *EtcdDiscovery) error {
if etcd == nil { if etcd == nil {
return nil return nil
} }
if d.discoveryType != InvalidType { if d.discoveryType != InvalidType {
return fmt.Errorf("Repeat configuration of Discovery") return fmt.Errorf("repeat configuration of Discovery")
} }
//Endpoints不允许重复 //Endpoints不允许重复
mapAddr:=make (map[string]struct{}) mapAddr := make(map[string]struct{})
for _, n := range etcd.EtcdList { for _, n := range etcd.EtcdList {
for _,endPoint := range n.Endpoints { for _, endPoint := range n.Endpoints {
if _,ok:=mapAddr[endPoint];ok == true { if _, ok := mapAddr[endPoint]; ok == true {
return fmt.Errorf("etcd discovery config Etcd.EtcdList.Endpoints %+v is repeat",endPoint) return fmt.Errorf("etcd discovery config Etcd.EtcdList.Endpoints %+v is repeat", endPoint)
} }
mapAddr[endPoint] = struct{}{} mapAddr[endPoint] = struct{}{}
} }
//networkName不允许重复 //networkName不允许重复
mapNetworkName := make(map[string]struct{}) mapNetworkName := make(map[string]struct{})
for _,netName := range n.NetworkName{ for _, netName := range n.NetworkName {
if _,ok := mapNetworkName[netName];ok == true { if _, ok := mapNetworkName[netName]; ok == true {
return fmt.Errorf("etcd discovery config Etcd.EtcdList.NetworkName %+v is repeat",n.NetworkName) return fmt.Errorf("etcd discovery config Etcd.EtcdList.NetworkName %+v is repeat", n.NetworkName)
} }
mapNetworkName[netName] = struct{}{} mapNetworkName[netName] = struct{}{}
@@ -124,13 +163,13 @@ func (d *DiscoveryInfo) setEtcd(etcd *EtcdDiscovery) error{
return nil return nil
} }
func (d *DiscoveryInfo) setOrigin(originDiscovery *OriginDiscovery) error{ func (d *DiscoveryInfo) setOrigin(originDiscovery *OriginDiscovery) error {
if originDiscovery== nil || len(originDiscovery.MasterNodeList)==0 { if originDiscovery == nil || len(originDiscovery.MasterNodeList) == 0 {
return nil return nil
} }
if d.discoveryType != InvalidType { if d.discoveryType != InvalidType {
return fmt.Errorf("Repeat configuration of Discovery") return fmt.Errorf("repeat configuration of Discovery")
} }
mapListenAddr := make(map[string]struct{}) mapListenAddr := make(map[string]struct{})
@@ -161,7 +200,7 @@ func (cls *Cluster) ReadClusterConfig(filepath string) (*NodeInfoList, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = json.Unmarshal(d, c) err = unmarshalConfig(d, c)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -176,7 +215,7 @@ func (cls *Cluster) readServiceConfig(filepath string) (interface{}, map[string]
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
err = json.Unmarshal(d, &c) err = unmarshalConfig(d, &c)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
@@ -204,7 +243,7 @@ func (cls *Cluster) readServiceConfig(filepath string) (interface{}, map[string]
return GlobalCfg, serviceConfig, mapNodeService, nil return GlobalCfg, serviceConfig, mapNodeService, nil
} }
func (cls *Cluster) SetRpcMode(cfgRpcMode *RpcMode,rpcMode *RpcMode) error { func (cls *Cluster) SetRpcMode(cfgRpcMode *RpcMode, rpcMode *RpcMode) error {
//忽略掉没有设置的配置 //忽略掉没有设置的配置
if cfgRpcMode.Typ == "" { if cfgRpcMode.Typ == "" {
return nil return nil
@@ -212,16 +251,16 @@ func (cls *Cluster) SetRpcMode(cfgRpcMode *RpcMode,rpcMode *RpcMode) error {
//不允许重复的配置Rpc模式 //不允许重复的配置Rpc模式
if cfgRpcMode.Typ != "" && rpcMode.Typ != ""{ if cfgRpcMode.Typ != "" && rpcMode.Typ != "" {
return errors.New("repeat config RpcMode") return errors.New("repeat config RpcMode")
} }
//检查Typ是否合法 //检查Typ是否合法
if cfgRpcMode.Typ!="Nats" && cfgRpcMode.Typ!="Default" { if cfgRpcMode.Typ != "Nats" && cfgRpcMode.Typ != "Default" {
return fmt.Errorf("RpcMode %s is not support", rpcMode.Typ) return fmt.Errorf("RpcMode %s is not support", rpcMode.Typ)
} }
if cfgRpcMode.Typ == "Nats" && len(cfgRpcMode.Nats.NatsUrl)==0 { if cfgRpcMode.Typ == "Nats" && len(cfgRpcMode.Nats.NatsUrl) == 0 {
return fmt.Errorf("nats rpc mode config NatsUrl is empty") return fmt.Errorf("nats rpc mode config NatsUrl is empty")
} }
@@ -230,50 +269,58 @@ func (cls *Cluster) SetRpcMode(cfgRpcMode *RpcMode,rpcMode *RpcMode) error {
return nil return nil
} }
func (cls *Cluster) readLocalClusterConfig(nodeId string) (DiscoveryInfo, []NodeInfo,RpcMode, error) { func (cls *Cluster) readLocalClusterConfig(nodeId string) (DiscoveryInfo, []NodeInfo, RpcMode, error) {
var nodeInfoList []NodeInfo var nodeInfoList []NodeInfo
var discoveryInfo DiscoveryInfo var discoveryInfo DiscoveryInfo
var rpcMode RpcMode var rpcMode RpcMode
clusterCfgPath := strings.TrimRight(configDir, "/") + "/cluster"
fileInfoList, err := os.ReadDir(clusterCfgPath)
if err != nil {
return discoveryInfo, nil,rpcMode, fmt.Errorf("Read dir %s is fail :%+v", clusterCfgPath, err)
}
//读取任何文件,只读符合格式的配置,目录下的文件可以自定义分文件 //读取任何文件,只读符合格式的配置,目录下的文件可以自定义分文件
for _, f := range fileInfoList { err := filepath.Walk(configDir, func(path string, info fs.FileInfo, err error)error {
if f.IsDir() == false { if info.IsDir() {
filePath := strings.TrimRight(strings.TrimRight(clusterCfgPath, "/"), "\\") + "/" + f.Name() return nil
fileNodeInfoList, rerr := cls.ReadClusterConfig(filePath) }
if rerr != nil { if err != nil {
return discoveryInfo, nil,rpcMode, fmt.Errorf("read file path %s is error:%+v", filePath, rerr) return err
} }
err = cls.SetRpcMode(&fileNodeInfoList.RpcMode,&rpcMode) if !validConfigFile(info.Name()) {
if err != nil { return nil
return discoveryInfo, nil,rpcMode, err }
}
err = discoveryInfo.setDiscovery(&fileNodeInfoList.Discovery) fileNodeInfoList, rErr := cls.ReadClusterConfig(path)
if err != nil { if rErr != nil {
return discoveryInfo,nil,rpcMode,err return fmt.Errorf("read file path %s is error:%+v", path, rErr)
} }
for _, nodeInfo := range fileNodeInfoList.NodeList { err = cls.SetRpcMode(&fileNodeInfoList.RpcMode, &rpcMode)
if nodeInfo.NodeId == nodeId || nodeId == rpc.NodeIdNull { if err != nil {
nodeInfoList = append(nodeInfoList, nodeInfo) return err
} }
err = discoveryInfo.setDiscovery(&fileNodeInfoList.Discovery)
if err != nil {
return err
}
for _, nodeInfo := range fileNodeInfoList.NodeList {
if nodeInfo.NodeId == nodeId || nodeId == rpc.NodeIdNull {
nodeInfoList = append(nodeInfoList, nodeInfo)
} }
} }
return nil
})
if err != nil {
return discoveryInfo, nil, rpcMode, err
} }
if nodeId != rpc.NodeIdNull && (len(nodeInfoList) != 1) { if nodeId != rpc.NodeIdNull && (len(nodeInfoList) != 1) {
return discoveryInfo, nil,rpcMode, fmt.Errorf("%d configurations were found for the configuration with node ID %d!", len(nodeInfoList), nodeId) return discoveryInfo, nil, rpcMode, fmt.Errorf("nodeid %s configuration error in NodeList", nodeId)
} }
for i, _ := range nodeInfoList { for i := range nodeInfoList {
for j, s := range nodeInfoList[i].ServiceList { for j, s := range nodeInfoList[i].ServiceList {
//私有结点不加入到Public服务列表中 //私有结点不加入到Public服务列表中
if strings.HasPrefix(s, "_") == false && nodeInfoList[i].Private == false { if strings.HasPrefix(s, "_") == false && nodeInfoList[i].Private == false {
@@ -284,40 +331,36 @@ func (cls *Cluster) readLocalClusterConfig(nodeId string) (DiscoveryInfo, []Node
} }
} }
return discoveryInfo, nodeInfoList, rpcMode,nil return discoveryInfo, nodeInfoList, rpcMode, nil
} }
func (cls *Cluster) readLocalService(localNodeId string) error { func (cls *Cluster) readLocalService(localNodeId string) error {
clusterCfgPath := strings.TrimRight(configDir, "/") + "/cluster" var globalCfg interface{}
fileInfoList, err := os.ReadDir(clusterCfgPath)
if err != nil {
return fmt.Errorf("Read dir %s is fail :%+v", clusterCfgPath, err)
}
var globalCfg interface{}
publicService := map[string]interface{}{} publicService := map[string]interface{}{}
nodeService := map[string]interface{}{} nodeService := map[string]interface{}{}
//读取任何文件,只读符合格式的配置,目录下的文件可以自定义分文件 //读取任何文件,只读符合格式的配置,目录下的文件可以自定义分文件
for _, f := range fileInfoList { err := filepath.Walk(configDir, func(path string, info fs.FileInfo, err error)error{
if f.IsDir() == true { if info.IsDir() {
continue return nil
} }
if filepath.Ext(f.Name())!= ".json" {
continue
}
filePath := strings.TrimRight(strings.TrimRight(clusterCfgPath, "/"), "\\") + "/" + f.Name()
currGlobalCfg, serviceConfig, mapNodeService, err := cls.readServiceConfig(filePath)
if err != nil { if err != nil {
continue return err
}
if !validConfigFile(info.Name()) {
return nil
}
currGlobalCfg, serviceConfig, mapNodeService, err := cls.readServiceConfig(path)
if err != nil {
return err
} }
if currGlobalCfg != nil { if currGlobalCfg != nil {
//不允许重复的配置global配置 //不允许重复的配置global配置
if globalCfg != nil { if globalCfg != nil {
return fmt.Errorf("[Global] does not allow repeated configuration in %s.",f.Name()) return fmt.Errorf("[Global] does not allow repeated configuration in %s", info.Name())
} }
globalCfg = currGlobalCfg globalCfg = currGlobalCfg
} }
@@ -325,17 +368,21 @@ func (cls *Cluster) readLocalService(localNodeId string) error {
//保存公共配置 //保存公共配置
for _, s := range cls.localNodeInfo.ServiceList { for _, s := range cls.localNodeInfo.ServiceList {
for { for {
splitServiceName := strings.Split(s, ":")
if len(splitServiceName) == 2 {
s = splitServiceName[0]
}
//取公共服务配置 //取公共服务配置
pubCfg, ok := serviceConfig[s] pubCfg, ok := serviceConfig[s]
if ok == true { if ok == true {
if _,publicOk := publicService[s];publicOk == true { if _, publicOk := publicService[s]; publicOk == true {
return fmt.Errorf("public service [%s] does not allow repeated configuration in %s.",s,f.Name()) return fmt.Errorf("public service [%s] does not allow repeated configuration in %s", s, info.Name())
} }
publicService[s] = pubCfg publicService[s] = pubCfg
} }
//取指定结点配置的服务 //取指定结点配置的服务
nodeServiceCfg,ok := mapNodeService[localNodeId] nodeServiceCfg, ok := mapNodeService[localNodeId]
if ok == false { if ok == false {
break break
} }
@@ -344,30 +391,40 @@ func (cls *Cluster) readLocalService(localNodeId string) error {
break break
} }
if _,nodeOK := nodeService[s];nodeOK == true { if _, nodeOK := nodeService[s]; nodeOK == true {
return fmt.Errorf("NodeService NodeId[%d] Service[%s] does not allow repeated configuration in %s.",cls.localNodeInfo.NodeId,s,f.Name()) return fmt.Errorf("NodeService NodeId[%s] Service[%s] does not allow repeated configuration in %s", cls.localNodeInfo.NodeId, s, info.Name())
} }
nodeService[s] = nodeCfg nodeService[s] = nodeCfg
break break
} }
} }
return nil
})
if err != nil {
return err
} }
//组合所有的配置 //组合所有的配置
for _, s := range cls.localNodeInfo.ServiceList { for _, s := range cls.localNodeInfo.ServiceList {
splitServiceName := strings.Split(s, ":")
if len(splitServiceName) == 2 {
s = splitServiceName[0]
}
//先从NodeService中找 //先从NodeService中找
var serviceCfg interface{} var serviceCfg interface{}
var ok bool var ok bool
serviceCfg,ok = nodeService[s] serviceCfg, ok = nodeService[s]
if ok == true { if ok == true {
cls.localServiceCfg[s] =serviceCfg cls.localServiceCfg[s] = serviceCfg
continue continue
} }
//如果找不到从PublicService中找 //如果找不到从PublicService中找
serviceCfg,ok = publicService[s] serviceCfg, ok = publicService[s]
if ok == true { if ok == true {
cls.localServiceCfg[s] =serviceCfg cls.localServiceCfg[s] = serviceCfg
} }
} }
cls.globalCfg = globalCfg cls.globalCfg = globalCfg
@@ -375,20 +432,35 @@ func (cls *Cluster) readLocalService(localNodeId string) error {
return nil return nil
} }
func (cls *Cluster) parseLocalCfg() { func (cls *Cluster) parseLocalCfg() error{
rpcInfo := NodeRpcInfo{} rpcInfo := NodeRpcInfo{}
rpcInfo.nodeInfo = cls.localNodeInfo rpcInfo.nodeInfo = cls.localNodeInfo
rpcInfo.client = rpc.NewLClient(rpcInfo.nodeInfo.NodeId,&cls.callSet) rpcInfo.client = rpc.NewLClient(rpcInfo.nodeInfo.NodeId, &cls.callSet)
cls.mapRpc[cls.localNodeInfo.NodeId] = &rpcInfo cls.mapRpc[cls.localNodeInfo.NodeId] = &rpcInfo
for _, serviceName := range cls.localNodeInfo.ServiceList {
for _, sName := range cls.localNodeInfo.ServiceList { splitServiceName := strings.Split(serviceName, ":")
if _, ok := cls.mapServiceNode[sName]; ok == false { if len(splitServiceName) == 2 {
cls.mapServiceNode[sName] = make(map[string]struct{}) serviceName = splitServiceName[0]
templateServiceName := splitServiceName[1]
//记录模板
if _, ok := cls.mapTemplateServiceNode[templateServiceName]; ok == false {
cls.mapTemplateServiceNode[templateServiceName] = map[string]struct{}{}
}
cls.mapTemplateServiceNode[templateServiceName][serviceName] = struct{}{}
} }
cls.mapServiceNode[sName][cls.localNodeInfo.NodeId] = struct{}{} if _, ok := cls.mapServiceNode[serviceName]; ok == false {
cls.mapServiceNode[serviceName] = make(map[string]struct{})
}
if _,ok:=cls.mapServiceNode[serviceName][cls.localNodeInfo.NodeId];ok {
return fmt.Errorf("duplicate service %s is configured in node %s", serviceName, cls.localNodeInfo.NodeId)
}
cls.mapServiceNode[serviceName][cls.localNodeInfo.NodeId] = struct{}{}
} }
return nil
} }
func (cls *Cluster) IsNatsMode() bool { func (cls *Cluster) IsNatsMode() bool {
@@ -403,9 +475,10 @@ func (cls *Cluster) InitCfg(localNodeId string) error {
cls.localServiceCfg = map[string]interface{}{} cls.localServiceCfg = map[string]interface{}{}
cls.mapRpc = map[string]*NodeRpcInfo{} cls.mapRpc = map[string]*NodeRpcInfo{}
cls.mapServiceNode = map[string]map[string]struct{}{} cls.mapServiceNode = map[string]map[string]struct{}{}
cls.mapTemplateServiceNode = map[string]map[string]struct{}{}
//加载本地结点的NodeList配置 //加载本地结点的NodeList配置
discoveryInfo, nodeInfoList,rpcMode, err := cls.readLocalClusterConfig(localNodeId) discoveryInfo, nodeInfoList, rpcMode, err := cls.readLocalClusterConfig(localNodeId)
if err != nil { if err != nil {
return err return err
} }
@@ -420,8 +493,7 @@ func (cls *Cluster) InitCfg(localNodeId string) error {
} }
//本地配置服务加到全局map信息中 //本地配置服务加到全局map信息中
cls.parseLocalCfg() return cls.parseLocalCfg()
return nil
} }
func (cls *Cluster) IsConfigService(serviceName string) bool { func (cls *Cluster) IsConfigService(serviceName string) bool {
@@ -436,15 +508,40 @@ func (cls *Cluster) IsConfigService(serviceName string) bool {
return ok return ok
} }
func (cls *Cluster) GetNodeIdByTemplateService(templateServiceName string, rpcClientList []*rpc.Client, filterRetire bool) (error, []*rpc.Client) {
cls.locker.RLock()
defer cls.locker.RUnlock()
func (cls *Cluster) GetNodeIdByService(serviceName string, rpcClientList []*rpc.Client, filterRetire bool) (error, int) { mapServiceName := cls.mapTemplateServiceNode[templateServiceName]
for serviceName := range mapServiceName {
mapNodeId, ok := cls.mapServiceNode[serviceName]
if ok == true {
for nodeId := range mapNodeId {
pClient, retire := GetCluster().getRpcClient(nodeId)
if pClient == nil || pClient.IsConnected() == false {
continue
}
//如果需要筛选掉退休的对retire状态的结点略过
if filterRetire == true && retire == true {
continue
}
rpcClientList = append(rpcClientList, pClient)
}
}
}
return nil, rpcClientList
}
func (cls *Cluster) GetNodeIdByService(serviceName string, rpcClientList []*rpc.Client, filterRetire bool) (error, []*rpc.Client) {
cls.locker.RLock() cls.locker.RLock()
defer cls.locker.RUnlock() defer cls.locker.RUnlock()
mapNodeId, ok := cls.mapServiceNode[serviceName] mapNodeId, ok := cls.mapServiceNode[serviceName]
count := 0
if ok == true { if ok == true {
for nodeId, _ := range mapNodeId { for nodeId := range mapNodeId {
pClient,retire := GetCluster().getRpcClient(nodeId) pClient, retire := GetCluster().getRpcClient(nodeId)
if pClient == nil || pClient.IsConnected() == false { if pClient == nil || pClient.IsConnected() == false {
continue continue
} }
@@ -454,15 +551,11 @@ func (cls *Cluster) GetNodeIdByService(serviceName string, rpcClientList []*rpc.
continue continue
} }
rpcClientList[count] = pClient rpcClientList = append(rpcClientList, pClient)
count++
if count >= cap(rpcClientList) {
break
}
} }
} }
return nil, count return nil, rpcClientList
} }
func (cls *Cluster) GetServiceCfg(serviceName string) interface{} { func (cls *Cluster) GetServiceCfg(serviceName string) interface{} {

View File

@@ -22,10 +22,12 @@ type Concurrent struct {
tasks chan task tasks chan task
cbChannel chan func(error) cbChannel chan func(error)
open int32 open int32
} }
/* /*
OpenConcurrentByNumCPU 函数使用说明
cpuMul 表示cpu的倍数 cpuMul 表示cpu的倍数
建议:(1)cpu密集型 使用1 (2)i/o密集型使用2或者更高 建议:(1)cpu密集型 使用1 (2)i/o密集型使用2或者更高
*/ */
@@ -35,10 +37,10 @@ func (c *Concurrent) OpenConcurrentByNumCPU(cpuNumMul float32) {
} }
func (c *Concurrent) OpenConcurrent(minGoroutineNum int32, maxGoroutineNum int32, maxTaskChannelNum int) { func (c *Concurrent) OpenConcurrent(minGoroutineNum int32, maxGoroutineNum int32, maxTaskChannelNum int) {
if atomic.AddInt32(&c.open,1) > 1 { if atomic.AddInt32(&c.open, 1) > 1 {
panic("repeated calls to OpenConcurrent are not allowed!") panic("repeated calls to OpenConcurrent are not allowed!")
} }
c.tasks = make(chan task, maxTaskChannelNum) c.tasks = make(chan task, maxTaskChannelNum)
c.cbChannel = make(chan func(error), maxTaskChannelNum) c.cbChannel = make(chan func(error), maxTaskChannelNum)
@@ -56,7 +58,7 @@ func (c *Concurrent) AsyncDoByQueue(queueId int64, fn func() bool, cb func(err e
} }
if fn == nil && cb == nil { if fn == nil && cb == nil {
log.Stack("fn and cb is nil") log.StackError("fn and cb is nil")
return return
} }
@@ -66,7 +68,7 @@ func (c *Concurrent) AsyncDoByQueue(queueId int64, fn func() bool, cb func(err e
} }
if queueId != 0 { if queueId != 0 {
queueId = queueId % maxTaskQueueSessionId+1 queueId = queueId%maxTaskQueueSessionId + 1
} }
select { select {

View File

@@ -6,13 +6,15 @@ import (
"time" "time"
"fmt" "fmt"
"runtime"
"context"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/util/queue" "github.com/duanhf2012/origin/v2/util/queue"
) )
var idleTimeout = int64(2 * time.Second) var idleTimeout = int64(2 * time.Second)
const maxTaskQueueSessionId = 10000 const maxTaskQueueSessionId = 10000
type dispatch struct { type dispatch struct {
@@ -30,6 +32,9 @@ type dispatch struct {
waitWorker sync.WaitGroup waitWorker sync.WaitGroup
waitDispatch sync.WaitGroup waitDispatch sync.WaitGroup
cancelContext context.Context
cancel context.CancelFunc
} }
func (d *dispatch) open(minGoroutineNum int32, maxGoroutineNum int32, tasks chan task, cbChannel chan func(error)) { func (d *dispatch) open(minGoroutineNum int32, maxGoroutineNum int32, tasks chan task, cbChannel chan func(error)) {
@@ -40,7 +45,7 @@ func (d *dispatch) open(minGoroutineNum int32, maxGoroutineNum int32, tasks chan
d.workerQueue = make(chan task) d.workerQueue = make(chan task)
d.cbChannel = cbChannel d.cbChannel = cbChannel
d.queueIdChannel = make(chan int64, cap(tasks)) d.queueIdChannel = make(chan int64, cap(tasks))
d.cancelContext, d.cancel = context.WithCancel(context.Background())
d.waitDispatch.Add(1) d.waitDispatch.Add(1)
go d.run() go d.run()
} }
@@ -52,7 +57,7 @@ func (d *dispatch) run() {
for { for {
select { select {
case queueId := <-d.queueIdChannel: case queueId := <-d.queueIdChannel:
d.processqueueEvent(queueId) d.processQueueEvent(queueId)
default: default:
select { select {
case t, ok := <-d.tasks: case t, ok := <-d.tasks:
@@ -61,13 +66,15 @@ func (d *dispatch) run() {
} }
d.processTask(&t) d.processTask(&t)
case queueId := <-d.queueIdChannel: case queueId := <-d.queueIdChannel:
d.processqueueEvent(queueId) d.processQueueEvent(queueId)
case <-timeout.C: case <-timeout.C:
d.processTimer() d.processTimer()
if atomic.LoadInt32(&d.minConcurrentNum) == -1 && len(d.tasks) == 0 { case <-d.cancelContext.Done():
atomic.StoreInt64(&idleTimeout,int64(time.Millisecond * 10)) atomic.StoreInt64(&idleTimeout, int64(time.Millisecond*5))
}
timeout.Reset(time.Duration(atomic.LoadInt64(&idleTimeout))) timeout.Reset(time.Duration(atomic.LoadInt64(&idleTimeout)))
for i := int32(0); i < d.workerNum; i++ {
d.processIdle()
}
} }
} }
@@ -87,7 +94,7 @@ func (d *dispatch) processTimer() {
d.idle = true d.idle = true
} }
func (d *dispatch) processqueueEvent(queueId int64) { func (d *dispatch) processQueueEvent(queueId int64) {
d.idle = false d.idle = false
queueSession := d.mapTaskQueueSession[queueId] queueSession := d.mapTaskQueueSession[queueId]
@@ -155,17 +162,18 @@ func (d *dispatch) pushQueueTaskFinishEvent(queueId int64) {
d.queueIdChannel <- queueId d.queueIdChannel <- queueId
} }
func (c *dispatch) pushAsyncDoCallbackEvent(cb func(err error)) { func (d *dispatch) pushAsyncDoCallbackEvent(cb func(err error)) {
if cb == nil { if cb == nil {
//不需要回调的情况 //不需要回调的情况
return return
} }
c.cbChannel <- cb d.cbChannel <- cb
} }
func (d *dispatch) close() { func (d *dispatch) close() {
atomic.StoreInt32(&d.minConcurrentNum, -1) atomic.StoreInt32(&d.minConcurrentNum, -1)
d.cancel()
breakFor: breakFor:
for { for {
@@ -184,10 +192,7 @@ breakFor:
func (d *dispatch) DoCallback(cb func(err error)) { func (d *dispatch) DoCallback(cb func(err error)) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096) log.StackError(fmt.Sprint(r))
l := runtime.Stack(buf, false)
errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString))
} }
}() }()

View File

@@ -5,7 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"runtime"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
) )
@@ -51,24 +51,22 @@ func (w *worker) run(waitGroup *sync.WaitGroup, t task) {
func (w *worker) exec(t *task) { func (w *worker) exec(t *task) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096)
l := runtime.Stack(buf, false)
errString := fmt.Sprint(r) errString := fmt.Sprint(r)
cb := t.cb cb := t.cb
t.cb = func(err error) { t.cb = func(err error) {
cb(errors.New(errString)) cb(errors.New(errString))
} }
log.Dump(string(buf[:l]),log.String("error",errString)) log.StackError(errString)
w.endCallFun(true,t) w.endCallFun(true, t)
} }
}() }()
w.endCallFun(t.fn(),t) w.endCallFun(t.fn(), t)
} }
func (w *worker) endCallFun(isDocallBack bool,t *task) { func (w *worker) endCallFun(isDoCallBack bool, t *task) {
if isDocallBack { if isDoCallBack {
w.pushAsyncDoCallbackEvent(t.cb) w.pushAsyncDoCallbackEvent(t.cb)
} }

View File

@@ -8,47 +8,47 @@ import (
type valueType int type valueType int
type CommandFunctionCB func(args interface{}) error type CommandFunctionCB func(args interface{}) error
var commandList []*command var commandList []*command
var programName string var programName string
const(
boolType valueType = 0 const (
boolType valueType = 0
stringType valueType = 1 stringType valueType = 1
intType valueType = 2 intType valueType = 2
) )
type command struct{ type command struct {
valType valueType valType valueType
name string name string
bValue bool bValue bool
strValue string strValue string
intValue int intValue int
usage string usage string
fn CommandFunctionCB fn CommandFunctionCB
} }
func (cmd *command) execute() error{ func (cmd *command) execute() error {
if cmd.valType == boolType { if cmd.valType == boolType {
return cmd.fn(cmd.bValue) return cmd.fn(cmd.bValue)
}else if cmd.valType == stringType { } else if cmd.valType == stringType {
return cmd.fn(cmd.strValue) return cmd.fn(cmd.strValue)
}else if cmd.valType == intType { } else if cmd.valType == intType {
return cmd.fn(cmd.intValue) return cmd.fn(cmd.intValue)
}else{
return fmt.Errorf("Unknow command type.")
} }
return nil return fmt.Errorf("unknow command type")
} }
func Run(args []string) error { func Run(args []string) error {
flag.Parse() flag.Parse()
programName = args[0] programName = args[0]
if flag.NFlag() <= 0 { if flag.NFlag() <= 0 {
return fmt.Errorf("Command input parameter error,try `%s -help` for help",args[0]) return fmt.Errorf("Command input parameter error,try `%s -help` for help", args[0])
} }
var startCmd *command var startCmd *command
for _,val := range commandList { for _, val := range commandList {
if val.name == "start" { if val.name == "start" {
startCmd = val startCmd = val
continue continue
@@ -63,50 +63,50 @@ func Run(args []string) error {
return startCmd.execute() return startCmd.execute()
} }
return fmt.Errorf("Command input parameter error,try `%s -help` for help",args[0]) return fmt.Errorf("Command input parameter error,try `%s -help` for help", args[0])
} }
func RegisterCommandBool(cmdName string, defaultValue bool, usage string,fn CommandFunctionCB){ func RegisterCommandBool(cmdName string, defaultValue bool, usage string, fn CommandFunctionCB) {
var cmd command var cmd command
cmd.valType = boolType cmd.valType = boolType
cmd.name = cmdName cmd.name = cmdName
cmd.fn = fn cmd.fn = fn
cmd.usage = usage cmd.usage = usage
flag.BoolVar(&cmd.bValue, cmdName, defaultValue, usage) flag.BoolVar(&cmd.bValue, cmdName, defaultValue, usage)
commandList = append(commandList,&cmd) commandList = append(commandList, &cmd)
} }
func RegisterCommandInt(cmdName string, defaultValue int, usage string,fn CommandFunctionCB){ func RegisterCommandInt(cmdName string, defaultValue int, usage string, fn CommandFunctionCB) {
var cmd command var cmd command
cmd.valType = intType cmd.valType = intType
cmd.name = cmdName cmd.name = cmdName
cmd.fn = fn cmd.fn = fn
cmd.usage = usage cmd.usage = usage
flag.IntVar(&cmd.intValue, cmdName, defaultValue, usage) flag.IntVar(&cmd.intValue, cmdName, defaultValue, usage)
commandList = append(commandList,&cmd) commandList = append(commandList, &cmd)
} }
func RegisterCommandString(cmdName string, defaultValue string, usage string,fn CommandFunctionCB){ func RegisterCommandString(cmdName string, defaultValue string, usage string, fn CommandFunctionCB) {
var cmd command var cmd command
cmd.valType = stringType cmd.valType = stringType
cmd.name = cmdName cmd.name = cmdName
cmd.fn = fn cmd.fn = fn
cmd.usage = usage cmd.usage = usage
flag.StringVar(&cmd.strValue, cmdName, defaultValue, usage) flag.StringVar(&cmd.strValue, cmdName, defaultValue, usage)
commandList = append(commandList,&cmd) commandList = append(commandList, &cmd)
} }
func PrintDefaults(){ func PrintDefaults() {
fmt.Fprintf(os.Stderr, "Options:\n") fmt.Fprintf(os.Stderr, "Options:\n")
for _,val := range commandList { for _, val := range commandList {
fmt.Fprintf(os.Stderr, " -%-10s%10s\n",val.name,val.usage) fmt.Fprintf(os.Stderr, " -%-10s%10s\n", val.name, val.usage)
} }
} }
func GetParamStringVal(paramName string) string{ func GetParamStringVal(paramName string) string {
for _,cmd := range commandList { for _, cmd := range commandList {
if cmd.name == paramName{ if cmd.name == paramName {
return cmd.strValue return cmd.strValue
} }
} }
@@ -114,11 +114,11 @@ func GetParamStringVal(paramName string) string{
} }
func GetParamBoolVal(paramName string) bool { func GetParamBoolVal(paramName string) bool {
for _,cmd := range commandList { for _, cmd := range commandList {
if cmd.name == paramName{ if cmd.name == paramName {
return cmd.bValue return cmd.bValue
} }
} }
return false return false
} }

View File

@@ -3,11 +3,10 @@ package event
import ( import (
"fmt" "fmt"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"runtime"
"sync" "sync"
) )
//事件接受器 // EventCallBack 事件接受器
type EventCallBack func(event IEvent) type EventCallBack func(event IEvent)
type IEvent interface { type IEvent interface {
@@ -17,10 +16,14 @@ type IEvent interface {
type Event struct { type Event struct {
Type EventType Type EventType
Data interface{} Data interface{}
ref bool IntExt [2]int64
StringExt [2]string
AnyExt [2]any
ref bool
} }
var emptyEvent Event var emptyEvent Event
func (e *Event) Reset() { func (e *Event) Reset() {
*e = emptyEvent *e = emptyEvent
} }
@@ -37,18 +40,18 @@ func (e *Event) UnRef() {
e.ref = false e.ref = false
} }
func (e *Event) GetEventType() EventType{ func (e *Event) GetEventType() EventType {
return e.Type return e.Type
} }
type IEventHandler interface { type IEventHandler interface {
Init(processor IEventProcessor) Init(processor IEventProcessor)
GetEventProcessor() IEventProcessor //获得事件 GetEventProcessor() IEventProcessor //获得事件
NotifyEvent(IEvent) NotifyEvent(IEvent)
Destroy() Destroy()
//注册了事件 //注册了事件
addRegInfo(eventType EventType,eventProcessor IEventProcessor) addRegInfo(eventType EventType, eventProcessor IEventProcessor)
removeRegInfo(eventType EventType,eventProcessor IEventProcessor) removeRegInfo(eventType EventType, eventProcessor IEventProcessor)
} }
type IEventChannel interface { type IEventChannel interface {
@@ -60,11 +63,11 @@ type IEventProcessor interface {
Init(eventChannel IEventChannel) Init(eventChannel IEventChannel)
EventHandler(ev IEvent) EventHandler(ev IEvent)
RegEventReceiverFunc(eventType EventType, receiver IEventHandler,callback EventCallBack) RegEventReceiverFunc(eventType EventType, receiver IEventHandler, callback EventCallBack)
UnRegEventReceiverFun(eventType EventType, receiver IEventHandler) UnRegEventReceiverFun(eventType EventType, receiver IEventHandler)
castEvent(event IEvent) //广播事件 castEvent(event IEvent) //广播事件
addBindEvent(eventType EventType, receiver IEventHandler,callback EventCallBack) addBindEvent(eventType EventType, receiver IEventHandler, callback EventCallBack)
addListen(eventType EventType, receiver IEventHandler) addListen(eventType EventType, receiver IEventHandler)
removeBindEvent(eventType EventType, receiver IEventHandler) removeBindEvent(eventType EventType, receiver IEventHandler)
removeListen(eventType EventType, receiver IEventHandler) removeListen(eventType EventType, receiver IEventHandler)
@@ -75,116 +78,115 @@ type EventHandler struct {
eventProcessor IEventProcessor eventProcessor IEventProcessor
//已经注册的事件 //已经注册的事件
locker sync.RWMutex locker sync.RWMutex
mapRegEvent map[EventType]map[IEventProcessor]interface{} //向其他事件处理器监听的事件类型 mapRegEvent map[EventType]map[IEventProcessor]interface{} //向其他事件处理器监听的事件类型
} }
type EventProcessor struct { type EventProcessor struct {
IEventChannel IEventChannel
locker sync.RWMutex locker sync.RWMutex
mapListenerEvent map[EventType]map[IEventProcessor]int //监听者信息 mapListenerEvent map[EventType]map[IEventProcessor]int //监听者信息
mapBindHandlerEvent map[EventType]map[IEventHandler]EventCallBack//收到事件处理 mapBindHandlerEvent map[EventType]map[IEventHandler]EventCallBack //收到事件处理
} }
func NewEventHandler() IEventHandler{ func NewEventHandler() IEventHandler {
eh := EventHandler{} eh := EventHandler{}
eh.mapRegEvent = map[EventType]map[IEventProcessor]interface{}{} eh.mapRegEvent = map[EventType]map[IEventProcessor]interface{}{}
return &eh return &eh
} }
func NewEventProcessor() IEventProcessor{ func NewEventProcessor() IEventProcessor {
ep := EventProcessor{} ep := EventProcessor{}
ep.mapListenerEvent = map[EventType]map[IEventProcessor]int{} ep.mapListenerEvent = map[EventType]map[IEventProcessor]int{}
ep.mapBindHandlerEvent = map[EventType]map[IEventHandler]EventCallBack{} ep.mapBindHandlerEvent = map[EventType]map[IEventHandler]EventCallBack{}
return &ep return &ep
} }
func (handler *EventHandler) addRegInfo(eventType EventType,eventProcessor IEventProcessor){ func (handler *EventHandler) addRegInfo(eventType EventType, eventProcessor IEventProcessor) {
handler.locker.Lock() handler.locker.Lock()
defer handler.locker.Unlock() defer handler.locker.Unlock()
if handler.mapRegEvent == nil { if handler.mapRegEvent == nil {
handler.mapRegEvent = map[EventType]map[IEventProcessor]interface{}{} handler.mapRegEvent = map[EventType]map[IEventProcessor]interface{}{}
} }
if _,ok := handler.mapRegEvent[eventType] ;ok == false{ if _, ok := handler.mapRegEvent[eventType]; ok == false {
handler.mapRegEvent[eventType] = map[IEventProcessor]interface{}{} handler.mapRegEvent[eventType] = map[IEventProcessor]interface{}{}
} }
handler.mapRegEvent[eventType][eventProcessor] = nil handler.mapRegEvent[eventType][eventProcessor] = nil
} }
func (handler *EventHandler) removeRegInfo(eventType EventType,eventProcessor IEventProcessor){ func (handler *EventHandler) removeRegInfo(eventType EventType, eventProcessor IEventProcessor) {
if _,ok := handler.mapRegEvent[eventType];ok == true { if _, ok := handler.mapRegEvent[eventType]; ok == true {
delete(handler.mapRegEvent[eventType],eventProcessor) delete(handler.mapRegEvent[eventType], eventProcessor)
} }
} }
func (handler *EventHandler) GetEventProcessor() IEventProcessor{ func (handler *EventHandler) GetEventProcessor() IEventProcessor {
return handler.eventProcessor return handler.eventProcessor
} }
func (handler *EventHandler) NotifyEvent(ev IEvent){ func (handler *EventHandler) NotifyEvent(ev IEvent) {
handler.GetEventProcessor().castEvent(ev) handler.GetEventProcessor().castEvent(ev)
} }
func (handler *EventHandler) Init(processor IEventProcessor){ func (handler *EventHandler) Init(processor IEventProcessor) {
handler.eventProcessor = processor handler.eventProcessor = processor
handler.mapRegEvent =map[EventType]map[IEventProcessor]interface{}{} handler.mapRegEvent = map[EventType]map[IEventProcessor]interface{}{}
} }
func (processor *EventProcessor) Init(eventChannel IEventChannel) {
func (processor *EventProcessor) Init(eventChannel IEventChannel){
processor.IEventChannel = eventChannel processor.IEventChannel = eventChannel
} }
func (processor *EventProcessor) addBindEvent(eventType EventType, receiver IEventHandler,callback EventCallBack){ func (processor *EventProcessor) addBindEvent(eventType EventType, receiver IEventHandler, callback EventCallBack) {
processor.locker.Lock() processor.locker.Lock()
defer processor.locker.Unlock() defer processor.locker.Unlock()
if _,ok := processor.mapBindHandlerEvent[eventType]; ok == false { if _, ok := processor.mapBindHandlerEvent[eventType]; ok == false {
processor.mapBindHandlerEvent[eventType] = map[IEventHandler]EventCallBack{} processor.mapBindHandlerEvent[eventType] = map[IEventHandler]EventCallBack{}
} }
processor.mapBindHandlerEvent[eventType][receiver] = callback processor.mapBindHandlerEvent[eventType][receiver] = callback
} }
func (processor *EventProcessor) addListen(eventType EventType, receiver IEventHandler){ func (processor *EventProcessor) addListen(eventType EventType, receiver IEventHandler) {
processor.locker.Lock() processor.locker.Lock()
defer processor.locker.Unlock() defer processor.locker.Unlock()
if _,ok := processor.mapListenerEvent[eventType];ok == false{ if _, ok := processor.mapListenerEvent[eventType]; ok == false {
processor.mapListenerEvent[eventType] = map[IEventProcessor]int{} processor.mapListenerEvent[eventType] = map[IEventProcessor]int{}
} }
processor.mapListenerEvent[eventType][receiver.GetEventProcessor()] += 1 processor.mapListenerEvent[eventType][receiver.GetEventProcessor()] += 1
} }
func (processor *EventProcessor) removeBindEvent(eventType EventType, receiver IEventHandler){ func (processor *EventProcessor) removeBindEvent(eventType EventType, receiver IEventHandler) {
processor.locker.Lock() processor.locker.Lock()
defer processor.locker.Unlock() defer processor.locker.Unlock()
if _,ok := processor.mapBindHandlerEvent[eventType];ok == true{ if _, ok := processor.mapBindHandlerEvent[eventType]; ok == true {
delete(processor.mapBindHandlerEvent[eventType], receiver) delete(processor.mapBindHandlerEvent[eventType], receiver)
} }
} }
func (processor *EventProcessor) removeListen(eventType EventType, receiver IEventHandler){ func (processor *EventProcessor) removeListen(eventType EventType, receiver IEventHandler) {
processor.locker.Lock() processor.locker.Lock()
defer processor.locker.Unlock() defer processor.locker.Unlock()
if _,ok := processor.mapListenerEvent[eventType];ok == true{ if _, ok := processor.mapListenerEvent[eventType]; ok == true {
processor.mapListenerEvent[eventType][receiver.GetEventProcessor()]-=1 processor.mapListenerEvent[eventType][receiver.GetEventProcessor()] -= 1
if processor.mapListenerEvent[eventType][receiver.GetEventProcessor()] <= 0 { if processor.mapListenerEvent[eventType][receiver.GetEventProcessor()] <= 0 {
delete(processor.mapListenerEvent[eventType], receiver.GetEventProcessor()) delete(processor.mapListenerEvent[eventType], receiver.GetEventProcessor())
} }
} }
} }
func (processor *EventProcessor) RegEventReceiverFunc(eventType EventType, receiver IEventHandler,callback EventCallBack){ func (processor *EventProcessor) RegEventReceiverFunc(eventType EventType, receiver IEventHandler, callback EventCallBack) {
//记录receiver自己注册过的事件 //记录receiver自己注册过的事件
receiver.addRegInfo(eventType, processor) receiver.addRegInfo(eventType, processor)
//记录当前所属IEventProcessor注册的回调 //记录当前所属IEventProcessor注册的回调
receiver.GetEventProcessor().addBindEvent(eventType, receiver,callback) receiver.GetEventProcessor().addBindEvent(eventType, receiver, callback)
//将注册加入到监听中 //将注册加入到监听中
processor.addListen(eventType, receiver) processor.addListen(eventType, receiver)
} }
@@ -195,10 +197,10 @@ func (processor *EventProcessor) UnRegEventReceiverFun(eventType EventType, rece
receiver.removeRegInfo(eventType, processor) receiver.removeRegInfo(eventType, processor)
} }
func (handler *EventHandler) Destroy(){ func (handler *EventHandler) Destroy() {
handler.locker.Lock() handler.locker.Lock()
defer handler.locker.Unlock() defer handler.locker.Unlock()
for eventTyp,mapEventProcess := range handler.mapRegEvent { for eventTyp, mapEventProcess := range handler.mapRegEvent {
if mapEventProcess == nil { if mapEventProcess == nil {
continue continue
} }
@@ -212,30 +214,27 @@ func (handler *EventHandler) Destroy(){
func (processor *EventProcessor) EventHandler(ev IEvent) { func (processor *EventProcessor) EventHandler(ev IEvent) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096) log.StackError(fmt.Sprint(r))
l := runtime.Stack(buf, false)
errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString))
} }
}() }()
mapCallBack,ok := processor.mapBindHandlerEvent[ev.GetEventType()] mapCallBack, ok := processor.mapBindHandlerEvent[ev.GetEventType()]
if ok == false { if ok == false {
return return
} }
for _,callback := range mapCallBack { for _, callback := range mapCallBack {
callback(ev) callback(ev)
} }
} }
func (processor *EventProcessor) castEvent(event IEvent){ func (processor *EventProcessor) castEvent(event IEvent) {
if processor.mapListenerEvent == nil { if processor.mapListenerEvent == nil {
log.Error("mapListenerEvent not init!") log.Error("mapListenerEvent not init!")
return return
} }
eventProcessor,ok := processor.mapListenerEvent[event.GetEventType()] eventProcessor, ok := processor.mapListenerEvent[event.GetEventType()]
if ok == false || processor == nil{ if ok == false || processor == nil {
return return
} }
@@ -243,4 +242,3 @@ func (processor *EventProcessor) castEvent(event IEvent){
proc.PushEvent(event) proc.PushEvent(event)
} }
} }

View File

@@ -2,22 +2,22 @@ package event
type EventType int type EventType int
//大于Sys_Event_User_Define给用户定义 // 大于Sys_Event_User_Define给用户定义
const ( const (
ServiceRpcRequestEvent EventType = -1 ServiceRpcRequestEvent EventType = -1
ServiceRpcResponseEvent EventType = -2 ServiceRpcResponseEvent EventType = -2
Sys_Event_Tcp EventType = -3 Sys_Event_Tcp EventType = -3
Sys_Event_Http_Event EventType = -4 Sys_Event_Http_Event EventType = -4
Sys_Event_WebSocket EventType = -5 Sys_Event_WebSocket EventType = -5
Sys_Event_Node_Conn_Event EventType = -6 Sys_Event_Kcp EventType = -6
Sys_Event_Nats_Conn_Event EventType = -7 Sys_Event_Node_Conn_Event EventType = -7
Sys_Event_DiscoverService EventType = -8 Sys_Event_Nats_Conn_Event EventType = -8
Sys_Event_DiscardGoroutine EventType = -9 Sys_Event_DiscoverService EventType = -9
Sys_Event_QueueTaskFinish EventType = -10 Sys_Event_Retire EventType = -10
Sys_Event_Retire EventType = -11 Sys_Event_EtcdDiscovery EventType = -11
Sys_Event_EtcdDiscovery EventType = -12 Sys_Event_Gin_Event EventType = -12
Sys_Event_FrameTick EventType = -13
Sys_Event_User_Define EventType = 1
Sys_Event_User_Define EventType = 1
) )

65
go.mod
View File

@@ -1,40 +1,80 @@
module github.com/duanhf2012/origin/v2 module github.com/duanhf2012/origin/v2
go 1.21 go 1.22
toolchain go1.22.7
require ( require (
github.com/IBM/sarama v1.43.3
github.com/gin-gonic/gin v1.10.0
github.com/go-sql-driver/mysql v1.6.0 github.com/go-sql-driver/mysql v1.6.0
github.com/gomodule/redigo v1.8.8 github.com/gomodule/redigo v1.8.8
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.0 github.com/gorilla/websocket v1.5.0
github.com/json-iterator/go v1.1.12 github.com/json-iterator/go v1.1.12
github.com/nats-io/nats.go v1.34.1 github.com/nats-io/nats.go v1.34.1
github.com/pierrec/lz4/v4 v4.1.18 github.com/pierrec/lz4/v4 v4.1.21
github.com/shirou/gopsutil v3.21.11+incompatible github.com/shirou/gopsutil v3.21.11+incompatible
github.com/xtaci/kcp-go/v5 v5.6.18
go.etcd.io/etcd/api/v3 v3.5.13 go.etcd.io/etcd/api/v3 v3.5.13
go.etcd.io/etcd/client/v3 v3.5.13 go.etcd.io/etcd/client/v3 v3.5.13
go.mongodb.org/mongo-driver v1.9.1 go.mongodb.org/mongo-driver v1.9.1
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
google.golang.org/protobuf v1.33.0 google.golang.org/protobuf v1.34.1
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1
) )
require ( require (
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/eapache/go-resiliency v1.7.0 // indirect
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect
github.com/eapache/queue v1.1.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/go-stack/stack v1.8.0 // indirect github.com/go-stack/stack v1.8.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.1 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/klauspost/compress v1.17.2 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
github.com/jcmturner/gofork v1.7.6 // indirect
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/klauspost/reedsolomon v1.12.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nkeys v0.4.7 // indirect
github.com/nats-io/nuid v1.0.1 // indirect github.com/nats-io/nuid v1.0.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/templexxx/cpu v0.1.1 // indirect
github.com/templexxx/xorsimd v0.4.3 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect
github.com/tklauser/go-sysconf v0.3.13 // indirect github.com/tklauser/go-sysconf v0.3.13 // indirect
github.com/tklauser/numcpus v0.7.0 // indirect github.com/tklauser/numcpus v0.7.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.0.2 // indirect github.com/xdg-go/scram v1.0.2 // indirect
github.com/xdg-go/stringprep v1.0.2 // indirect github.com/xdg-go/stringprep v1.0.2 // indirect
@@ -42,11 +82,12 @@ require (
github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.13 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.13 // indirect
go.uber.org/multierr v1.10.0 // indirect go.uber.org/multierr v1.10.0 // indirect
golang.org/x/crypto v0.18.0 // indirect golang.org/x/arch v0.8.0 // indirect
golang.org/x/net v0.17.0 // indirect golang.org/x/crypto v0.26.0 // indirect
golang.org/x/sync v0.3.0 // indirect golang.org/x/net v0.28.0 // indirect
golang.org/x/sys v0.16.0 // indirect golang.org/x/sync v0.8.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/sys v0.23.0 // indirect
golang.org/x/text v0.17.0 // indirect
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect

228
go.sum
View File

@@ -1,3 +1,18 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/IBM/sarama v1.43.3 h1:Yj6L2IaNvb2mRBop39N7mmJAHBVY3dTPncr3qGVkxPA=
github.com/IBM/sarama v1.43.3/go.mod h1:FVIRaLrhK3Cla/9FfRF5X9Zua2KpS3SYIXxhac1H+FQ=
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
@@ -5,44 +20,120 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/eapache/go-resiliency v1.7.0 h1:n3NRTnBn5N0Cbi/IeOHuQn9s2UwVUH7Ga0ZWcP+9JTA=
github.com/eapache/go-resiliency v1.7.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho=
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4ALJ04o5Qqpdz8XLIpNA3WM/iSIXqxtqo7UGVws=
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0=
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v1.8.8 h1:f6cXq6RRfiyrOJEV7p3JhLDlmawGBVBBP1MggY8Mo4E= github.com/gomodule/redigo v1.8.8 h1:f6cXq6RRfiyrOJEV7p3JhLDlmawGBVBBP1MggY8Mo4E=
github.com/gomodule/redigo v1.8.8/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE= github.com/gomodule/redigo v1.8.8/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=
github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8=
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/reedsolomon v1.12.0 h1:I5FEp3xSwVCcEh3F5A7dofEfhXdF/bWhQWPH+XwBFno=
github.com/klauspost/reedsolomon v1.12.0/go.mod h1:EPLZJeh4l27pUGC3aXOjheaoh1I9yut7xTURiW3LQ9Y=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
@@ -52,36 +143,66 @@ github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/templexxx/cpu v0.1.1 h1:isxHaxBXpYFWnk2DReuKkigaZyrjs2+9ypIdGP4h+HI=
github.com/templexxx/cpu v0.1.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
github.com/templexxx/xorsimd v0.4.3 h1:9AQTFHd7Bhk3dIT7Al2XeBX5DWOvsUPZCuhyAtNbHjU=
github.com/templexxx/xorsimd v0.4.3/go.mod h1:oZQcD6RFDisW2Am58dSAGwwL6rHjbzrlu25VDqfWkQg=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4= github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w= github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc= github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc=
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
github.com/xtaci/kcp-go/v5 v5.6.18 h1:7oV4mc272pcnn39/13BB11Bx7hJM4ogMIEokJYVWn4g=
github.com/xtaci/kcp-go/v5 v5.6.18/go.mod h1:75S1AKYYzNUSXIv30h+jPKJYZUwqpfvLshu63nCNSOM=
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.etcd.io/etcd/api/v3 v3.5.13 h1:8WXU2/NBge6AUF1K1gOexB6e07NgsN1hXK0rSTtgSp4= go.etcd.io/etcd/api/v3 v3.5.13 h1:8WXU2/NBge6AUF1K1gOexB6e07NgsN1hXK0rSTtgSp4=
@@ -98,65 +219,126 @@ go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY=
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q=
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@@ -1,96 +0,0 @@
package log // import "go.uber.org/zap/buffer"
import (
"strconv"
)
const _size = 9216
type Buffer struct {
bs []byte
//mu sync.Mutex // ensures atomic writes; protects the following fields
}
func (buff *Buffer) Init(){
buff.bs = make([]byte,_size)
}
// AppendByte writes a single byte to the Buffer.
func (b *Buffer) AppendByte(v byte) {
b.bs = append(b.bs, v)
}
func (b *Buffer) AppendBytes(v []byte) {
b.bs = append(b.bs, v...)
}
// AppendString writes a string to the Buffer.
func (b *Buffer) AppendString(s string) {
b.bs = append(b.bs, s...)
}
// AppendInt appends an integer to the underlying buffer (assuming base 10).
func (b *Buffer) AppendInt(i int64) {
b.bs = strconv.AppendInt(b.bs, i, 10)
}
// AppendUint appends an unsigned integer to the underlying buffer (assuming
// base 10).
func (b *Buffer) AppendUint(i uint64) {
b.bs = strconv.AppendUint(b.bs, i, 10)
}
// AppendBool appends a bool to the underlying buffer.
func (b *Buffer) AppendBool(v bool) {
b.bs = strconv.AppendBool(b.bs, v)
}
// AppendFloat appends a float to the underlying buffer. It doesn't quote NaN
// or +/- Inf.
func (b *Buffer) AppendFloat(f float64, bitSize int) {
b.bs = strconv.AppendFloat(b.bs, f, 'f', -1, bitSize)
}
// Len returns the length of the underlying byte slice.
func (b *Buffer) Len() int {
return len(b.bs)
}
// Cap returns the capacity of the underlying byte slice.
func (b *Buffer) Cap() int {
return cap(b.bs)
}
// Bytes returns a mutable reference to the underlying byte slice.
func (b *Buffer) Bytes() []byte {
return b.bs
}
// String returns a string copy of the underlying byte slice.
func (b *Buffer) String() string {
return string(b.bs)
}
// Reset resets the underlying byte slice. Subsequent writes re-use the slice's
// backing array.
func (b *Buffer) Reset() {
b.bs = b.bs[:0]
}
// Write implements io.Writer.
func (b *Buffer) Write(bs []byte) (int, error) {
b.bs = append(b.bs, bs...)
return len(bs), nil
}
// TrimNewline trims any final "\n" byte from the end of the buffer.
func (b *Buffer) TrimNewline() {
if i := len(b.bs) - 1; i >= 0 {
if b.bs[i] == '\n' {
b.bs = b.bs[:i]
}
}
}

View File

@@ -1,147 +0,0 @@
package log
import (
"context"
"io"
"log/slog"
"path/filepath"
"runtime"
"runtime/debug"
"sync"
)
type IOriginHandler interface {
slog.Handler
Lock()
UnLock()
}
type BaseHandler struct {
addSource bool
w io.Writer
locker sync.Mutex
}
type OriginTextHandler struct {
BaseHandler
*slog.TextHandler
}
type OriginJsonHandler struct {
BaseHandler
*slog.JSONHandler
}
func getStrLevel(level slog.Level) string{
switch level {
case LevelTrace:
return "Trace"
case LevelDebug:
return "Debug"
case LevelInfo:
return "Info"
case LevelWarning:
return "Warning"
case LevelError:
return "Error"
case LevelStack:
return "Stack"
case LevelDump:
return "Dump"
case LevelFatal:
return "Fatal"
}
return ""
}
func defaultReplaceAttr(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.LevelKey {
level := a.Value.Any().(slog.Level)
a.Value = slog.StringValue(getStrLevel(level))
}else if a.Key == slog.TimeKey && len(groups) == 0 {
a.Value = slog.StringValue(a.Value.Time().Format("2006/01/02 15:04:05"))
}else if a.Key == slog.SourceKey {
source := a.Value.Any().(*slog.Source)
source.File = filepath.Base(source.File)
}
return a
}
func NewOriginTextHandler(level slog.Level,w io.Writer,addSource bool,replaceAttr func([]string,slog.Attr) slog.Attr) slog.Handler{
var textHandler OriginTextHandler
textHandler.addSource = addSource
textHandler.w = w
textHandler.TextHandler = slog.NewTextHandler(w,&slog.HandlerOptions{
AddSource: addSource,
Level: level,
ReplaceAttr: replaceAttr,
})
return &textHandler
}
func (oh *OriginTextHandler) Handle(context context.Context, record slog.Record) error{
oh.Fill(context,&record)
oh.locker.Lock()
defer oh.locker.Unlock()
if record.Level == LevelStack || record.Level == LevelFatal{
err := oh.TextHandler.Handle(context, record)
oh.logStack(&record)
return err
}else if record.Level == LevelDump {
strDump := record.Message
record.Message = "dump info"
err := oh.TextHandler.Handle(context, record)
oh.w.Write([]byte(strDump))
return err
}
return oh.TextHandler.Handle(context, record)
}
func (b *BaseHandler) logStack(record *slog.Record){
b.w.Write(debug.Stack())
}
func (b *BaseHandler) Lock(){
b.locker.Lock()
}
func (b *BaseHandler) UnLock(){
b.locker.Unlock()
}
func NewOriginJsonHandler(level slog.Level,w io.Writer,addSource bool,replaceAttr func([]string,slog.Attr) slog.Attr) slog.Handler{
var jsonHandler OriginJsonHandler
jsonHandler.addSource = addSource
jsonHandler.w = w
jsonHandler.JSONHandler = slog.NewJSONHandler(w,&slog.HandlerOptions{
AddSource: addSource,
Level: level,
ReplaceAttr: replaceAttr,
})
return &jsonHandler
}
func (oh *OriginJsonHandler) Handle(context context.Context, record slog.Record) error{
oh.Fill(context,&record)
if record.Level == LevelStack || record.Level == LevelFatal || record.Level == LevelDump{
record.Add("stack",debug.Stack())
}
oh.locker.Lock()
defer oh.locker.Unlock()
return oh.JSONHandler.Handle(context, record)
}
func (b *BaseHandler) Fill(context context.Context, record *slog.Record) {
if b.addSource {
var pcs [1]uintptr
runtime.Callers(7, pcs[:])
record.PC = pcs[0]
}
}

View File

@@ -1,519 +1,401 @@
package log package log
import ( import (
"context" "github.com/duanhf2012/rotatelogs"
"fmt" "go.uber.org/zap"
"github.com/duanhf2012/origin/v2/util/bytespool" "go.uber.org/zap/zapcore"
jsoniter "github.com/json-iterator/go" "gopkg.in/natefinch/lumberjack.v2"
"io"
"log/slog"
"os" "os"
"path"
"path/filepath" "path/filepath"
"runtime" "strings"
"sync"
"sync/atomic"
"time" "time"
) )
var json = jsoniter.ConfigCompatibleWithStandardLibrary
var OpenConsole bool
var LogSize int64
var LogChannelCap int
var LogPath string
var LogLevel slog.Level = LevelTrace
var gLogger, _ = NewTextLogger(LevelDebug, "", "",true,LogChannelCap)
var isSetLogger bool var isSetLogger bool
var memPool = bytespool.NewMemAreaPool() var gLogger = NewDefaultLogger()
var LogLevel zapcore.Level
// levels var MaxSize int
const ( var LogPath string
LevelTrace = slog.Level(-8) var OpenConsole *bool
LevelDebug = slog.LevelDebug var LogChanLen int
LevelInfo = slog.LevelInfo
LevelWarning = slog.LevelWarn
LevelError = slog.LevelError
LevelStack = slog.Level(12)
LevelDump = slog.Level(16)
LevelFatal = slog.Level(20)
)
type ILogger interface {
Trace(msg string, args ...any)
Debug(msg string, args ...any)
Info(msg string, args ...any)
Warning(msg string, args ...any)
Error(msg string, args ...any)
Stack(msg string, args ...any)
Dump(msg string, args ...any)
Fatal(msg string, args ...any)
DoSPrintf(level slog.Level,a []interface{})
FormatHeader(buf *Buffer,level slog.Level,calldepth int)
Close()
}
type Logger struct { type Logger struct {
Slogger *slog.Logger *zap.Logger
stack bool
ioWriter IoWriter FileName string
Skip int
sBuff Buffer Encoder zapcore.Encoder
SugaredLogger *zap.SugaredLogger
CoreList []zapcore.Core
WriteSyncerFun []func() zapcore.WriteSyncer
} }
type IoWriter struct { // 设置Logger
outFile io.Writer // destination for output func SetLogger(logger *Logger) {
writeBytes int64 if logger != nil {
logChannel chan []byte
wg sync.WaitGroup
closeSig chan struct{}
lockWrite sync.Mutex
filePath string
fileprefix string
fileDay int
fileCreateTime int64 //second
}
func (iw *IoWriter) Close() error {
iw.lockWrite.Lock()
defer iw.lockWrite.Unlock()
iw.close()
return nil
}
func (iw *IoWriter) close() error {
if iw.closeSig != nil {
close(iw.closeSig)
iw.closeSig = nil
}
iw.wg.Wait()
if iw.outFile!= nil {
err := iw.outFile.(io.Closer).Close()
iw.outFile = nil
return err
}
return nil
}
func (iw *IoWriter) writeFile(p []byte) (n int, err error){
//swich log file
iw.swichFile()
if iw.outFile != nil {
n,err = iw.outFile.Write(p)
if n > 0 {
atomic.AddInt64(&iw.writeBytes,int64(n))
}
}
return 0,nil
}
func (iw *IoWriter) Write(p []byte) (n int, err error){
iw.lockWrite.Lock()
defer iw.lockWrite.Unlock()
if iw.logChannel == nil {
return iw.writeIo(p)
}
copyBuff := memPool.MakeBytes(len(p))
if copyBuff == nil {
return 0,fmt.Errorf("MakeByteSlice failed")
}
copy(copyBuff,p)
iw.logChannel <- copyBuff
return
}
func (iw *IoWriter) writeIo(p []byte) (n int, err error){
n,err = iw.writeFile(p)
if OpenConsole {
n,err = os.Stdout.Write(p)
}
return
}
func (iw *IoWriter) setLogChannel(logChannelNum int) (err error){
iw.lockWrite.Lock()
defer iw.lockWrite.Unlock()
iw.close()
if logChannelNum == 0 {
return nil
}
//copy iw.logChannel
var logInfo []byte
logChannel := make(chan []byte,logChannelNum)
for i := 0; i < logChannelNum&&i<len(iw.logChannel); i++{
logInfo = <- iw.logChannel
logChannel <- logInfo
}
iw.logChannel = logChannel
iw.closeSig = make(chan struct{})
iw.wg.Add(1)
go iw.run()
return nil
}
func (iw *IoWriter) run(){
defer iw.wg.Done()
Loop:
for{
select {
case <- iw.closeSig:
break Loop
case logs := <-iw.logChannel:
iw.writeIo(logs)
memPool.ReleaseBytes(logs)
}
}
for len(iw.logChannel) > 0 {
logs := <-iw.logChannel
iw.writeIo(logs)
memPool.ReleaseBytes(logs)
}
}
func (iw *IoWriter) isFull() bool {
if LogSize == 0 {
return false
}
return atomic.LoadInt64(&iw.writeBytes) >= LogSize
}
func (logger *Logger) setLogChannel(logChannel int) (err error){
return logger.ioWriter.setLogChannel(logChannel)
}
func (iw *IoWriter) swichFile() error{
now := time.Now()
if iw.fileCreateTime == now.Unix() {
return nil
}
if iw.fileDay == now.Day() && iw.isFull() == false {
return nil
}
if iw.filePath != "" {
var err error
fileName := fmt.Sprintf("%s%d%02d%02d_%02d_%02d_%02d.log",
iw.fileprefix,
now.Year(),
now.Month(),
now.Day(),
now.Hour(),
now.Minute(),
now.Second())
filePath := path.Join(iw.filePath, fileName)
iw.outFile,err = os.Create(filePath)
if err != nil {
return err
}
iw.fileDay = now.Day()
iw.fileCreateTime = now.Unix()
atomic.StoreInt64(&iw.writeBytes,0)
}
return nil
}
func NewTextLogger(level slog.Level,pathName string,filePrefix string,addSource bool,logChannelCap int) (ILogger,error){
var logger Logger
logger.ioWriter.filePath = pathName
logger.ioWriter.fileprefix = filePrefix
logger.Slogger = slog.New(NewOriginTextHandler(level,&logger.ioWriter,addSource,defaultReplaceAttr))
logger.setLogChannel(logChannelCap)
err := logger.ioWriter.swichFile()
if err != nil {
return nil,err
}
return &logger,nil
}
func NewJsonLogger(level slog.Level,pathName string,filePrefix string,addSource bool,logChannelCap int) (ILogger,error){
var logger Logger
logger.ioWriter.filePath = pathName
logger.ioWriter.fileprefix = filePrefix
logger.Slogger = slog.New(NewOriginJsonHandler(level,&logger.ioWriter,true,defaultReplaceAttr))
logger.setLogChannel(logChannelCap)
err := logger.ioWriter.swichFile()
if err != nil {
return nil,err
}
return &logger,nil
}
// It's dangerous to call the method on logging
func (logger *Logger) Close() {
logger.ioWriter.Close()
}
func (logger *Logger) Trace(msg string, args ...any) {
logger.Slogger.Log(context.Background(),LevelTrace,msg,args...)
}
func (logger *Logger) Debug(msg string, args ...any) {
logger.Slogger.Log(context.Background(),LevelDebug,msg,args...)
}
func (logger *Logger) Info(msg string, args ...any) {
logger.Slogger.Log(context.Background(),LevelInfo,msg,args...)
}
func (logger *Logger) Warning(msg string, args ...any) {
logger.Slogger.Log(context.Background(),LevelWarning,msg,args...)
}
func (logger *Logger) Error(msg string, args ...any) {
logger.Slogger.Log(context.Background(),LevelError,msg,args...)
}
func (logger *Logger) Stack(msg string, args ...any) {
logger.Slogger.Log(context.Background(),LevelStack,msg,args...)
}
func (logger *Logger) Dump(msg string, args ...any) {
logger.Slogger.Log(context.Background(),LevelDump,msg,args...)
}
func (logger *Logger) Fatal(msg string, args ...any) {
logger.Slogger.Log(context.Background(),LevelFatal,msg,args...)
os.Exit(1)
}
// It's non-thread-safe
func SetLogger(logger ILogger) {
if logger != nil && isSetLogger == false {
gLogger = logger gLogger = logger
isSetLogger = true isSetLogger = true
} }
} }
func GetLogger() ILogger{ // 设置ZapLogger
func SetZapLogger(zapLogger *zap.Logger) {
if zapLogger != nil {
gLogger = &Logger{}
gLogger.Logger = zapLogger
isSetLogger = true
}
}
func GetLogger() *Logger {
return gLogger return gLogger
} }
func Trace(msg string, args ...any){ func (logger *Logger) SetEncoder(encoder zapcore.Encoder) {
gLogger.Trace(msg, args...) logger.Encoder = encoder
} }
func Debug(msg string, args ...any){ func (logger *Logger) SetSkip(skip int) {
gLogger.Debug(msg,args...) logger.Skip = skip
} }
func Info(msg string, args ...any){ func GetJsonEncoder() zapcore.Encoder {
gLogger.Info(msg,args...) encoderConfig := zap.NewProductionEncoderConfig()
} encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
func Warning(msg string, args ...any){ encoderConfig.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
gLogger.Warning(msg,args...) enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
}
func Error(msg string, args ...any){
gLogger.Error(msg,args...)
}
func Stack(msg string, args ...any){
gLogger.Stack(msg,args...)
}
func Dump(dump string, args ...any){
gLogger.Dump(dump,args...)
}
func Fatal(msg string, args ...any){
gLogger.Fatal(msg,args...)
}
func Close() {
gLogger.Close()
}
func ErrorAttr(key string,value error) slog.Attr{
if value== nil {
return slog.Attr{key, slog.StringValue("nil")}
} }
return slog.Attr{key, slog.StringValue(value.Error())} return zapcore.NewJSONEncoder(encoderConfig)
} }
func String(key, value string) slog.Attr { func GetTxtEncoder() zapcore.Encoder {
return slog.Attr{key, slog.StringValue(value)} encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
encoderConfig.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
}
return zapcore.NewConsoleEncoder(encoderConfig)
} }
func Int(key string, value int) slog.Attr { func (logger *Logger) getLogConfig() *lumberjack.Logger {
return slog.Attr{key, slog.Int64Value(int64(value))} return &lumberjack.Logger{
Filename: filepath.Join(LogPath, logger.FileName),
MaxSize: MaxSize,
MaxBackups: 0,
MaxAge: 0,
Compress: false,
LocalTime: true,
}
} }
func Int64(key string, value int64) slog.Attr { func NewDefaultLogger() *Logger {
return slog.Attr{key, slog.Int64Value(value)} logger := Logger{}
logger.Encoder = GetJsonEncoder()
core := zapcore.NewCore(logger.Encoder, zapcore.AddSync(os.Stdout), zap.InfoLevel)
logger.Logger = zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1))
return &logger
} }
func Int32(key string, value int32) slog.Attr { func (logger *Logger) SetSyncers(syncers ...func() zapcore.WriteSyncer) {
return slog.Attr{key, slog.Int64Value(int64(value))} logger.WriteSyncerFun = syncers
} }
func Int16(key string, value int16) slog.Attr { func (logger *Logger) AppendSyncerFun(syncerFun func() zapcore.WriteSyncer) {
return slog.Attr{key, slog.Int64Value(int64(value))} logger.WriteSyncerFun = append(logger.WriteSyncerFun, syncerFun)
} }
func Int8(key string, value int8) slog.Attr { func SetLogLevel(level zapcore.Level) {
return slog.Attr{key, slog.Int64Value(int64(value))} LogLevel = level
} }
func Uint(key string, value uint) slog.Attr { func (logger *Logger) Enabled(zapcore.Level) bool {
return slog.Attr{key, slog.Uint64Value(uint64(value))} return logger.stack
} }
func Uint64(key string, v uint64) slog.Attr { func (logger *Logger) NewLumberjackWriter() zapcore.WriteSyncer {
return slog.Attr{key, slog.Uint64Value(v)} return zapcore.AddSync(
&lumberjack.Logger{
Filename: filepath.Join(LogPath, logger.FileName),
MaxSize: MaxSize,
MaxBackups: 0,
MaxAge: 0,
Compress: false,
LocalTime: true,
})
} }
func Uint32(key string, value uint32) slog.Attr { func (logger *Logger) NewRotatelogsWriter() zapcore.WriteSyncer {
return slog.Attr{key, slog.Uint64Value(uint64(value))} var options []rotatelogs.Option
if MaxSize > 0 {
options = append(options, rotatelogs.WithRotateMaxSize(int64(MaxSize)))
}
if LogChanLen > 0 {
options = append(options, rotatelogs.WithChannelLen(LogChanLen))
}
options = append(options, rotatelogs.WithRotationTime(time.Hour*24))
fileName := strings.TrimRight(logger.FileName, filepath.Ext(logger.FileName))
rotateLogs, err := rotatelogs.NewRotateLogs(LogPath, "20060102/"+fileName+"_20060102_150405", options...)
if err != nil {
panic(err)
}
return zapcore.AddSync(rotateLogs)
} }
func Uint16(key string, value uint16) slog.Attr { func (logger *Logger) Init() {
return slog.Attr{key, slog.Uint64Value(uint64(value))} if isSetLogger {
}
func Uint8(key string, value uint8) slog.Attr {
return slog.Attr{key, slog.Uint64Value(uint64(value))}
}
func Float64(key string, v float64) slog.Attr {
return slog.Attr{key, slog.Float64Value(v)}
}
func Bool(key string, v bool) slog.Attr {
return slog.Attr{key, slog.BoolValue(v)}
}
func Time(key string, v time.Time) slog.Attr {
return slog.Attr{key, slog.TimeValue(v)}
}
func Duration(key string, v time.Duration) slog.Attr {
return slog.Attr{key, slog.DurationValue(v)}
}
func Any(key string, value any) slog.Attr {
return slog.Attr{key, slog.AnyValue(value)}
}
func Group(key string, args ...any) slog.Attr {
return slog.Group(key, args...)
}
func (logger *Logger) DoSPrintf(level slog.Level,a []interface{}) {
if logger.Slogger.Enabled(context.Background(),level) == false{
return return
} }
logger.Slogger.Handler().(IOriginHandler).Lock() var syncerList []zapcore.WriteSyncer
defer logger.Slogger.Handler().(IOriginHandler).UnLock() if logger.WriteSyncerFun == nil {
syncerList = append(syncerList, logger.NewRotatelogsWriter())
logger.sBuff.Reset() } else {
for _, syncer := range logger.WriteSyncerFun {
logger.FormatHeader(&logger.sBuff,level,3) syncerList = append(syncerList, syncer())
}
for _,s := range a {
logger.sBuff.AppendString(slog.AnyValue(s).String())
} }
logger.sBuff.AppendString("\"\n")
logger.ioWriter.Write([]byte(logger.sBuff.Bytes()))
}
func (logger *Logger) STrace(a ...interface{}) { var coreList []zapcore.Core
logger.DoSPrintf(LevelTrace,a) if OpenConsole == nil || *OpenConsole {
} syncerList = append(syncerList, zapcore.AddSync(os.Stdout))
func (logger *Logger) SDebug(a ...interface{}) {
logger.DoSPrintf(LevelDebug,a)
}
func (logger *Logger) SInfo(a ...interface{}) {
logger.DoSPrintf(LevelInfo,a)
}
func (logger *Logger) SWarning(a ...interface{}) {
logger.DoSPrintf(LevelWarning,a)
}
func (logger *Logger) SError(a ...interface{}) {
logger.DoSPrintf(LevelError,a)
}
func STrace(a ...interface{}) {
gLogger.DoSPrintf(LevelTrace,a)
}
func SDebug(a ...interface{}) {
gLogger.DoSPrintf(LevelDebug,a)
}
func SInfo(a ...interface{}) {
gLogger.DoSPrintf(LevelInfo,a)
}
func SWarning(a ...interface{}) {
gLogger.DoSPrintf(LevelWarning,a)
}
func SError(a ...interface{}) {
gLogger.DoSPrintf(LevelError,a)
}
func (logger *Logger) FormatHeader(buf *Buffer,level slog.Level,calldepth int) {
t := time.Now()
var file string
var line int
// Release lock while getting caller info - it's expensive.
var ok bool
_, file, line, ok = runtime.Caller(calldepth)
if !ok {
file = "???"
line = 0
} }
file = filepath.Base(file)
buf.AppendString("time=\"") for _, writer := range syncerList {
buf.AppendString(t.Format("2006/01/02 15:04:05")) core := zapcore.NewCore(logger.Encoder, writer, LogLevel)
buf.AppendString("\"") coreList = append(coreList, core)
logger.sBuff.AppendString(" level=") }
logger.sBuff.AppendString(getStrLevel(level))
logger.sBuff.AppendString(" source=")
buf.AppendString(file) if logger.CoreList != nil {
buf.AppendByte(':') coreList = append(coreList, logger.CoreList...)
buf.AppendInt(int64(line)) }
buf.AppendString(" msg=\"")
} core := zapcore.NewTee(coreList...)
logger.Logger = zap.New(core, zap.AddCaller(), zap.AddStacktrace(logger), zap.AddCallerSkip(1+logger.Skip))
logger.SugaredLogger = logger.Logger.Sugar()
}
func (logger *Logger) Debug(msg string, fields ...zap.Field) {
logger.Logger.Debug(msg, fields...)
}
func (logger *Logger) Info(msg string, fields ...zap.Field) {
logger.Logger.Info(msg, fields...)
}
func (logger *Logger) Warn(msg string, fields ...zap.Field) {
logger.Logger.Warn(msg, fields...)
}
func (logger *Logger) Error(msg string, fields ...zap.Field) {
logger.Logger.Error(msg, fields...)
}
func (logger *Logger) StackError(msg string, args ...zap.Field) {
logger.stack = true
logger.Logger.Log(zapcore.ErrorLevel, msg, args...)
logger.stack = false
}
func (logger *Logger) Fatal(msg string, fields ...zap.Field) {
gLogger.stack = true
logger.Logger.Fatal(msg, fields...)
gLogger.stack = false
}
func Debug(msg string, fields ...zap.Field) {
gLogger.Logger.Debug(msg, fields...)
}
func Info(msg string, fields ...zap.Field) {
gLogger.Logger.Info(msg, fields...)
}
func Warn(msg string, fields ...zap.Field) {
gLogger.Logger.Warn(msg, fields...)
}
func Error(msg string, fields ...zap.Field) {
gLogger.Logger.Error(msg, fields...)
}
func StackError(msg string, fields ...zap.Field) {
gLogger.stack = true
gLogger.Logger.Error(msg, fields...)
gLogger.stack = false
}
func Fatal(msg string, fields ...zap.Field) {
gLogger.stack = true
gLogger.Logger.Fatal(msg, fields...)
gLogger.stack = false
}
func Debugf(template string, args ...any) {
gLogger.SugaredLogger.Debugf(template, args...)
}
func Infof(template string, args ...any) {
gLogger.SugaredLogger.Infof(template, args...)
}
func Warnf(template string, args ...any) {
gLogger.SugaredLogger.Warnf(template, args...)
}
func Errorf(template string, args ...any) {
gLogger.SugaredLogger.Errorf(template, args...)
}
func StackErrorf(template string, args ...any) {
gLogger.stack = true
gLogger.SugaredLogger.Errorf(template, args...)
gLogger.stack = false
}
func Fatalf(template string, args ...any) {
gLogger.SugaredLogger.Fatalf(template, args...)
}
func (logger *Logger) SDebug(args ...interface{}) {
logger.SugaredLogger.Debugln(args...)
}
func (logger *Logger) SInfo(args ...interface{}) {
logger.SugaredLogger.Infoln(args...)
}
func (logger *Logger) SWarn(args ...interface{}) {
logger.SugaredLogger.Warnln(args...)
}
func (logger *Logger) SError(args ...interface{}) {
logger.SugaredLogger.Errorln(args...)
}
func (logger *Logger) SStackError(args ...interface{}) {
gLogger.stack = true
logger.SugaredLogger.Errorln(args...)
gLogger.stack = false
}
func (logger *Logger) SFatal(args ...interface{}) {
gLogger.stack = true
logger.SugaredLogger.Fatalln(args...)
gLogger.stack = false
}
func SDebug(args ...interface{}) {
gLogger.SugaredLogger.Debugln(args...)
}
func SInfo(args ...interface{}) {
gLogger.SugaredLogger.Infoln(args...)
}
func SWarn(args ...interface{}) {
gLogger.SugaredLogger.Warnln(args...)
}
func SError(args ...interface{}) {
gLogger.SugaredLogger.Errorln(args...)
}
func SStackError(args ...interface{}) {
gLogger.stack = true
gLogger.SugaredLogger.Errorln(args...)
gLogger.stack = false
}
func SFatal(args ...interface{}) {
gLogger.stack = true
gLogger.SugaredLogger.Fatalln(args...)
gLogger.stack = false
}
func ErrorField(key string, value error) zap.Field {
if value == nil {
return zap.String(key, "nil")
}
return zap.String(key, value.Error())
}
func String(key, value string) zap.Field {
return zap.String(key, value)
}
func Int(key string, value int) zap.Field {
return zap.Int(key, value)
}
func Int64(key string, value int64) zap.Field {
return zap.Int64(key, value)
}
func Int32(key string, value int32) zap.Field {
return zap.Int32(key, value)
}
func Int16(key string, value int16) zap.Field {
return zap.Int16(key, value)
}
func Int8(key string, value int8) zap.Field {
return zap.Int8(key, value)
}
func Uint(key string, value uint) zap.Field {
return zap.Uint(key, value)
}
func Uint64(key string, v uint64) zap.Field {
return zap.Uint64(key, v)
}
func Uint32(key string, value uint32) zap.Field {
return zap.Uint32(key, value)
}
func Uint16(key string, value uint16) zap.Field {
return zap.Uint16(key, value)
}
func Uint8(key string, value uint8) zap.Field {
return zap.Uint8(key, value)
}
func Float64(key string, v float64) zap.Field {
return zap.Float64(key, v)
}
func Bool(key string, v bool) zap.Field {
return zap.Bool(key, v)
}
func Bools(key string, v []bool) zap.Field {
return zap.Bools(key, v)
}
func Time(key string, v time.Time) zap.Field {
return zap.Time(key, v)
}
func Duration(key string, v time.Duration) zap.Field {
return zap.Duration(key, v)
}
func Durations(key string, v []time.Duration) zap.Field {
return zap.Durations(key, v)
}
func Any(key string, value any) zap.Field {
return zap.Any(key, value)
}

View File

@@ -1,7 +1,12 @@
package network package network
import ( import (
"errors"
"github.com/duanhf2012/origin/v2/log"
"net" "net"
"sync"
"sync/atomic"
"time"
) )
type Conn interface { type Conn interface {
@@ -13,3 +18,158 @@ type Conn interface {
Destroy() Destroy()
ReleaseReadMsg(byteBuff []byte) ReleaseReadMsg(byteBuff []byte)
} }
type ConnSet map[net.Conn]struct{}
type NetConn struct {
sync.Mutex
conn net.Conn
writeChan chan []byte
closeFlag int32
msgParser *MsgParser
}
func freeChannel(conn *NetConn) {
for len(conn.writeChan) > 0 {
byteBuff := <-conn.writeChan
if byteBuff != nil {
conn.ReleaseReadMsg(byteBuff)
}
}
}
func newNetConn(conn net.Conn, pendingWriteNum int, msgParser *MsgParser, writeDeadline time.Duration) *NetConn {
netConn := new(NetConn)
netConn.conn = conn
netConn.writeChan = make(chan []byte, pendingWriteNum)
netConn.msgParser = msgParser
go func() {
for b := range netConn.writeChan {
if b == nil {
break
}
conn.SetWriteDeadline(time.Now().Add(writeDeadline))
_, err := conn.Write(b)
netConn.msgParser.ReleaseBytes(b)
if err != nil {
break
}
}
conn.Close()
netConn.Lock()
freeChannel(netConn)
atomic.StoreInt32(&netConn.closeFlag, 1)
netConn.Unlock()
}()
return netConn
}
func (netConn *NetConn) doDestroy() {
netConn.conn.Close()
if atomic.LoadInt32(&netConn.closeFlag) == 0 {
close(netConn.writeChan)
atomic.StoreInt32(&netConn.closeFlag, 1)
}
}
func (netConn *NetConn) Destroy() {
netConn.Lock()
defer netConn.Unlock()
netConn.doDestroy()
}
func (netConn *NetConn) Close() {
netConn.Lock()
defer netConn.Unlock()
if atomic.LoadInt32(&netConn.closeFlag) == 1 {
return
}
netConn.doWrite(nil)
atomic.StoreInt32(&netConn.closeFlag, 1)
}
func (netConn *NetConn) GetRemoteIp() string {
return netConn.conn.RemoteAddr().String()
}
func (netConn *NetConn) doWrite(b []byte) error {
if len(netConn.writeChan) == cap(netConn.writeChan) {
netConn.ReleaseReadMsg(b)
log.Error("close conn: channel full")
netConn.doDestroy()
return errors.New("close conn: channel full")
}
netConn.writeChan <- b
return nil
}
// b must not be modified by the others goroutines
func (netConn *NetConn) Write(b []byte) (int,error) {
netConn.Lock()
defer netConn.Unlock()
if atomic.LoadInt32(&netConn.closeFlag) == 1 || b == nil {
netConn.ReleaseReadMsg(b)
return 0,errors.New("conn is close")
}
return len(b),netConn.doWrite(b)
}
func (netConn *NetConn) Read(b []byte) (int, error) {
return netConn.conn.Read(b)
}
func (netConn *NetConn) LocalAddr() net.Addr {
return netConn.conn.LocalAddr()
}
func (netConn *NetConn) RemoteAddr() net.Addr {
return netConn.conn.RemoteAddr()
}
func (netConn *NetConn) ReadMsg() ([]byte, error) {
return netConn.msgParser.Read(netConn)
}
func (netConn *NetConn) GetRecyclerReaderBytes() func(data []byte) {
return netConn.msgParser.GetRecyclerReaderBytes()
}
func (netConn *NetConn) ReleaseReadMsg(byteBuff []byte) {
netConn.msgParser.ReleaseBytes(byteBuff)
}
func (netConn *NetConn) WriteMsg(args ...[]byte) error {
if atomic.LoadInt32(&netConn.closeFlag) == 1 {
return errors.New("conn is close")
}
return netConn.msgParser.Write(netConn, args...)
}
func (netConn *NetConn) WriteRawMsg(args []byte) error {
if atomic.LoadInt32(&netConn.closeFlag) == 1 {
return errors.New("conn is close")
}
_,err:= netConn.Write(args)
return err
}
func (netConn *NetConn) IsConnected() bool {
return atomic.LoadInt32(&netConn.closeFlag) == 0
}
func (netConn *NetConn) SetReadDeadline(d time.Duration) {
netConn.conn.SetReadDeadline(time.Now().Add(d))
}
func (netConn *NetConn) SetWriteDeadline(d time.Duration) {
netConn.conn.SetWriteDeadline(time.Now().Add(d))
}

View File

@@ -8,20 +8,20 @@ import (
"time" "time"
) )
var DefaultMaxHeaderBytes int = 1<<20 var DefaultMaxHeaderBytes = 1 << 20
type CAFile struct { type CAFile struct {
CertFile string CertFile string
Keyfile string Keyfile string
} }
type HttpServer struct { type HttpServer struct {
listenAddr string listenAddr string
readTimeout time.Duration readTimeout time.Duration
writeTimeout time.Duration writeTimeout time.Duration
handler http.Handler handler http.Handler
caFileList []CAFile caFileList []CAFile
httpServer *http.Server httpServer *http.Server
} }
@@ -39,7 +39,7 @@ func (slf *HttpServer) Start() {
func (slf *HttpServer) startListen() error { func (slf *HttpServer) startListen() error {
if slf.httpServer != nil { if slf.httpServer != nil {
return errors.New("Duplicate start not allowed") return errors.New("duplicate start not allowed")
} }
var tlsCaList []tls.Certificate var tlsCaList []tls.Certificate
@@ -47,7 +47,7 @@ func (slf *HttpServer) startListen() error {
for _, caFile := range slf.caFileList { for _, caFile := range slf.caFileList {
cer, err := tls.LoadX509KeyPair(caFile.CertFile, caFile.Keyfile) cer, err := tls.LoadX509KeyPair(caFile.CertFile, caFile.Keyfile)
if err != nil { if err != nil {
log.Fatal("Load CA file is fail",log.String("error",err.Error()),log.String("certFile",caFile.CertFile),log.String("keyFile",caFile.Keyfile)) log.Fatal("Load CA file is fail", log.String("error", err.Error()), log.String("certFile", caFile.CertFile), log.String("keyFile", caFile.Keyfile))
return err return err
} }
tlsCaList = append(tlsCaList, cer) tlsCaList = append(tlsCaList, cer)
@@ -74,14 +74,13 @@ func (slf *HttpServer) startListen() error {
} }
if err != nil { if err != nil {
log.Fatal("Listen failure",log.String("error",err.Error()),log.String("addr:",slf.listenAddr)) log.Fatal("Listen failure", log.String("error", err.Error()), log.String("addr:", slf.listenAddr))
return err return err
} }
return nil return nil
} }
func (slf *HttpServer) SetCAFile(caFile []CAFile) { func (slf *HttpServer) SetCAFile(caFile []CAFile) {
slf.caFileList = caFile slf.caFileList = caFile
} }

161
network/kcp_client.go Normal file
View File

@@ -0,0 +1,161 @@
package network
import (
"github.com/duanhf2012/origin/v2/log"
"github.com/xtaci/kcp-go/v5"
"net"
"sync"
"time"
)
type KCPClient struct {
sync.Mutex
Addr string
ConnNum int
ConnectInterval time.Duration
PendingWriteNum int
ReadDeadline time.Duration
WriteDeadline time.Duration
AutoReconnect bool
NewAgent func(conn *NetConn) Agent
cons ConnSet
wg sync.WaitGroup
closeFlag bool
// msg parser
MsgParser
}
func (client *KCPClient) Start() {
client.init()
for i := 0; i < client.ConnNum; i++ {
client.wg.Add(1)
go client.connect()
}
}
func (client *KCPClient) init() {
client.Lock()
defer client.Unlock()
if client.ConnNum <= 0 {
client.ConnNum = 1
log.Info("invalid ConnNum", log.Int("reset", client.ConnNum))
}
if client.ConnectInterval <= 0 {
client.ConnectInterval = 3 * time.Second
log.Info("invalid ConnectInterval", log.Duration("reset", client.ConnectInterval))
}
if client.PendingWriteNum <= 0 {
client.PendingWriteNum = 1000
log.Info("invalid PendingWriteNum", log.Int("reset", client.PendingWriteNum))
}
if client.ReadDeadline == 0 {
client.ReadDeadline = 15 * time.Second
log.Info("invalid ReadDeadline", log.Int64("reset", int64(client.ReadDeadline.Seconds())))
}
if client.WriteDeadline == 0 {
client.WriteDeadline = 15 * time.Second
log.Info("invalid WriteDeadline", log.Int64("reset", int64(client.WriteDeadline.Seconds())))
}
if client.NewAgent == nil {
log.Fatal("NewAgent must not be nil")
}
if client.cons != nil {
log.Fatal("client is running")
}
if client.MinMsgLen == 0 {
client.MinMsgLen = Default_MinMsgLen
}
if client.MaxMsgLen == 0 {
client.MaxMsgLen = Default_MaxMsgLen
}
if client.LenMsgLen == 0 {
client.LenMsgLen = Default_LenMsgLen
}
maxMsgLen := client.MsgParser.getMaxMsgLen()
if client.MaxMsgLen > maxMsgLen {
client.MaxMsgLen = maxMsgLen
log.Info("invalid MaxMsgLen", log.Uint32("reset", maxMsgLen))
}
client.cons = make(ConnSet)
client.closeFlag = false
client.MsgParser.Init()
}
func (client *KCPClient) GetCloseFlag() bool {
client.Lock()
defer client.Unlock()
return client.closeFlag
}
func (client *KCPClient) dial() net.Conn {
for {
conn, err := kcp.DialWithOptions(client.Addr, nil, 10, 3)
if client.closeFlag {
return conn
} else if err == nil && conn != nil {
conn.SetNoDelay(1, 10, 2, 1)
conn.SetDSCP(46)
conn.SetStreamMode(true)
conn.SetWindowSize(1024, 1024)
return conn
}
log.Warn("connect error ", log.String("error", err.Error()), log.String("Addr", client.Addr))
time.Sleep(client.ConnectInterval)
continue
}
}
func (client *KCPClient) connect() {
defer client.wg.Done()
reconnect:
conn := client.dial()
if conn == nil {
return
}
client.Lock()
if client.closeFlag {
client.Unlock()
conn.Close()
return
}
client.cons[conn] = struct{}{}
client.Unlock()
netConn := newNetConn(conn, client.PendingWriteNum, &client.MsgParser, client.WriteDeadline)
agent := client.NewAgent(netConn)
agent.Run()
// cleanup
netConn.Close()
client.Lock()
delete(client.cons, conn)
client.Unlock()
agent.OnClose()
if client.AutoReconnect {
time.Sleep(client.ConnectInterval)
goto reconnect
}
}
func (client *KCPClient) Close(waitDone bool) {
client.Lock()
client.closeFlag = true
for conn := range client.cons {
conn.Close()
}
client.cons = nil
client.Unlock()
if waitDone == true {
client.wg.Wait()
}
}

257
network/kcp_server.go Normal file
View File

@@ -0,0 +1,257 @@
package network
import (
"github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/network/processor"
"github.com/xtaci/kcp-go/v5"
"sync"
"time"
)
type KCPServer struct {
NewAgent func(Conn) Agent
kcpCfg *KcpCfg
blockCrypt kcp.BlockCrypt
process processor.IRawProcessor
msgParser MsgParser
conns ConnSet
mutexConns sync.Mutex
wgLn sync.WaitGroup
wgConns sync.WaitGroup
listener *kcp.Listener
}
/*
NoDelayCfg
普通模式: ikcp_nodelay(kcp, 0, 40, 0, 0);
极速模式: ikcp_nodelay(kcp, 1, 10, 2, 1);
*/
type NoDelayCfg struct {
NoDelay int // 是否启用 nodelay模式0不启用1启用
IntervalMill int // 协议内部工作的 interval单位毫秒比如 10ms或者 20ms
Resend int // 快速重传模式默认0关闭可以设置22次ACK跨越将会直接重传
CongestionControl int // 是否关闭流控默认是0代表不关闭1代表关闭
}
const (
DefaultNoDelay = 1
DefaultIntervalMill = 10
DefaultResend = 2
DefaultCongestionControl = 1
DefaultMtu = 1400
DefaultSndWndSize = 4096
DefaultRcvWndSize = 4096
DefaultStreamMode = true
DefaultDSCP = 46
DefaultDataShards = 10
DefaultParityShards = 0
DefaultReadDeadlineMill = 15 * time.Second
DefaultWriteDeadlineMill = 15 * time.Second
DefaultMaxConnNum = 20000
)
type KcpCfg struct {
ListenAddr string // 监听地址
MaxConnNum int //最大连接数
NoDelay *NoDelayCfg
Mtu *int // mtu大小
SndWndSize *int // 发送窗口大小,默认1024
RcvWndSize *int // 接收窗口大小,默认1024
ReadDeadlineMill *time.Duration // 读超时毫秒
WriteDeadlineMill *time.Duration // 写超时毫秒
StreamMode *bool // 是否打开流模式,默认true
DSCP *int // 差分服务代码点默认46
ReadBuffSize *int // 读Buff大小,默认
WriteBuffSize *int // 写Buff大小
// 用于 FEC前向纠错的数据分片和校验分片数量,默认10,0
DataShards *int
ParityShards *int
// 包体内容
LittleEndian bool //是否小端序
LenMsgLen int //消息头占用byte数量只能是1byte,2byte,4byte。如果是4byte意味着消息最大可以是math.MaxUint32(4GB)
MinMsgLen uint32 //最小消息长度
MaxMsgLen uint32 //最大消息长度,超过判定不合法,断开连接
PendingWriteNum int //写channel最大消息数量
}
func (kp *KCPServer) Init(kcpCfg *KcpCfg) {
kp.kcpCfg = kcpCfg
kp.msgParser.Init()
kp.msgParser.LenMsgLen = kp.kcpCfg.LenMsgLen
kp.msgParser.MaxMsgLen = kp.kcpCfg.MaxMsgLen
kp.msgParser.MinMsgLen = kp.kcpCfg.MinMsgLen
kp.msgParser.LittleEndian = kp.kcpCfg.LittleEndian
// setting default noDelay
if kp.kcpCfg.NoDelay == nil {
var noDelay NoDelayCfg
noDelay.NoDelay = DefaultNoDelay
noDelay.IntervalMill = DefaultIntervalMill
noDelay.Resend = DefaultResend
noDelay.CongestionControl = DefaultCongestionControl
kp.kcpCfg.NoDelay = &noDelay
}
if kp.kcpCfg.Mtu == nil {
mtu := DefaultMtu
kp.kcpCfg.Mtu = &mtu
}
if kp.kcpCfg.SndWndSize == nil {
sndWndSize := DefaultSndWndSize
kp.kcpCfg.SndWndSize = &sndWndSize
}
if kp.kcpCfg.RcvWndSize == nil {
rcvWndSize := DefaultRcvWndSize
kp.kcpCfg.RcvWndSize = &rcvWndSize
}
if kp.kcpCfg.ReadDeadlineMill == nil {
readDeadlineMill := DefaultReadDeadlineMill
kp.kcpCfg.ReadDeadlineMill = &readDeadlineMill
} else {
*kp.kcpCfg.ReadDeadlineMill *= time.Millisecond
}
if kp.kcpCfg.WriteDeadlineMill == nil {
writeDeadlineMill := DefaultWriteDeadlineMill
kp.kcpCfg.WriteDeadlineMill = &writeDeadlineMill
} else {
*kp.kcpCfg.WriteDeadlineMill *= time.Millisecond
}
if kp.kcpCfg.StreamMode == nil {
streamMode := DefaultStreamMode
kp.kcpCfg.StreamMode = &streamMode
}
if kp.kcpCfg.DataShards == nil {
dataShards := DefaultDataShards
kp.kcpCfg.DataShards = &dataShards
}
if kp.kcpCfg.ParityShards == nil {
parityShards := DefaultParityShards
kp.kcpCfg.ParityShards = &parityShards
}
if kp.kcpCfg.DSCP == nil {
dss := DefaultDSCP
kp.kcpCfg.DSCP = &dss
}
if kp.kcpCfg.MaxConnNum == 0 {
kp.kcpCfg.MaxConnNum = DefaultMaxConnNum
}
kp.conns = make(ConnSet, 2048)
kp.msgParser.Init()
return
}
func (kp *KCPServer) Start() error {
listener, err := kcp.ListenWithOptions(kp.kcpCfg.ListenAddr, kp.blockCrypt, *kp.kcpCfg.DataShards, *kp.kcpCfg.ParityShards)
if err != nil {
return err
}
if kp.kcpCfg.ReadBuffSize != nil {
err = listener.SetReadBuffer(*kp.kcpCfg.ReadBuffSize)
if err != nil {
return err
}
}
if kp.kcpCfg.WriteBuffSize != nil {
err = listener.SetWriteBuffer(*kp.kcpCfg.WriteBuffSize)
if err != nil {
return err
}
}
err = listener.SetDSCP(*kp.kcpCfg.DSCP)
if err != nil {
return err
}
kp.listener = listener
kp.wgLn.Add(1)
go func() {
defer kp.wgLn.Done()
for kp.run(listener) {
}
}()
return nil
}
func (kp *KCPServer) initSession(session *kcp.UDPSession) {
session.SetStreamMode(*kp.kcpCfg.StreamMode)
session.SetWindowSize(*kp.kcpCfg.SndWndSize, *kp.kcpCfg.RcvWndSize)
session.SetNoDelay(kp.kcpCfg.NoDelay.NoDelay, kp.kcpCfg.NoDelay.IntervalMill, kp.kcpCfg.NoDelay.Resend, kp.kcpCfg.NoDelay.CongestionControl)
session.SetDSCP(*kp.kcpCfg.DSCP)
session.SetMtu(*kp.kcpCfg.Mtu)
session.SetACKNoDelay(false)
//session.SetWriteDeadline(time.Now().Add(*kp.kcpCfg.WriteDeadlineMill))
}
func (kp *KCPServer) run(listener *kcp.Listener) bool {
conn, err := listener.Accept()
if err != nil {
log.Error("accept error", log.String("ListenAddr", kp.kcpCfg.ListenAddr), log.ErrorField("err", err))
return false
}
kp.mutexConns.Lock()
if len(kp.conns) >= kp.kcpCfg.MaxConnNum {
kp.mutexConns.Unlock()
conn.Close()
log.Warn("too many connections")
return true
}
kp.conns[conn] = struct{}{}
kp.mutexConns.Unlock()
if kp.kcpCfg.ReadBuffSize != nil {
conn.(*kcp.UDPSession).SetReadBuffer(*kp.kcpCfg.ReadBuffSize)
}
if kp.kcpCfg.WriteBuffSize != nil {
conn.(*kcp.UDPSession).SetWriteBuffer(*kp.kcpCfg.WriteBuffSize)
}
kp.initSession(conn.(*kcp.UDPSession))
netConn := newNetConn(conn, kp.kcpCfg.PendingWriteNum, &kp.msgParser, *kp.kcpCfg.WriteDeadlineMill)
agent := kp.NewAgent(netConn)
kp.wgConns.Add(1)
go func() {
agent.Run()
// cleanup
conn.Close()
kp.mutexConns.Lock()
delete(kp.conns, conn)
kp.mutexConns.Unlock()
agent.OnClose()
kp.wgConns.Done()
}()
return true
}
func (kp *KCPServer) Close() {
kp.listener.Close()
kp.wgLn.Wait()
kp.mutexConns.Lock()
for conn := range kp.conns {
conn.Close()
}
kp.conns = nil
kp.mutexConns.Unlock()
kp.wgConns.Wait()
}

View File

@@ -13,29 +13,29 @@ type MessageJsonInfo struct {
msgHandler MessageJsonHandler msgHandler MessageJsonHandler
} }
type MessageJsonHandler func(clientId string,msg interface{}) type MessageJsonHandler func(clientId string, msg interface{})
type ConnectJsonHandler func(clientId string) type ConnectJsonHandler func(clientId string)
type UnknownMessageJsonHandler func(clientId string,msg []byte) type UnknownMessageJsonHandler func(clientId string, msg []byte)
type JsonProcessor struct { type JsonProcessor struct {
mapMsg map[uint16]MessageJsonInfo mapMsg map[uint16]MessageJsonInfo
LittleEndian bool LittleEndian bool
unknownMessageHandler UnknownMessageJsonHandler unknownMessageHandler UnknownMessageJsonHandler
connectHandler ConnectJsonHandler connectHandler ConnectJsonHandler
disconnectHandler ConnectJsonHandler disconnectHandler ConnectJsonHandler
bytespool.IBytesMempool bytespool.IBytesMemPool
} }
type JsonPackInfo struct { type JsonPackInfo struct {
typ uint16 typ uint16
msg interface{} msg interface{}
rawMsg []byte rawMsg []byte
} }
func NewJsonProcessor() *JsonProcessor { func NewJsonProcessor() *JsonProcessor {
processor := &JsonProcessor{mapMsg:map[uint16]MessageJsonInfo{}} processor := &JsonProcessor{mapMsg: map[uint16]MessageJsonInfo{}}
processor.IBytesMempool = bytespool.NewMemAreaPool() processor.IBytesMemPool = bytespool.NewMemAreaPool()
return processor return processor
} }
@@ -44,97 +44,101 @@ func (jsonProcessor *JsonProcessor) SetByteOrder(littleEndian bool) {
jsonProcessor.LittleEndian = littleEndian jsonProcessor.LittleEndian = littleEndian
} }
// must goroutine safe // MsgRoute must goroutine safe
func (jsonProcessor *JsonProcessor ) MsgRoute(clientId string,msg interface{}) error{ func (jsonProcessor *JsonProcessor) MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error {
pPackInfo := msg.(*JsonPackInfo) pPackInfo := msg.(*JsonPackInfo)
v,ok := jsonProcessor.mapMsg[pPackInfo.typ] defer recyclerReaderBytes(pPackInfo.rawMsg)
v, ok := jsonProcessor.mapMsg[pPackInfo.typ]
if ok == false { if ok == false {
return fmt.Errorf("cannot find msgtype %d is register!",pPackInfo.typ) return fmt.Errorf("cannot find msgtype %d is register", pPackInfo.typ)
} }
v.msgHandler(clientId,pPackInfo.msg) v.msgHandler(clientId, pPackInfo.msg)
return nil return nil
} }
func (jsonProcessor *JsonProcessor) Unmarshal(clientId string,data []byte) (interface{}, error) { func (jsonProcessor *JsonProcessor) Unmarshal(clientId string, data []byte) (interface{}, error) {
typeStruct := struct {Type int `json:"typ"`}{} typeStruct := struct {
defer jsonProcessor.ReleaseBytes(data) Type int `json:"typ"`
}{}
err := json.Unmarshal(data, &typeStruct) err := json.Unmarshal(data, &typeStruct)
if err != nil { if err != nil {
return nil, err return nil, err
} }
msgType := uint16(typeStruct.Type) msgType := uint16(typeStruct.Type)
info,ok := jsonProcessor.mapMsg[msgType] info, ok := jsonProcessor.mapMsg[msgType]
if ok == false { if ok == false {
return nil,fmt.Errorf("Cannot find register %d msgType!",msgType) return nil, fmt.Errorf("cannot find register %d msgType", msgType)
} }
msgData := reflect.New(info.msgType.Elem()).Interface() msgData := reflect.New(info.msgType.Elem()).Interface()
err = json.Unmarshal(data, msgData) err = json.Unmarshal(data, msgData)
if err != nil { if err != nil {
return nil,err return nil, err
} }
return &JsonPackInfo{typ:msgType,msg:msgData},nil return &JsonPackInfo{typ: msgType, msg: msgData, rawMsg: data}, nil
} }
func (jsonProcessor *JsonProcessor) Marshal(clientId string,msg interface{}) ([]byte, error) { func (jsonProcessor *JsonProcessor) Marshal(clientId string, msg interface{}) ([]byte, error) {
rawMsg,err := json.Marshal(msg) rawMsg, err := json.Marshal(msg)
if err != nil { if err != nil {
return nil,err return nil, err
} }
return rawMsg,nil return rawMsg, nil
} }
func (jsonProcessor *JsonProcessor) Register(msgtype uint16,msg interface{},handle MessageJsonHandler) { func (jsonProcessor *JsonProcessor) Register(msgType uint16, msg interface{}, handle MessageJsonHandler) {
var info MessageJsonInfo var info MessageJsonInfo
info.msgType = reflect.TypeOf(msg) info.msgType = reflect.TypeOf(msg)
info.msgHandler = handle info.msgHandler = handle
jsonProcessor.mapMsg[msgtype] = info jsonProcessor.mapMsg[msgType] = info
} }
func (jsonProcessor *JsonProcessor) MakeMsg(msgType uint16,msg interface{}) *JsonPackInfo { func (jsonProcessor *JsonProcessor) MakeMsg(msgType uint16, msg interface{}) *JsonPackInfo {
return &JsonPackInfo{typ:msgType,msg:msg} return &JsonPackInfo{typ: msgType, msg: msg}
} }
func (jsonProcessor *JsonProcessor) MakeRawMsg(msgType uint16,msg []byte) *JsonPackInfo { func (jsonProcessor *JsonProcessor) MakeRawMsg(msgType uint16, msg []byte) *JsonPackInfo {
return &JsonPackInfo{typ:msgType,rawMsg:msg} return &JsonPackInfo{typ: msgType, rawMsg: msg}
} }
func (jsonProcessor *JsonProcessor) UnknownMsgRoute(clientId string,msg interface{}){ func (jsonProcessor *JsonProcessor) UnknownMsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) {
if jsonProcessor.unknownMessageHandler==nil { defer recyclerReaderBytes(msg.([]byte))
log.Debug("Unknown message",log.String("clientId",clientId)) if jsonProcessor.unknownMessageHandler == nil {
log.Debug("Unknown message", log.String("clientId", clientId))
return return
} }
jsonProcessor.unknownMessageHandler(clientId,msg.([]byte)) jsonProcessor.unknownMessageHandler(clientId, msg.([]byte))
} }
func (jsonProcessor *JsonProcessor) ConnectedRoute(clientId string){ func (jsonProcessor *JsonProcessor) ConnectedRoute(clientId string) {
if jsonProcessor.connectHandler != nil { if jsonProcessor.connectHandler != nil {
jsonProcessor.connectHandler(clientId) jsonProcessor.connectHandler(clientId)
} }
} }
func (jsonProcessor *JsonProcessor) DisConnectedRoute(clientId string){ func (jsonProcessor *JsonProcessor) DisConnectedRoute(clientId string) {
if jsonProcessor.disconnectHandler != nil { if jsonProcessor.disconnectHandler != nil {
jsonProcessor.disconnectHandler(clientId) jsonProcessor.disconnectHandler(clientId)
} }
} }
func (jsonProcessor *JsonProcessor) RegisterUnknownMsg(unknownMessageHandler UnknownMessageJsonHandler){ func (jsonProcessor *JsonProcessor) RegisterUnknownMsg(unknownMessageHandler UnknownMessageJsonHandler) {
jsonProcessor.unknownMessageHandler = unknownMessageHandler jsonProcessor.unknownMessageHandler = unknownMessageHandler
} }
func (jsonProcessor *JsonProcessor) RegisterConnected(connectHandler ConnectJsonHandler){ func (jsonProcessor *JsonProcessor) RegisterConnected(connectHandler ConnectJsonHandler) {
jsonProcessor.connectHandler = connectHandler jsonProcessor.connectHandler = connectHandler
} }
func (jsonProcessor *JsonProcessor) RegisterDisConnected(disconnectHandler ConnectJsonHandler){ func (jsonProcessor *JsonProcessor) RegisterDisConnected(disconnectHandler ConnectJsonHandler) {
jsonProcessor.disconnectHandler = disconnectHandler jsonProcessor.disconnectHandler = disconnectHandler
} }

View File

@@ -26,7 +26,7 @@ type PBProcessor struct {
unknownMessageHandler UnknownMessageHandler unknownMessageHandler UnknownMessageHandler
connectHandler ConnectHandler connectHandler ConnectHandler
disconnectHandler ConnectHandler disconnectHandler ConnectHandler
bytespool.IBytesMempool bytespool.IBytesMemPool
} }
type PBPackInfo struct { type PBPackInfo struct {
@@ -37,7 +37,7 @@ type PBPackInfo struct {
func NewPBProcessor() *PBProcessor { func NewPBProcessor() *PBProcessor {
processor := &PBProcessor{mapMsg: map[uint16]MessageInfo{}} processor := &PBProcessor{mapMsg: map[uint16]MessageInfo{}}
processor.IBytesMempool = bytespool.NewMemAreaPool() processor.IBytesMemPool = bytespool.NewMemAreaPool()
return processor return processor
} }
@@ -53,25 +53,26 @@ func (slf *PBPackInfo) GetMsg() proto.Message {
return slf.msg return slf.msg
} }
// must goroutine safe // MsgRoute must goroutine safe
func (pbProcessor *PBProcessor) MsgRoute(clientId string, msg interface{}) error { func (pbProcessor *PBProcessor) MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error {
pPackInfo := msg.(*PBPackInfo) pPackInfo := msg.(*PBPackInfo)
defer recyclerReaderBytes(pPackInfo.rawMsg)
v, ok := pbProcessor.mapMsg[pPackInfo.typ] v, ok := pbProcessor.mapMsg[pPackInfo.typ]
if ok == false { if ok == false {
return fmt.Errorf("Cannot find msgtype %d is register!", pPackInfo.typ) return fmt.Errorf("cannot find msgtype %d is register", pPackInfo.typ)
} }
v.msgHandler(clientId, pPackInfo.msg) v.msgHandler(clientId, pPackInfo.msg)
return nil return nil
} }
// must goroutine safe // Unmarshal must goroutine safe
func (pbProcessor *PBProcessor) Unmarshal(clientId string, data []byte) (interface{}, error) { func (pbProcessor *PBProcessor) Unmarshal(clientId string, data []byte) (interface{}, error) {
defer pbProcessor.ReleaseBytes(data)
return pbProcessor.UnmarshalWithOutRelease(clientId, data) return pbProcessor.UnmarshalWithOutRelease(clientId, data)
} }
// unmarshal but not release data // UnmarshalWithOutRelease not release data
func (pbProcessor *PBProcessor) UnmarshalWithOutRelease(clientId string, data []byte) (interface{}, error) { func (pbProcessor *PBProcessor) UnmarshalWithOutRelease(clientId string, data []byte) (interface{}, error) {
var msgType uint16 var msgType uint16
if pbProcessor.LittleEndian == true { if pbProcessor.LittleEndian == true {
@@ -82,7 +83,7 @@ func (pbProcessor *PBProcessor) UnmarshalWithOutRelease(clientId string, data []
info, ok := pbProcessor.mapMsg[msgType] info, ok := pbProcessor.mapMsg[msgType]
if ok == false { if ok == false {
return nil, fmt.Errorf("cannot find register %d msgtype!", msgType) return nil, fmt.Errorf("cannot find register %d msgtype", msgType)
} }
msg := reflect.New(info.msgType.Elem()).Interface() msg := reflect.New(info.msgType.Elem()).Interface()
protoMsg := msg.(proto.Message) protoMsg := msg.(proto.Message)
@@ -91,10 +92,10 @@ func (pbProcessor *PBProcessor) UnmarshalWithOutRelease(clientId string, data []
return nil, err return nil, err
} }
return &PBPackInfo{typ: msgType, msg: protoMsg}, nil return &PBPackInfo{typ: msgType, msg: protoMsg, rawMsg: data}, nil
} }
// must goroutine safe // Marshal must goroutine safe
func (pbProcessor *PBProcessor) Marshal(clientId string, msg interface{}) ([]byte, error) { func (pbProcessor *PBProcessor) Marshal(clientId string, msg interface{}) ([]byte, error) {
pMsg := msg.(*PBPackInfo) pMsg := msg.(*PBPackInfo)
@@ -117,12 +118,12 @@ func (pbProcessor *PBProcessor) Marshal(clientId string, msg interface{}) ([]byt
return buff, nil return buff, nil
} }
func (pbProcessor *PBProcessor) Register(msgtype uint16, msg proto.Message, handle MessageHandler) { func (pbProcessor *PBProcessor) Register(msgType uint16, msg proto.Message, handle MessageHandler) {
var info MessageInfo var info MessageInfo
info.msgType = reflect.TypeOf(msg.(proto.Message)) info.msgType = reflect.TypeOf(msg.(proto.Message))
info.msgHandler = handle info.msgHandler = handle
pbProcessor.mapMsg[msgtype] = info pbProcessor.mapMsg[msgType] = info
} }
func (pbProcessor *PBProcessor) MakeMsg(msgType uint16, protoMsg proto.Message) *PBPackInfo { func (pbProcessor *PBProcessor) MakeMsg(msgType uint16, protoMsg proto.Message) *PBPackInfo {
@@ -133,11 +134,11 @@ func (pbProcessor *PBProcessor) MakeRawMsg(msgType uint16, msg []byte) *PBPackIn
return &PBPackInfo{typ: msgType, rawMsg: msg} return &PBPackInfo{typ: msgType, rawMsg: msg}
} }
func (pbProcessor *PBProcessor) UnknownMsgRoute(clientId string, msg interface{}) { func (pbProcessor *PBProcessor) UnknownMsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) {
pbProcessor.unknownMessageHandler(clientId, msg.([]byte)) pbProcessor.unknownMessageHandler(clientId, msg.([]byte))
recyclerReaderBytes(msg.([]byte))
} }
// connect event
func (pbProcessor *PBProcessor) ConnectedRoute(clientId string) { func (pbProcessor *PBProcessor) ConnectedRoute(clientId string) {
pbProcessor.connectHandler(clientId) pbProcessor.connectHandler(clientId)
} }

View File

@@ -10,21 +10,22 @@ type RawMessageInfo struct {
msgHandler RawMessageHandler msgHandler RawMessageHandler
} }
type RawMessageHandler func(clientId string,packType uint16,msg []byte) type RawMessageHandler func(clientId string, packType uint16, msg []byte)
type RawConnectHandler func(clientId string) type RawConnectHandler func(clientId string)
type UnknownRawMessageHandler func(clientId string,msg []byte) type UnknownRawMessageHandler func(clientId string, msg []byte)
const RawMsgTypeSize = 2 const RawMsgTypeSize = 2
type PBRawProcessor struct { type PBRawProcessor struct {
msgHandler RawMessageHandler msgHandler RawMessageHandler
LittleEndian bool LittleEndian bool
unknownMessageHandler UnknownRawMessageHandler unknownMessageHandler UnknownRawMessageHandler
connectHandler RawConnectHandler connectHandler RawConnectHandler
disconnectHandler RawConnectHandler disconnectHandler RawConnectHandler
} }
type PBRawPackInfo struct { type PBRawPackInfo struct {
typ uint16 typ uint16
rawMsg []byte rawMsg []byte
} }
@@ -37,74 +38,76 @@ func (pbRawProcessor *PBRawProcessor) SetByteOrder(littleEndian bool) {
pbRawProcessor.LittleEndian = littleEndian pbRawProcessor.LittleEndian = littleEndian
} }
// must goroutine safe // MsgRoute must goroutine safe
func (pbRawProcessor *PBRawProcessor ) MsgRoute(clientId string, msg interface{}) error{ func (pbRawProcessor *PBRawProcessor) MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error {
pPackInfo := msg.(*PBRawPackInfo) pPackInfo := msg.(*PBRawPackInfo)
pbRawProcessor.msgHandler(clientId,pPackInfo.typ,pPackInfo.rawMsg) pbRawProcessor.msgHandler(clientId, pPackInfo.typ, pPackInfo.rawMsg)
recyclerReaderBytes(pPackInfo.rawMsg)
return nil return nil
} }
// must goroutine safe // Unmarshal must goroutine safe
func (pbRawProcessor *PBRawProcessor ) Unmarshal(clientId string,data []byte) (interface{}, error) { func (pbRawProcessor *PBRawProcessor) Unmarshal(clientId string, data []byte) (interface{}, error) {
var msgType uint16 var msgType uint16
if pbRawProcessor.LittleEndian == true { if pbRawProcessor.LittleEndian == true {
msgType = binary.LittleEndian.Uint16(data[:2]) msgType = binary.LittleEndian.Uint16(data[:2])
}else{ } else {
msgType = binary.BigEndian.Uint16(data[:2]) msgType = binary.BigEndian.Uint16(data[:2])
} }
return &PBRawPackInfo{typ:msgType,rawMsg:data},nil return &PBRawPackInfo{typ: msgType, rawMsg: data}, nil
} }
// must goroutine safe // Marshal must goroutine safe
func (pbRawProcessor *PBRawProcessor ) Marshal(clientId string,msg interface{}) ([]byte, error){ func (pbRawProcessor *PBRawProcessor) Marshal(clientId string, msg interface{}) ([]byte, error) {
pMsg := msg.(*PBRawPackInfo) pMsg := msg.(*PBRawPackInfo)
buff := make([]byte, 2, len(pMsg.rawMsg)+RawMsgTypeSize) buff := make([]byte, 2, len(pMsg.rawMsg)+RawMsgTypeSize)
if pbRawProcessor.LittleEndian == true { if pbRawProcessor.LittleEndian == true {
binary.LittleEndian.PutUint16(buff[:2],pMsg.typ) binary.LittleEndian.PutUint16(buff[:2], pMsg.typ)
}else{ } else {
binary.BigEndian.PutUint16(buff[:2],pMsg.typ) binary.BigEndian.PutUint16(buff[:2], pMsg.typ)
} }
buff = append(buff,pMsg.rawMsg...) buff = append(buff, pMsg.rawMsg...)
return buff,nil return buff, nil
} }
func (pbRawProcessor *PBRawProcessor) SetRawMsgHandler(handle RawMessageHandler) { func (pbRawProcessor *PBRawProcessor) SetRawMsgHandler(handle RawMessageHandler) {
pbRawProcessor.msgHandler = handle pbRawProcessor.msgHandler = handle
} }
func (pbRawProcessor *PBRawProcessor) MakeRawMsg(msgType uint16,msg []byte,pbRawPackInfo *PBRawPackInfo) { func (pbRawProcessor *PBRawProcessor) MakeRawMsg(msgType uint16, msg []byte, pbRawPackInfo *PBRawPackInfo) {
pbRawPackInfo.typ = msgType pbRawPackInfo.typ = msgType
pbRawPackInfo.rawMsg = msg pbRawPackInfo.rawMsg = msg
} }
func (pbRawProcessor *PBRawProcessor) UnknownMsgRoute(clientId string,msg interface{}){ func (pbRawProcessor *PBRawProcessor) UnknownMsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) {
defer recyclerReaderBytes(msg.([]byte))
if pbRawProcessor.unknownMessageHandler == nil { if pbRawProcessor.unknownMessageHandler == nil {
return return
} }
pbRawProcessor.unknownMessageHandler(clientId,msg.([]byte)) pbRawProcessor.unknownMessageHandler(clientId, msg.([]byte))
} }
// connect event func (pbRawProcessor *PBRawProcessor) ConnectedRoute(clientId string) {
func (pbRawProcessor *PBRawProcessor) ConnectedRoute(clientId string){
pbRawProcessor.connectHandler(clientId) pbRawProcessor.connectHandler(clientId)
} }
func (pbRawProcessor *PBRawProcessor) DisConnectedRoute(clientId string){ func (pbRawProcessor *PBRawProcessor) DisConnectedRoute(clientId string) {
pbRawProcessor.disconnectHandler(clientId) pbRawProcessor.disconnectHandler(clientId)
} }
func (pbRawProcessor *PBRawProcessor) SetUnknownMsgHandler(unknownMessageHandler UnknownRawMessageHandler){ func (pbRawProcessor *PBRawProcessor) SetUnknownMsgHandler(unknownMessageHandler UnknownRawMessageHandler) {
pbRawProcessor.unknownMessageHandler = unknownMessageHandler pbRawProcessor.unknownMessageHandler = unknownMessageHandler
} }
func (pbRawProcessor *PBRawProcessor) SetConnectedHandler(connectHandler RawConnectHandler){ func (pbRawProcessor *PBRawProcessor) SetConnectedHandler(connectHandler RawConnectHandler) {
pbRawProcessor.connectHandler = connectHandler pbRawProcessor.connectHandler = connectHandler
} }
func (pbRawProcessor *PBRawProcessor) SetDisConnectedHandler(disconnectHandler RawConnectHandler){ func (pbRawProcessor *PBRawProcessor) SetDisConnectedHandler(disconnectHandler RawConnectHandler) {
pbRawProcessor.disconnectHandler = disconnectHandler pbRawProcessor.disconnectHandler = disconnectHandler
} }
@@ -116,7 +119,7 @@ func (slf *PBRawPackInfo) GetMsg() []byte {
return slf.rawMsg return slf.rawMsg
} }
func (slf *PBRawPackInfo) SetPackInfo(typ uint16,rawMsg []byte){ func (slf *PBRawPackInfo) SetPackInfo(typ uint16, rawMsg []byte) {
slf.typ = typ slf.typ = typ
slf.rawMsg = rawMsg slf.rawMsg = rawMsg
} }

View File

@@ -1,19 +1,18 @@
package processor package processor
type IProcessor interface { type IProcessor interface {
// must goroutine safe // MsgRoute must goroutine safe
MsgRoute(clientId string,msg interface{}) error MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error
//must goroutine safe // UnknownMsgRoute must goroutine safe
UnknownMsgRoute(clientId string,msg interface{}) UnknownMsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte))
// connect event // ConnectedRoute connect event
ConnectedRoute(clientId string) ConnectedRoute(clientId string)
DisConnectedRoute(clientId string) DisConnectedRoute(clientId string)
// must goroutine safe // Unmarshal must goroutine safe
Unmarshal(clientId string,data []byte) (interface{}, error) Unmarshal(clientId string, data []byte) (interface{}, error)
// must goroutine safe // Marshal must goroutine safe
Marshal(clientId string,msg interface{}) ([]byte, error) Marshal(clientId string, msg interface{}) ([]byte, error)
} }
type IRawProcessor interface { type IRawProcessor interface {
@@ -21,9 +20,8 @@ type IRawProcessor interface {
SetByteOrder(littleEndian bool) SetByteOrder(littleEndian bool)
SetRawMsgHandler(handle RawMessageHandler) SetRawMsgHandler(handle RawMessageHandler)
MakeRawMsg(msgType uint16,msg []byte,pbRawPackInfo *PBRawPackInfo) MakeRawMsg(msgType uint16, msg []byte, pbRawPackInfo *PBRawPackInfo)
SetUnknownMsgHandler(unknownMessageHandler UnknownRawMessageHandler) SetUnknownMsgHandler(unknownMessageHandler UnknownRawMessageHandler)
SetConnectedHandler(connectHandler RawConnectHandler) SetConnectedHandler(connectHandler RawConnectHandler)
SetDisConnectedHandler(disconnectHandler RawConnectHandler) SetDisConnectedHandler(disconnectHandler RawConnectHandler)
} }

View File

@@ -14,9 +14,9 @@ type TCPClient struct {
ConnectInterval time.Duration ConnectInterval time.Duration
PendingWriteNum int PendingWriteNum int
ReadDeadline time.Duration ReadDeadline time.Duration
WriteDeadline time.Duration WriteDeadline time.Duration
AutoReconnect bool AutoReconnect bool
NewAgent func(*TCPConn) Agent NewAgent func(conn *NetConn) Agent
cons ConnSet cons ConnSet
wg sync.WaitGroup wg sync.WaitGroup
closeFlag bool closeFlag bool
@@ -40,23 +40,23 @@ func (client *TCPClient) init() {
if client.ConnNum <= 0 { if client.ConnNum <= 0 {
client.ConnNum = 1 client.ConnNum = 1
log.Info("invalid ConnNum",log.Int("reset", client.ConnNum)) log.Info("invalid ConnNum", log.Int("reset", client.ConnNum))
} }
if client.ConnectInterval <= 0 { if client.ConnectInterval <= 0 {
client.ConnectInterval = 3 * time.Second client.ConnectInterval = 3 * time.Second
log.Info("invalid ConnectInterval",log.Duration("reset", client.ConnectInterval)) log.Info("invalid ConnectInterval", log.Duration("reset", client.ConnectInterval))
} }
if client.PendingWriteNum <= 0 { if client.PendingWriteNum <= 0 {
client.PendingWriteNum = 1000 client.PendingWriteNum = 1000
log.Info("invalid PendingWriteNum",log.Int("reset",client.PendingWriteNum)) log.Info("invalid PendingWriteNum", log.Int("reset", client.PendingWriteNum))
} }
if client.ReadDeadline == 0 { if client.ReadDeadline == 0 {
client.ReadDeadline = 15*time.Second client.ReadDeadline = 15 * time.Second
log.Info("invalid ReadDeadline",log.Int64("reset", int64(client.ReadDeadline.Seconds()))) log.Info("invalid ReadDeadline", log.Int64("reset", int64(client.ReadDeadline.Seconds())))
} }
if client.WriteDeadline == 0 { if client.WriteDeadline == 0 {
client.WriteDeadline = 15*time.Second client.WriteDeadline = 15 * time.Second
log.Info("invalid WriteDeadline",log.Int64("reset", int64(client.WriteDeadline.Seconds()))) log.Info("invalid WriteDeadline", log.Int64("reset", int64(client.WriteDeadline.Seconds())))
} }
if client.NewAgent == nil { if client.NewAgent == nil {
log.Fatal("NewAgent must not be nil") log.Fatal("NewAgent must not be nil")
@@ -71,21 +71,21 @@ func (client *TCPClient) init() {
if client.MaxMsgLen == 0 { if client.MaxMsgLen == 0 {
client.MaxMsgLen = Default_MaxMsgLen client.MaxMsgLen = Default_MaxMsgLen
} }
if client.LenMsgLen ==0 { if client.LenMsgLen == 0 {
client.LenMsgLen = Default_LenMsgLen client.LenMsgLen = Default_LenMsgLen
} }
maxMsgLen := client.MsgParser.getMaxMsgLen(client.LenMsgLen) maxMsgLen := client.MsgParser.getMaxMsgLen()
if client.MaxMsgLen > maxMsgLen { if client.MaxMsgLen > maxMsgLen {
client.MaxMsgLen = maxMsgLen client.MaxMsgLen = maxMsgLen
log.Info("invalid MaxMsgLen",log.Uint32("reset", maxMsgLen)) log.Info("invalid MaxMsgLen", log.Uint32("reset", maxMsgLen))
} }
client.cons = make(ConnSet) client.cons = make(ConnSet)
client.closeFlag = false client.closeFlag = false
client.MsgParser.init() client.MsgParser.Init()
} }
func (client *TCPClient) GetCloseFlag() bool{ func (client *TCPClient) GetCloseFlag() bool {
client.Lock() client.Lock()
defer client.Unlock() defer client.Unlock()
@@ -102,7 +102,7 @@ func (client *TCPClient) dial() net.Conn {
return conn return conn
} }
log.Warning("connect error ",log.String("error",err.Error()), log.String("Addr",client.Addr)) log.Warn("connect error ", log.String("error", err.Error()), log.String("Addr", client.Addr))
time.Sleep(client.ConnectInterval) time.Sleep(client.ConnectInterval)
continue continue
} }
@@ -116,7 +116,7 @@ reconnect:
if conn == nil { if conn == nil {
return return
} }
client.Lock() client.Lock()
if client.closeFlag { if client.closeFlag {
client.Unlock() client.Unlock()
@@ -126,7 +126,7 @@ reconnect:
client.cons[conn] = struct{}{} client.cons[conn] = struct{}{}
client.Unlock() client.Unlock()
tcpConn := newTCPConn(conn, client.PendingWriteNum, &client.MsgParser,client.WriteDeadline) tcpConn := newNetConn(conn, client.PendingWriteNum, &client.MsgParser, client.WriteDeadline)
agent := client.NewAgent(tcpConn) agent := client.NewAgent(tcpConn)
agent.Run() agent.Run()
@@ -152,8 +152,7 @@ func (client *TCPClient) Close(waitDone bool) {
client.cons = nil client.cons = nil
client.Unlock() client.Unlock()
if waitDone == true{ if waitDone == true {
client.wg.Wait() client.wg.Wait()
} }
} }

View File

@@ -1,162 +0,0 @@
package network
import (
"errors"
"github.com/duanhf2012/origin/v2/log"
"net"
"sync"
"sync/atomic"
"time"
)
type ConnSet map[net.Conn]struct{}
type TCPConn struct {
sync.Mutex
conn net.Conn
writeChan chan []byte
closeFlag int32
msgParser *MsgParser
}
func freeChannel(conn *TCPConn){
for;len(conn.writeChan)>0;{
byteBuff := <- conn.writeChan
if byteBuff != nil {
conn.ReleaseReadMsg(byteBuff)
}
}
}
func newTCPConn(conn net.Conn, pendingWriteNum int, msgParser *MsgParser,writeDeadline time.Duration) *TCPConn {
tcpConn := new(TCPConn)
tcpConn.conn = conn
tcpConn.writeChan = make(chan []byte, pendingWriteNum)
tcpConn.msgParser = msgParser
go func() {
for b := range tcpConn.writeChan {
if b == nil {
break
}
conn.SetWriteDeadline(time.Now().Add(writeDeadline))
_, err := conn.Write(b)
tcpConn.msgParser.ReleaseBytes(b)
if err != nil {
break
}
}
conn.Close()
tcpConn.Lock()
freeChannel(tcpConn)
atomic.StoreInt32(&tcpConn.closeFlag,1)
tcpConn.Unlock()
}()
return tcpConn
}
func (tcpConn *TCPConn) doDestroy() {
tcpConn.conn.(*net.TCPConn).SetLinger(0)
tcpConn.conn.Close()
if atomic.LoadInt32(&tcpConn.closeFlag)==0 {
close(tcpConn.writeChan)
atomic.StoreInt32(&tcpConn.closeFlag,1)
}
}
func (tcpConn *TCPConn) Destroy() {
tcpConn.Lock()
defer tcpConn.Unlock()
tcpConn.doDestroy()
}
func (tcpConn *TCPConn) Close() {
tcpConn.Lock()
defer tcpConn.Unlock()
if atomic.LoadInt32(&tcpConn.closeFlag)==1 {
return
}
tcpConn.doWrite(nil)
atomic.StoreInt32(&tcpConn.closeFlag,1)
}
func (tcpConn *TCPConn) GetRemoteIp() string {
return tcpConn.conn.RemoteAddr().String()
}
func (tcpConn *TCPConn) doWrite(b []byte) error{
if len(tcpConn.writeChan) == cap(tcpConn.writeChan) {
tcpConn.ReleaseReadMsg(b)
log.Error("close conn: channel full")
tcpConn.doDestroy()
return errors.New("close conn: channel full")
}
tcpConn.writeChan <- b
return nil
}
// b must not be modified by the others goroutines
func (tcpConn *TCPConn) Write(b []byte) error{
tcpConn.Lock()
defer tcpConn.Unlock()
if atomic.LoadInt32(&tcpConn.closeFlag)==1 || b == nil {
tcpConn.ReleaseReadMsg(b)
return errors.New("conn is close")
}
return tcpConn.doWrite(b)
}
func (tcpConn *TCPConn) Read(b []byte) (int, error) {
return tcpConn.conn.Read(b)
}
func (tcpConn *TCPConn) LocalAddr() net.Addr {
return tcpConn.conn.LocalAddr()
}
func (tcpConn *TCPConn) RemoteAddr() net.Addr {
return tcpConn.conn.RemoteAddr()
}
func (tcpConn *TCPConn) ReadMsg() ([]byte, error) {
return tcpConn.msgParser.Read(tcpConn)
}
func (tcpConn *TCPConn) ReleaseReadMsg(byteBuff []byte){
tcpConn.msgParser.ReleaseBytes(byteBuff)
}
func (tcpConn *TCPConn) WriteMsg(args ...[]byte) error {
if atomic.LoadInt32(&tcpConn.closeFlag) == 1 {
return errors.New("conn is close")
}
return tcpConn.msgParser.Write(tcpConn, args...)
}
func (tcpConn *TCPConn) WriteRawMsg(args []byte) error {
if atomic.LoadInt32(&tcpConn.closeFlag) == 1 {
return errors.New("conn is close")
}
return tcpConn.Write(args)
}
func (tcpConn *TCPConn) IsConnected() bool {
return atomic.LoadInt32(&tcpConn.closeFlag) == 0
}
func (tcpConn *TCPConn) SetReadDeadline(d time.Duration) {
tcpConn.conn.SetReadDeadline(time.Now().Add(d))
}
func (tcpConn *TCPConn) SetWriteDeadline(d time.Duration) {
tcpConn.conn.SetWriteDeadline(time.Now().Add(d))
}

View File

@@ -8,7 +8,7 @@ import (
"math" "math"
) )
// -------------- // MsgParser --------------
// | len | data | // | len | data |
// -------------- // --------------
type MsgParser struct { type MsgParser struct {
@@ -17,11 +17,10 @@ type MsgParser struct {
MaxMsgLen uint32 MaxMsgLen uint32
LittleEndian bool LittleEndian bool
bytespool.IBytesMempool bytespool.IBytesMemPool
} }
func (p *MsgParser) getMaxMsgLen() uint32 {
func (p *MsgParser) getMaxMsgLen(lenMsgLen int) uint32 {
switch p.LenMsgLen { switch p.LenMsgLen {
case 1: case 1:
return math.MaxUint8 return math.MaxUint8
@@ -34,17 +33,17 @@ func (p *MsgParser) getMaxMsgLen(lenMsgLen int) uint32 {
} }
} }
func (p *MsgParser) init(){ func (p *MsgParser) Init() {
p.IBytesMempool = bytespool.NewMemAreaPool() p.IBytesMemPool = bytespool.NewMemAreaPool()
} }
// goroutine safe // goroutine safe
func (p *MsgParser) Read(conn *TCPConn) ([]byte, error) { func (p *MsgParser) Read(r io.Reader) ([]byte, error) {
var b [4]byte var b [4]byte
bufMsgLen := b[:p.LenMsgLen] bufMsgLen := b[:p.LenMsgLen]
// read len // read len
if _, err := io.ReadFull(conn, bufMsgLen); err != nil { if _, err := io.ReadFull(r, bufMsgLen); err != nil {
return nil, err return nil, err
} }
@@ -73,10 +72,10 @@ func (p *MsgParser) Read(conn *TCPConn) ([]byte, error) {
} else if msgLen < p.MinMsgLen { } else if msgLen < p.MinMsgLen {
return nil, errors.New("message too short") return nil, errors.New("message too short")
} }
// data // data
msgData := p.MakeBytes(int(msgLen)) msgData := p.MakeBytes(int(msgLen))
if _, err := io.ReadFull(conn, msgData[:msgLen]); err != nil { if _, err := io.ReadFull(r, msgData[:msgLen]); err != nil {
p.ReleaseBytes(msgData) p.ReleaseBytes(msgData)
return nil, err return nil, err
} }
@@ -85,7 +84,7 @@ func (p *MsgParser) Read(conn *TCPConn) ([]byte, error) {
} }
// goroutine safe // goroutine safe
func (p *MsgParser) Write(conn *TCPConn, args ...[]byte) error { func (p *MsgParser) Write(conn io.Writer, args ...[]byte) error {
// get len // get len
var msgLen uint32 var msgLen uint32
for i := 0; i < len(args); i++ { for i := 0; i < len(args); i++ {
@@ -100,7 +99,7 @@ func (p *MsgParser) Write(conn *TCPConn, args ...[]byte) error {
} }
//msg := make([]byte, uint32(p.lenMsgLen)+msgLen) //msg := make([]byte, uint32(p.lenMsgLen)+msgLen)
msg := p.MakeBytes(p.LenMsgLen+int(msgLen)) msg := p.MakeBytes(p.LenMsgLen + int(msgLen))
// write len // write len
switch p.LenMsgLen { switch p.LenMsgLen {
case 1: case 1:
@@ -130,3 +129,9 @@ func (p *MsgParser) Write(conn *TCPConn, args ...[]byte) error {
return nil return nil
} }
func (p *MsgParser) GetRecyclerReaderBytes() func(data []byte) {
return func(data []byte) {
p.IBytesMemPool.ReleaseBytes(data)
}
}

View File

@@ -1,24 +1,23 @@
package network package network
import ( import (
"errors"
"fmt"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/util/bytespool" "github.com/duanhf2012/origin/v2/util/bytespool"
"net" "net"
"sync" "sync"
"time" "time"
"fmt"
"errors"
) )
const( const (
Default_ReadDeadline = time.Second*30 //默认读超时30s Default_ReadDeadline = time.Second * 30 //默认读超时30s
Default_WriteDeadline = time.Second*30 //默认写超时30s Default_WriteDeadline = time.Second * 30 //默认写超时30s
Default_MaxConnNum = 1000000 //默认最大连接数 Default_MaxConnNum = 1000000 //默认最大连接数
Default_PendingWriteNum = 100000 //单连接写消息Channel容量 Default_PendingWriteNum = 100000 //单连接写消息Channel容量
Default_LittleEndian = false //默认大小端 Default_MinMsgLen = 2 //最小消息长度2byte
Default_MinMsgLen = 2 //最小消息长度2byte Default_LenMsgLen = 2 //包头字段长度占用2byte
Default_LenMsgLen = 2 //包头字段长度占用2byte Default_MaxMsgLen = 65535 //最大消息长度
Default_MaxMsgLen = 65535 //最大消息长度
) )
type TCPServer struct { type TCPServer struct {
@@ -26,42 +25,44 @@ type TCPServer struct {
MaxConnNum int MaxConnNum int
PendingWriteNum int PendingWriteNum int
ReadDeadline time.Duration ReadDeadline time.Duration
WriteDeadline time.Duration WriteDeadline time.Duration
NewAgent func(*TCPConn) Agent NewAgent func(conn Conn) Agent
ln net.Listener ln net.Listener
conns ConnSet conns ConnSet
mutexConns sync.Mutex mutexConns sync.Mutex
wgLn sync.WaitGroup wgLn sync.WaitGroup
wgConns sync.WaitGroup wgConns sync.WaitGroup
MsgParser MsgParser
} }
func (server *TCPServer) Start() error{ func (server *TCPServer) Start() error {
err := server.init() err := server.init()
if err != nil { if err != nil {
return err return err
} }
server.wgLn.Add(1)
go server.run() go server.run()
return nil return nil
} }
func (server *TCPServer) init() error{ func (server *TCPServer) init() error {
ln, err := net.Listen("tcp", server.Addr) ln, err := net.Listen("tcp", server.Addr)
if err != nil { if err != nil {
return fmt.Errorf("Listen tcp fail,error:%s",err.Error()) return fmt.Errorf("listen tcp fail,error:%s", err.Error())
} }
if server.MaxConnNum <= 0 { if server.MaxConnNum <= 0 {
server.MaxConnNum = Default_MaxConnNum server.MaxConnNum = Default_MaxConnNum
log.Info("invalid MaxConnNum",log.Int("reset", server.MaxConnNum)) log.Info("invalid MaxConnNum", log.Int("reset", server.MaxConnNum))
} }
if server.PendingWriteNum <= 0 { if server.PendingWriteNum <= 0 {
server.PendingWriteNum = Default_PendingWriteNum server.PendingWriteNum = Default_PendingWriteNum
log.Info("invalid PendingWriteNum",log.Int("reset", server.PendingWriteNum)) log.Info("invalid PendingWriteNum", log.Int("reset", server.PendingWriteNum))
} }
if server.LenMsgLen <= 0 { if server.LenMsgLen <= 0 {
@@ -74,25 +75,25 @@ func (server *TCPServer) init() error{
log.Info("invalid MaxMsgLen", log.Uint32("reset to", server.MaxMsgLen)) log.Info("invalid MaxMsgLen", log.Uint32("reset to", server.MaxMsgLen))
} }
maxMsgLen := server.MsgParser.getMaxMsgLen(server.LenMsgLen) maxMsgLen := server.MsgParser.getMaxMsgLen()
if server.MaxMsgLen > maxMsgLen { if server.MaxMsgLen > maxMsgLen {
server.MaxMsgLen = maxMsgLen server.MaxMsgLen = maxMsgLen
log.Info("invalid MaxMsgLen",log.Uint32("reset", maxMsgLen)) log.Info("invalid MaxMsgLen", log.Uint32("reset", maxMsgLen))
} }
if server.MinMsgLen <= 0 { if server.MinMsgLen <= 0 {
server.MinMsgLen = Default_MinMsgLen server.MinMsgLen = Default_MinMsgLen
log.Info("invalid MinMsgLen",log.Uint32("reset", server.MinMsgLen)) log.Info("invalid MinMsgLen", log.Uint32("reset", server.MinMsgLen))
} }
if server.WriteDeadline == 0 { if server.WriteDeadline == 0 {
server.WriteDeadline = Default_WriteDeadline server.WriteDeadline = Default_WriteDeadline
log.Info("invalid WriteDeadline",log.Int64("reset",int64(server.WriteDeadline.Seconds()))) log.Info("invalid WriteDeadline", log.Int64("reset", int64(server.WriteDeadline.Seconds())))
} }
if server.ReadDeadline == 0 { if server.ReadDeadline == 0 {
server.ReadDeadline = Default_ReadDeadline server.ReadDeadline = Default_ReadDeadline
log.Info("invalid ReadDeadline",log.Int64("reset", int64(server.ReadDeadline.Seconds()))) log.Info("invalid ReadDeadline", log.Int64("reset", int64(server.ReadDeadline.Seconds())))
} }
if server.NewAgent == nil { if server.NewAgent == nil {
@@ -100,44 +101,44 @@ func (server *TCPServer) init() error{
} }
server.ln = ln server.ln = ln
server.conns = make(ConnSet) server.conns = make(ConnSet, 2048)
server.MsgParser.init() server.MsgParser.Init()
return nil return nil
} }
func (server *TCPServer) SetNetMempool(mempool bytespool.IBytesMempool){ func (server *TCPServer) SetNetMemPool(memPool bytespool.IBytesMemPool) {
server.IBytesMempool = mempool server.IBytesMemPool = memPool
} }
func (server *TCPServer) GetNetMempool() bytespool.IBytesMempool { func (server *TCPServer) GetNetMemPool() bytespool.IBytesMemPool {
return server.IBytesMempool return server.IBytesMemPool
} }
func (server *TCPServer) run() { func (server *TCPServer) run() {
server.wgLn.Add(1)
defer server.wgLn.Done() defer server.wgLn.Done()
var tempDelay time.Duration var tempDelay time.Duration
for { for {
conn, err := server.ln.Accept() conn, err := server.ln.Accept()
if err != nil { if err != nil {
if ne, ok := err.(net.Error); ok && ne.Temporary() { var ne net.Error
if errors.As(err, &ne) && ne.Timeout() {
if tempDelay == 0 { if tempDelay == 0 {
tempDelay = 5 * time.Millisecond tempDelay = 5 * time.Millisecond
} else { } else {
tempDelay *= 2 tempDelay *= 2
} }
if max := 1 * time.Second; tempDelay > max {
tempDelay = max log.Info("accept fail", log.String("error", err.Error()), log.Duration("sleep time", tempDelay))
} tempDelay = min(1*time.Second, tempDelay)
log.Info("accept fail",log.String("error",err.Error()),log.Duration("sleep time", tempDelay))
time.Sleep(tempDelay) time.Sleep(tempDelay)
continue continue
} }
return return
} }
conn.(*net.TCPConn).SetLinger(0)
conn.(*net.TCPConn).SetNoDelay(true) conn.(*net.TCPConn).SetNoDelay(true)
tempDelay = 0 tempDelay = 0
@@ -145,7 +146,7 @@ func (server *TCPServer) run() {
if len(server.conns) >= server.MaxConnNum { if len(server.conns) >= server.MaxConnNum {
server.mutexConns.Unlock() server.mutexConns.Unlock()
conn.Close() conn.Close()
log.Warning("too many connections") log.Warn("too many connections")
continue continue
} }
@@ -153,7 +154,7 @@ func (server *TCPServer) run() {
server.mutexConns.Unlock() server.mutexConns.Unlock()
server.wgConns.Add(1) server.wgConns.Add(1)
tcpConn := newTCPConn(conn, server.PendingWriteNum, &server.MsgParser,server.WriteDeadline) tcpConn := newNetConn(conn, server.PendingWriteNum, &server.MsgParser, server.WriteDeadline)
agent := server.NewAgent(tcpConn) agent := server.NewAgent(tcpConn)
go func() { go func() {

View File

@@ -108,7 +108,7 @@ reconnect:
client.cons[conn] = struct{}{} client.cons[conn] = struct{}{}
client.Unlock() client.Unlock()
wsConn := newWSConn(conn, client.PendingWriteNum, client.MaxMsgLen,client.MessageType) wsConn := newWSConn(conn,nil, client.PendingWriteNum, client.MaxMsgLen,client.MessageType)
agent := client.NewAgent(wsConn) agent := client.NewAgent(wsConn)
agent.Run() agent.Run()

View File

@@ -5,6 +5,7 @@ import (
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"net" "net"
"net/http"
"sync" "sync"
) )
@@ -16,13 +17,15 @@ type WSConn struct {
writeChan chan []byte writeChan chan []byte
maxMsgLen uint32 maxMsgLen uint32
closeFlag bool closeFlag bool
header http.Header
} }
func newWSConn(conn *websocket.Conn, pendingWriteNum int, maxMsgLen uint32,messageType int) *WSConn { func newWSConn(conn *websocket.Conn, header http.Header, pendingWriteNum int, maxMsgLen uint32, messageType int) *WSConn {
wsConn := new(WSConn) wsConn := new(WSConn)
wsConn.conn = conn wsConn.conn = conn
wsConn.writeChan = make(chan []byte, pendingWriteNum) wsConn.writeChan = make(chan []byte, pendingWriteNum)
wsConn.maxMsgLen = maxMsgLen wsConn.maxMsgLen = maxMsgLen
wsConn.header = header
go func() { go func() {
for b := range wsConn.writeChan { for b := range wsConn.writeChan {
@@ -46,7 +49,6 @@ func newWSConn(conn *websocket.Conn, pendingWriteNum int, maxMsgLen uint32,messa
} }
func (wsConn *WSConn) doDestroy() { func (wsConn *WSConn) doDestroy() {
wsConn.conn.UnderlyingConn().(*net.TCPConn).SetLinger(0)
wsConn.conn.Close() wsConn.conn.Close()
if !wsConn.closeFlag { if !wsConn.closeFlag {
@@ -83,6 +85,10 @@ func (wsConn *WSConn) doWrite(b []byte) {
wsConn.writeChan <- b wsConn.writeChan <- b
} }
func (wsConn *WSConn) GetHeader() http.Header {
return wsConn.header
}
func (wsConn *WSConn) LocalAddr() net.Addr { func (wsConn *WSConn) LocalAddr() net.Addr {
return wsConn.conn.LocalAddr() return wsConn.conn.LocalAddr()
} }
@@ -91,13 +97,13 @@ func (wsConn *WSConn) RemoteAddr() net.Addr {
return wsConn.conn.RemoteAddr() return wsConn.conn.RemoteAddr()
} }
// goroutine not safe // ReadMsg goroutine not safe
func (wsConn *WSConn) ReadMsg() ([]byte, error) { func (wsConn *WSConn) ReadMsg() ([]byte, error) {
_, b, err := wsConn.conn.ReadMessage() _, b, err := wsConn.conn.ReadMessage()
return b, err return b, err
} }
// args must not be modified by the others goroutines // WriteMsg args must not be modified by the others goroutines
func (wsConn *WSConn) WriteMsg(args ...[]byte) error { func (wsConn *WSConn) WriteMsg(args ...[]byte) error {
wsConn.Lock() wsConn.Lock()
defer wsConn.Unlock() defer wsConn.Unlock()

View File

@@ -2,6 +2,7 @@ package network
import ( import (
"crypto/tls" "crypto/tls"
"errors"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"net" "net"
@@ -47,7 +48,7 @@ func (handler *WSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} }
conn, err := handler.upgrader.Upgrade(w, r, nil) conn, err := handler.upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
log.Error("upgrade fail",log.String("error",err.Error())) log.Error("upgrade fail", log.String("error", err.Error()))
return return
} }
conn.SetReadLimit(int64(handler.maxMsgLen)) conn.SetReadLimit(int64(handler.maxMsgLen))
@@ -67,13 +68,28 @@ func (handler *WSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if len(handler.conns) >= handler.maxConnNum { if len(handler.conns) >= handler.maxConnNum {
handler.mutexConns.Unlock() handler.mutexConns.Unlock()
conn.Close() conn.Close()
log.Warning("too many connections") log.Warn("too many connections")
return return
} }
handler.conns[conn] = struct{}{} handler.conns[conn] = struct{}{}
handler.mutexConns.Unlock() handler.mutexConns.Unlock()
c,ok:=conn.NetConn().(*net.TCPConn)
if !ok {
tlsConn,ok := conn.NetConn().(*tls.Conn)
if !ok {
log.Error("conn error")
return
}
c,ok = tlsConn.NetConn().(*net.TCPConn)
if !ok {
log.Error("conn error")
return
}
}
wsConn := newWSConn(conn, handler.pendingWriteNum, handler.maxMsgLen, handler.messageType) c.SetLinger(0)
c.SetNoDelay(true)
wsConn := newWSConn(conn, r.Header, handler.pendingWriteNum, handler.maxMsgLen, handler.messageType)
agent := handler.newAgent(wsConn) agent := handler.newAgent(wsConn)
agent.Run() agent.Run()
@@ -92,10 +108,11 @@ func (server *WSServer) SetMessageType(messageType int) {
} }
} }
func (server *WSServer) Start() { func (server *WSServer) Start() error {
ln, err := net.Listen("tcp", server.Addr) ln, err := net.Listen("tcp", server.Addr)
if err != nil { if err != nil {
log.Fatal("WSServer Listen fail",log.String("error", err.Error())) log.Error("WSServer Listen fail", log.String("error", err.Error()))
return err
} }
if server.MaxConnNum <= 0 { if server.MaxConnNum <= 0 {
@@ -115,18 +132,19 @@ func (server *WSServer) Start() {
log.Info("invalid HTTPTimeout", log.Duration("reset", server.HTTPTimeout)) log.Info("invalid HTTPTimeout", log.Duration("reset", server.HTTPTimeout))
} }
if server.NewAgent == nil { if server.NewAgent == nil {
log.Fatal("NewAgent must not be nil") log.Error("NewAgent must not be nil")
return errors.New("NewAgent must not be nil")
} }
if server.CertFile != "" || server.KeyFile != "" { if server.CertFile != "" || server.KeyFile != "" {
config := &tls.Config{} config := &tls.Config{}
config.NextProtos = []string{"http/1.1"} config.NextProtos = []string{"http/1.1"}
var err error
config.Certificates = make([]tls.Certificate, 1) config.Certificates = make([]tls.Certificate, 1)
config.Certificates[0], err = tls.LoadX509KeyPair(server.CertFile, server.KeyFile) config.Certificates[0], err = tls.LoadX509KeyPair(server.CertFile, server.KeyFile)
if err != nil { if err != nil {
log.Fatal("LoadX509KeyPair fail",log.String("error", err.Error())) log.Error("LoadX509KeyPair fail", log.String("error", err.Error()))
return err
} }
ln = tls.NewListener(ln, config) ln = tls.NewListener(ln, config)
@@ -139,7 +157,7 @@ func (server *WSServer) Start() {
maxMsgLen: server.MaxMsgLen, maxMsgLen: server.MaxMsgLen,
newAgent: server.NewAgent, newAgent: server.NewAgent,
conns: make(WebsocketConnSet), conns: make(WebsocketConnSet),
messageType:server.messageType, messageType: server.messageType,
upgrader: websocket.Upgrader{ upgrader: websocket.Upgrader{
HandshakeTimeout: server.HTTPTimeout, HandshakeTimeout: server.HTTPTimeout,
CheckOrigin: func(_ *http.Request) bool { return true }, CheckOrigin: func(_ *http.Request) bool { return true },
@@ -155,6 +173,7 @@ func (server *WSServer) Start() {
} }
go httpServer.Serve(ln) go httpServer.Serve(ln)
return nil
} }
func (server *WSServer) Close() { func (server *WSServer) Close() {

View File

@@ -9,7 +9,9 @@ import (
"github.com/duanhf2012/origin/v2/profiler" "github.com/duanhf2012/origin/v2/profiler"
"github.com/duanhf2012/origin/v2/service" "github.com/duanhf2012/origin/v2/service"
"github.com/duanhf2012/origin/v2/util/buildtime" "github.com/duanhf2012/origin/v2/util/buildtime"
"github.com/duanhf2012/origin/v2/util/sysprocess"
"github.com/duanhf2012/origin/v2/util/timer" "github.com/duanhf2012/origin/v2/util/timer"
"go.uber.org/zap/zapcore"
"io" "io"
"net/http" "net/http"
_ "net/http/pprof" _ "net/http/pprof"
@@ -19,32 +21,32 @@ import (
"strings" "strings"
"syscall" "syscall"
"time" "time"
"github.com/duanhf2012/origin/v2/util/sysprocess"
) )
var sig chan os.Signal var sig chan os.Signal
var nodeId string var nodeId string
var preSetupService []service.IService //预安装 var preSetupService []service.IService //预安装
var preSetupTemplateService []func() service.IService
var profilerInterval time.Duration var profilerInterval time.Duration
var bValid bool
var configDir = "./config/" var configDir = "./config/"
var NodeIsRun = false
const( const (
SingleStop syscall.Signal = 10 SingleStop syscall.Signal = 10
SignalRetire syscall.Signal = 12 SignalRetire syscall.Signal = 12
) )
type BuildOSType = int8 type BuildOSType = int8
const( const (
Windows BuildOSType = 0 Windows BuildOSType = 0
Linux BuildOSType = 1 Linux BuildOSType = 1
Mac BuildOSType = 2 Mac BuildOSType = 2
) )
func init() { func init() {
sig = make(chan os.Signal, 4) sig = make(chan os.Signal, 4)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM, SingleStop,SignalRetire) signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM, SingleStop, SignalRetire)
console.RegisterCommandBool("help", false, "<-help> This help.", usage) console.RegisterCommandBool("help", false, "<-help> This help.", usage)
console.RegisterCommandString("name", "", "<-name nodeName> Node's name.", setName) console.RegisterCommandString("name", "", "<-name nodeName> Node's name.", setName)
@@ -53,15 +55,14 @@ func init() {
console.RegisterCommandString("retire", "", "<-retire nodeid=nodeid> retire originserver process.", retireNode) console.RegisterCommandString("retire", "", "<-retire nodeid=nodeid> retire originserver process.", retireNode)
console.RegisterCommandString("config", "", "<-config path> Configuration file path.", setConfigPath) console.RegisterCommandString("config", "", "<-config path> Configuration file path.", setConfigPath)
console.RegisterCommandString("console", "", "<-console true|false> Turn on or off screen log output.", openConsole) console.RegisterCommandString("console", "", "<-console true|false> Turn on or off screen log output.", openConsole)
console.RegisterCommandString("loglevel", "debug", "<-loglevel debug|release|warning|error|fatal> Set loglevel.", setLevel) console.RegisterCommandString("loglevel", "debug", "<-loglevel debug|info|warn|error|stackerror|fatal> Set loglevel.", setLevel)
console.RegisterCommandString("logpath", "", "<-logpath path> Set log file path.", setLogPath) console.RegisterCommandString("logpath", "", "<-logpath path> Set log file path.", setLogPath)
console.RegisterCommandInt("logsize", 0, "<-logsize size> Set log size(MB).", setLogSize) console.RegisterCommandInt("logsize", 0, "<-logsize size> Set log size(MB).", setLogSize)
console.RegisterCommandInt("logchannelcap", 0, "<-logchannelcap num> Set log channel cap.", setLogChannelCapNum) console.RegisterCommandInt("logchanlen", 0, "<-logchanlen len> Set log channel len.", setLogChanLen)
console.RegisterCommandString("pprof", "", "<-pprof ip:port> Open performance analysis.", setPprof) console.RegisterCommandString("pprof", "", "<-pprof ip:port> Open performance analysis.", setPprof)
} }
func notifyAllServiceRetire() {
func notifyAllServiceRetire(){
service.NotifyAllServiceRetire() service.NotifyAllServiceRetire()
} }
@@ -81,7 +82,7 @@ func usage(val interface{}) error {
return nil return nil
} }
func setName(val interface{}) error { func setName(_ interface{}) error {
return nil return nil
} }
@@ -108,7 +109,7 @@ func setConfigPath(val interface{}) error {
} }
_, err := os.Stat(configPath) _, err := os.Stat(configPath)
if err != nil { if err != nil {
return fmt.Errorf("Cannot find file path %s", configPath) return fmt.Errorf("cannot find file path %s", configPath)
} }
cluster.SetConfigDir(configPath) cluster.SetConfigDir(configPath)
@@ -156,19 +157,46 @@ func initNode(id string) {
nodeId = id nodeId = id
err := cluster.GetCluster().Init(GetNodeId(), Setup) err := cluster.GetCluster().Init(GetNodeId(), Setup)
if err != nil { if err != nil {
log.Error("Init cluster fail",log.ErrorAttr("error",err)) log.Error("Init cluster fail", log.ErrorField("error", err))
os.Exit(1) os.Exit(1)
} }
err = initLog() err = initLog()
if err != nil { if err != nil {
log.Error("Init log fail", log.ErrorField("error", err))
os.Exit(1)
return return
} }
//2.顺序安装服务 //2.顺序安装服务
serviceOrder := cluster.GetCluster().GetLocalNodeInfo().ServiceList serviceOrder := cluster.GetCluster().GetLocalNodeInfo().ServiceList
for _,serviceName:= range serviceOrder{ for _, serviceName := range serviceOrder {
bSetup := false bSetup := false
//判断是否有配置模板服务
splitServiceName := strings.Split(serviceName, ":")
if len(splitServiceName) == 2 {
serviceName = splitServiceName[0]
templateServiceName := splitServiceName[1]
for _, newSer := range preSetupTemplateService {
ser := newSer()
ser.OnSetup(ser)
if ser.GetName() == templateServiceName {
ser.SetName(serviceName)
ser.Init(ser, cluster.GetRpcClient, cluster.GetRpcServer, cluster.GetCluster().GetServiceCfg(ser.GetName()))
service.Setup(ser)
bSetup = true
break
}
}
if bSetup == false {
log.Error("Template service not found", log.String("service name", serviceName), log.String("template service name", templateServiceName))
os.Exit(1)
}
}
for _, s := range preSetupService { for _, s := range preSetupService {
if s.GetName() != serviceName { if s.GetName() != serviceName {
continue continue
@@ -181,27 +209,29 @@ func initNode(id string) {
} }
if bSetup == false { if bSetup == false {
log.Fatal("Service name "+serviceName+" configuration error") log.Fatal("Service name " + serviceName + " configuration error")
} }
} }
//3.service初始化 //3.service初始化
log.Info("Start running server.")
service.Init() service.Init()
} }
func initLog() error { func initLog() error {
logger := log.GetLogger()
if log.LogPath == "" { if log.LogPath == "" {
setLogPath("./log") err := setLogPath("./log")
if err != nil {
return err
}
} }
localnodeinfo := cluster.GetCluster().GetLocalNodeInfo() localNodeInfo := cluster.GetCluster().GetLocalNodeInfo()
filepre := fmt.Sprintf("%s_", localnodeinfo.NodeId) fileName := fmt.Sprintf("%s.log", localNodeInfo.NodeId)
logger, err := log.NewTextLogger(log.LogLevel,log.LogPath,filepre,true,log.LogChannelCap) logger.FileName = fileName
if err != nil {
fmt.Printf("cannot create log file!\n") logger.Init()
return err
}
log.SetLogger(logger)
return nil return nil
} }
@@ -213,7 +243,6 @@ func Start() {
} }
} }
func retireNode(args interface{}) error { func retireNode(args interface{}) error {
//1.解析参数 //1.解析参数
param := args.(string) param := args.(string)
@@ -238,12 +267,10 @@ func retireNode(args interface{}) error {
return err return err
} }
RetireProcess(processId) RetireProcess(processId)
return nil return nil
} }
func stopNode(args interface{}) error { func stopNode(args interface{}) error {
//1.解析参数 //1.解析参数
param := args.(string) param := args.(string)
@@ -291,7 +318,7 @@ func startNode(args interface{}) error {
return fmt.Errorf("invalid option %s", param) return fmt.Errorf("invalid option %s", param)
} }
for{ for {
processId, pErr := getRunProcessPid(strNodeId) processId, pErr := getRunProcessPid(strNodeId)
if pErr != nil { if pErr != nil {
break break
@@ -301,48 +328,52 @@ func startNode(args interface{}) error {
myName, mErr := sysprocess.GetMyProcessName() myName, mErr := sysprocess.GetMyProcessName()
//当前进程名获取失败,不应该发生 //当前进程名获取失败,不应该发生
if mErr != nil { if mErr != nil {
log.SInfo("get my process's name is error,", mErr.Error()) log.Error("get my process's name is error", log.ErrorField("err", mErr))
os.Exit(-1) os.Exit(-1)
} }
//进程id存在而且进程名也相同被认为是当前进程重复运行 //进程id存在而且进程名也相同被认为是当前进程重复运行
if cErr == nil && name == myName { if cErr == nil && name == myName {
log.SInfo(fmt.Sprintf("repeat runs are not allowed,node is %s,processid is %d",strNodeId,processId)) log.Error("repeat runs are not allowed", log.String("nodeId", strNodeId), log.Int("processId", processId))
os.Exit(-1) os.Exit(-1)
} }
break break
} }
//2.记录进程id号 //2.记录进程id号
log.Info("Start running server.")
writeProcessPid(strNodeId) writeProcessPid(strNodeId)
timer.StartTimer(10*time.Millisecond, 1000000) timer.StartTimer(10*time.Millisecond, 1000000)
//3.初始化node //3.初始化node
defer log.GetLogger().Logger.Sync()
initNode(strNodeId) initNode(strNodeId)
//4.运行service //4.运行service
service.Start() service.Start()
//5.运行集群 //5.运行集群
cluster.GetCluster().Start() err := cluster.GetCluster().Start()
if err != nil {
log.Error(err.Error())
os.Exit(-1)
}
//6.监听程序退出信号&性能报告 //6.监听程序退出信号&性能报告
bRun := true
var pProfilerTicker *time.Ticker = &time.Ticker{} var pProfilerTicker *time.Ticker = &time.Ticker{}
if profilerInterval > 0 { if profilerInterval > 0 {
pProfilerTicker = time.NewTicker(profilerInterval) pProfilerTicker = time.NewTicker(profilerInterval)
} }
for bRun { NodeIsRun = true
for NodeIsRun {
select { select {
case s := <-sig: case s := <-sig:
signal := s.(syscall.Signal) signal := s.(syscall.Signal)
if signal == SignalRetire { if signal == SignalRetire {
log.Info("receipt retire signal.") log.Info("receipt retire signal.")
notifyAllServiceRetire() notifyAllServiceRetire()
}else { } else {
bRun = false NodeIsRun = false
log.Info("receipt stop signal.") log.Info("receipt stop signal.")
} }
case <-pProfilerTicker.C: case <-pProfilerTicker.C:
@@ -350,16 +381,20 @@ func startNode(args interface{}) error {
} }
} }
//7.退出 //7.退出
service.StopAllService() service.StopAllService()
cluster.GetCluster().Stop() cluster.GetCluster().Stop()
log.Info("Server is stop.") log.Info("Server is stop.")
log.Close()
return nil return nil
} }
type templateServicePoint[T any] interface {
*T
service.IService
}
func Setup(s ...service.IService) { func Setup(s ...service.IService) {
for _, sv := range s { for _, sv := range s {
sv.OnSetup(sv) sv.OnSetup(sv)
@@ -367,6 +402,19 @@ func Setup(s ...service.IService) {
} }
} }
func SetupTemplateFunc(fs ...func() service.IService) {
for _, f := range fs {
preSetupTemplateService = append(preSetupTemplateService, f)
}
}
func SetupTemplate[T any, P templateServicePoint[T]]() {
SetupTemplateFunc(func() service.IService {
var t T
return P(&t)
})
}
func GetService(serviceName string) service.IService { func GetService(serviceName string) service.IService {
return service.GetService(serviceName) return service.GetService(serviceName)
} }
@@ -390,11 +438,13 @@ func openConsole(args interface{}) error {
} }
strOpen := strings.ToLower(strings.TrimSpace(args.(string))) strOpen := strings.ToLower(strings.TrimSpace(args.(string)))
if strOpen == "false" { if strOpen == "false" {
log.OpenConsole = false bOpenConsole := false
log.OpenConsole = &bOpenConsole
} else if strOpen == "true" { } else if strOpen == "true" {
log.OpenConsole = true bOpenConsole := true
log.OpenConsole = &bOpenConsole
} else { } else {
return errors.New("Parameter console error!") return errors.New("parameter console error")
} }
return nil return nil
} }
@@ -406,20 +456,18 @@ func setLevel(args interface{}) error {
strlogLevel := strings.TrimSpace(args.(string)) strlogLevel := strings.TrimSpace(args.(string))
switch strlogLevel { switch strlogLevel {
case "trace":
log.LogLevel = log.LevelTrace
case "debug": case "debug":
log.LogLevel = log.LevelDebug log.LogLevel = zapcore.DebugLevel
case "info": case "info":
log.LogLevel = log.LevelInfo log.LogLevel = zapcore.InfoLevel
case "warning": case "warn":
log.LogLevel = log.LevelWarning log.LogLevel = zapcore.WarnLevel
case "error": case "error":
log.LogLevel = log.LevelError log.LogLevel = zapcore.ErrorLevel
case "stack": case "stackerror":
log.LogLevel = log.LevelStack log.LogLevel = zapcore.ErrorLevel
case "fatal": case "fatal":
log.LogLevel = log.LevelFatal log.LogLevel = zapcore.FatalLevel
default: default:
return errors.New("unknown level: " + strlogLevel) return errors.New("unknown level: " + strlogLevel)
} }
@@ -430,48 +478,42 @@ func setLogPath(args interface{}) error {
if args == "" { if args == "" {
return nil return nil
} }
logPath := strings.TrimSpace(args.(string))
log.LogPath = strings.TrimSpace(args.(string)) _, err := os.Stat(logPath)
dir, err := os.Stat(log.LogPath) //这个文件夹不存在
if err == nil && dir.IsDir() == false {
return errors.New("Not found dir " + log.LogPath)
}
if err != nil { if err != nil {
err = os.Mkdir(log.LogPath, os.ModePerm) err = os.MkdirAll(logPath, os.ModePerm)
if err != nil { if err != nil {
return errors.New("Cannot create dir " + log.LogPath) return errors.New("Cannot create dir " + logPath)
} }
} }
log.LogPath = logPath
return nil return nil
} }
func setLogSize(args interface{}) error { func setLogSize(args interface{}) error {
if args == "" { logSize, ok := args.(int)
if ok == false {
return errors.New("param logsize is error")
}
if logSize == 0 {
return nil return nil
} }
logSize,ok := args.(int) log.MaxSize = logSize
if ok == false{
return errors.New("param logsize is error")
}
log.LogSize = int64(logSize)*1024*1024
return nil return nil
} }
func setLogChannelCapNum(args interface{}) error { func setLogChanLen(args interface{}) error {
if args == "" { logChanLen, ok := args.(int)
if ok == false {
return errors.New("param logsize is error")
}
if logChanLen == 0 {
return nil return nil
} }
logChannelCap,ok := args.(int) log.LogChanLen = logChanLen
if ok == false{
return errors.New("param logsize is error")
}
log.LogChannelCap = logChannelCap
return nil return nil
} }

View File

@@ -2,100 +2,103 @@ package profiler
import ( import (
"container/list" "container/list"
"fmt"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"sync" "sync"
"time" "time"
) )
//最大超长时间,一般可以认为是死锁或者死循环,或者极差的性能问题 // DefaultMaxOvertime 最大超长时间,一般可以认为是死锁或者死循环,或者极差的性能问题
var DefaultMaxOvertime time.Duration = 5*time.Second var DefaultMaxOvertime = 5 * time.Second
//超过该时间将会监控报告
var DefaultOvertime time.Duration = 10*time.Millisecond // DefaultOvertime 超过该时间将会监控报告
var DefaultMaxRecordNum int = 100 //最大记录条数 var DefaultOvertime = 10 * time.Millisecond
var DefaultMaxRecordNum = 100 //最大记录条数
var mapProfiler map[string]*Profiler var mapProfiler map[string]*Profiler
type ReportFunType func(name string,callNum int,costTime time.Duration,record *list.List)
var reportFunc ReportFunType =DefaultReportFunction type ReportFunType func(name string, callNum int, costTime time.Duration, record *list.List)
var reportFunc ReportFunType = DefaultReportFunction
type Element struct { type Element struct {
tagName string tagName string
pushTime time.Time pushTime time.Time
} }
type RecordType int type RecordType int
const (
const (
MaxOvertimeType = 1 MaxOvertimeType = 1
OvertimeType =2 OvertimeType = 2
) )
type Record struct { type Record struct {
RType RecordType RType RecordType
CostTime time.Duration CostTime time.Duration
RecordName string RecordName string
} }
type Analyzer struct { type Analyzer struct {
elem *list.Element elem *list.Element
profiler *Profiler profiler *Profiler
} }
type Profiler struct { type Profiler struct {
stack *list.List //Element stack *list.List //Element
stackLocker sync.RWMutex stackLocker sync.RWMutex
mapAnalyzer map[*list.Element]Analyzer mapAnalyzer map[*list.Element]Analyzer
record *list.List //Record record *list.List //Record
callNum int //调用次数 callNum int //调用次数
totalCostTime time.Duration //总消费时间长 totalCostTime time.Duration //总消费时间长
maxOverTime time.Duration maxOverTime time.Duration
overTime time.Duration overTime time.Duration
maxRecordNum int maxRecordNum int
} }
func init(){ func init() {
mapProfiler = map[string]*Profiler{} mapProfiler = map[string]*Profiler{}
} }
func RegProfiler(profilerName string) *Profiler { func RegProfiler(profilerName string) *Profiler {
if _,ok :=mapProfiler[profilerName];ok==true { if _, ok := mapProfiler[profilerName]; ok == true {
return nil return nil
} }
pProfiler := &Profiler{stack:list.New(),record:list.New(),maxOverTime: DefaultMaxOvertime,overTime: DefaultOvertime} pProfiler := &Profiler{stack: list.New(), record: list.New(), maxOverTime: DefaultMaxOvertime, overTime: DefaultOvertime}
mapProfiler[profilerName] =pProfiler mapProfiler[profilerName] = pProfiler
return pProfiler return pProfiler
} }
func (slf *Profiler) SetMaxOverTime(tm time.Duration){ func (slf *Profiler) SetMaxOverTime(tm time.Duration) {
slf.maxOverTime = tm slf.maxOverTime = tm
} }
func (slf *Profiler) SetOverTime(tm time.Duration){ func (slf *Profiler) SetOverTime(tm time.Duration) {
slf.overTime = tm slf.overTime = tm
} }
func (slf *Profiler) SetMaxRecordNum(num int){ func (slf *Profiler) SetMaxRecordNum(num int) {
slf.maxRecordNum = num slf.maxRecordNum = num
} }
func (slf *Profiler) Push(tag string) *Analyzer{ func (slf *Profiler) Push(tag string) *Analyzer {
slf.stackLocker.Lock() slf.stackLocker.Lock()
defer slf.stackLocker.Unlock() defer slf.stackLocker.Unlock()
pElem := slf.stack.PushBack(&Element{tagName:tag,pushTime:time.Now()}) pElem := slf.stack.PushBack(&Element{tagName: tag, pushTime: time.Now()})
return &Analyzer{elem:pElem,profiler:slf} return &Analyzer{elem: pElem, profiler: slf}
} }
func (slf *Profiler) check(pElem *Element) (*Record,time.Duration) { func (slf *Profiler) check(pElem *Element) (*Record, time.Duration) {
if pElem == nil { if pElem == nil {
return nil,0 return nil, 0
} }
subTm := time.Now().Sub(pElem.pushTime) subTm := time.Now().Sub(pElem.pushTime)
if subTm < slf.overTime { if subTm < slf.overTime {
return nil,subTm return nil, subTm
} }
record := Record{ record := Record{
@@ -104,20 +107,20 @@ func (slf *Profiler) check(pElem *Element) (*Record,time.Duration) {
RecordName: pElem.tagName, RecordName: pElem.tagName,
} }
if subTm>slf.maxOverTime { if subTm > slf.maxOverTime {
record.RType = MaxOvertimeType record.RType = MaxOvertimeType
} }
return &record,subTm return &record, subTm
} }
func (slf *Analyzer) Pop(){ func (slf *Analyzer) Pop() {
slf.profiler.stackLocker.Lock() slf.profiler.stackLocker.Lock()
defer slf.profiler.stackLocker.Unlock() defer slf.profiler.stackLocker.Unlock()
pElement := slf.elem.Value.(*Element) pElement := slf.elem.Value.(*Element)
pElem,subTm := slf.profiler.check(pElement) pElem, subTm := slf.profiler.check(pElement)
slf.profiler.callNum+=1 slf.profiler.callNum += 1
slf.profiler.totalCostTime += subTm slf.profiler.totalCostTime += subTm
if pElem != nil { if pElem != nil {
slf.profiler.pushRecordLog(pElem) slf.profiler.pushRecordLog(pElem)
@@ -125,10 +128,10 @@ func (slf *Analyzer) Pop(){
slf.profiler.stack.Remove(slf.elem) slf.profiler.stack.Remove(slf.elem)
} }
func (slf *Profiler) pushRecordLog(record *Record){ func (slf *Profiler) pushRecordLog(record *Record) {
if slf.record.Len()>= DefaultMaxRecordNum { if slf.record.Len() >= DefaultMaxRecordNum {
front := slf.stack.Front() front := slf.stack.Front()
if front!=nil { if front != nil {
slf.stack.Remove(front) slf.stack.Remove(front)
} }
} }
@@ -140,47 +143,43 @@ func SetReportFunction(reportFun ReportFunType) {
reportFunc = reportFun reportFunc = reportFun
} }
func DefaultReportFunction(name string,callNum int,costTime time.Duration,record *list.List){ func DefaultReportFunction(name string, callNum int, costTime time.Duration, record *list.List) {
if record.Len()<=0 { if record.Len() <= 0 {
return return
} }
var strReport string
strReport = "Profiler report tag "+name+":\n"
var average int64 var average int64
if callNum>0 { if callNum > 0 {
average = costTime.Milliseconds()/int64(callNum) average = costTime.Milliseconds() / int64(callNum)
} }
strReport += fmt.Sprintf("process count %d,take time %d Milliseconds,average %d Milliseconds/per.\n",callNum,costTime.Milliseconds(),average) log.Info("Profiler report tag "+name, log.Int("process count", callNum), log.Int64("take time", costTime.Milliseconds()), log.Int64("average", average))
elem := record.Front() elem := record.Front()
var strTypes string var strTypes string
for elem!=nil { for elem != nil {
pRecord := elem.Value.(*Record) pRecord := elem.Value.(*Record)
if pRecord.RType == MaxOvertimeType { if pRecord.RType == MaxOvertimeType {
strTypes = "too slow process" strTypes = "too slow process"
}else{ } else {
strTypes = "slow process" strTypes = "slow process"
} }
strReport += fmt.Sprintf("%s:%s is take %d Milliseconds\n",strTypes,pRecord.RecordName,pRecord.CostTime.Milliseconds()) log.Info("Profiler report type", log.String("Types", strTypes), log.String("RecordName", pRecord.RecordName), log.Int64("take time", pRecord.CostTime.Milliseconds()))
elem = elem.Next() elem = elem.Next()
} }
log.SInfo("report",strReport)
} }
func Report() { func Report() {
var record *list.List var record *list.List
for name,prof := range mapProfiler{ for name, prof := range mapProfiler {
prof.stackLocker.RLock() prof.stackLocker.RLock()
//取栈顶是否存在异常MaxOverTime数据 //取栈顶是否存在异常MaxOverTime数据
pElem := prof.stack.Back() pElem := prof.stack.Back()
for pElem!=nil { for pElem != nil {
pElement := pElem.Value.(*Element) pElement := pElem.Value.(*Element)
pExceptionElem,_ := prof.check(pElement) pExceptionElem, _ := prof.check(pElement)
if pExceptionElem!=nil { if pExceptionElem != nil {
prof.pushRecordLog(pExceptionElem) prof.pushRecordLog(pExceptionElem)
} }
pElem = pElem.Prev() pElem = pElem.Prev()
@@ -197,7 +196,6 @@ func Report() {
totalCostTime := prof.totalCostTime totalCostTime := prof.totalCostTime
prof.stackLocker.RUnlock() prof.stackLocker.RUnlock()
DefaultReportFunction(name,callNum,totalCostTime,record) DefaultReportFunction(name, callNum, totalCostTime, record)
} }
} }

View File

@@ -3,11 +3,11 @@ package rpc
import ( import (
"errors" "errors"
"github.com/duanhf2012/origin/v2/log"
"strconv" "strconv"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/duanhf2012/origin/v2/log"
) )
type CallSet struct { type CallSet struct {
@@ -20,12 +20,10 @@ type CallSet struct {
callTimerHeap CallTimerHeap callTimerHeap CallTimerHeap
} }
func (cs *CallSet) Init() {
func (cs *CallSet) Init(){
cs.pendingLock.Lock() cs.pendingLock.Lock()
cs.callTimerHeap.Init() cs.callTimerHeap.Init()
cs.pending = make(map[uint64]*Call,4096) cs.pending = make(map[uint64]*Call, 4096)
cs.maxCheckCallRpcCount = DefaultMaxCheckCallRpcCount cs.maxCheckCallRpcCount = DefaultMaxCheckCallRpcCount
cs.callRpcTimeout = DefaultRpcTimeout cs.callRpcTimeout = DefaultRpcTimeout
@@ -34,7 +32,7 @@ func (cs *CallSet) Init(){
cs.pendingLock.Unlock() cs.pendingLock.Unlock()
} }
func (bc *CallSet) makeCallFail(call *Call) { func (cs *CallSet) makeCallFail(call *Call) {
if call.callback != nil && call.callback.IsValid() { if call.callback != nil && call.callback.IsValid() {
call.rpcHandler.PushRpcResponse(call) call.rpcHandler.PushRpcResponse(call)
} else { } else {
@@ -42,105 +40,105 @@ func (bc *CallSet) makeCallFail(call *Call) {
} }
} }
func (bc *CallSet) checkRpcCallTimeout() { func (cs *CallSet) checkRpcCallTimeout() {
for{ for {
time.Sleep(DefaultCheckRpcCallTimeoutInterval) time.Sleep(DefaultCheckRpcCallTimeoutInterval)
for i := 0; i < bc.maxCheckCallRpcCount; i++ { for i := 0; i < cs.maxCheckCallRpcCount; i++ {
bc.pendingLock.Lock() cs.pendingLock.Lock()
callSeq := bc.callTimerHeap.PopTimeout() callSeq := cs.callTimerHeap.PopTimeout()
if callSeq == 0 { if callSeq == 0 {
bc.pendingLock.Unlock() cs.pendingLock.Unlock()
break break
} }
pCall := bc.pending[callSeq] pCall := cs.pending[callSeq]
if pCall == nil { if pCall == nil {
bc.pendingLock.Unlock() cs.pendingLock.Unlock()
log.Error("call seq is not find",log.Uint64("seq", callSeq)) log.Error("call seq is not find", log.Uint64("seq", callSeq))
continue continue
} }
delete(bc.pending,callSeq) delete(cs.pending, callSeq)
strTimeout := strconv.FormatInt(int64(pCall.TimeOut.Seconds()), 10) strTimeout := strconv.FormatInt(int64(pCall.TimeOut.Seconds()), 10)
pCall.Err = errors.New("RPC call takes more than " + strTimeout + " seconds,method is "+pCall.ServiceMethod) pCall.Err = errors.New("RPC call takes more than " + strTimeout + " seconds,method is " + pCall.ServiceMethod)
log.Error("call timeout",log.String("error",pCall.Err.Error())) log.Error("call timeout", log.String("error", pCall.Err.Error()))
bc.makeCallFail(pCall) cs.makeCallFail(pCall)
bc.pendingLock.Unlock() cs.pendingLock.Unlock()
continue continue
} }
} }
} }
func (bc *CallSet) AddPending(call *Call) { func (cs *CallSet) AddPending(call *Call) {
bc.pendingLock.Lock() cs.pendingLock.Lock()
if call.Seq == 0 { if call.Seq == 0 {
bc.pendingLock.Unlock() cs.pendingLock.Unlock()
log.Stack("call is error.") log.StackError("call is error.")
return return
} }
bc.pending[call.Seq] = call cs.pending[call.Seq] = call
bc.callTimerHeap.AddTimer(call.Seq,call.TimeOut) cs.callTimerHeap.AddTimer(call.Seq, call.TimeOut)
bc.pendingLock.Unlock() cs.pendingLock.Unlock()
} }
func (bc *CallSet) RemovePending(seq uint64) *Call { func (cs *CallSet) RemovePending(seq uint64) *Call {
if seq == 0 { if seq == 0 {
return nil return nil
} }
bc.pendingLock.Lock() cs.pendingLock.Lock()
call := bc.removePending(seq) call := cs.removePending(seq)
bc.pendingLock.Unlock() cs.pendingLock.Unlock()
return call return call
} }
func (bc *CallSet) removePending(seq uint64) *Call { func (cs *CallSet) removePending(seq uint64) *Call {
v, ok := bc.pending[seq] v, ok := cs.pending[seq]
if ok == false { if ok == false {
return nil return nil
} }
bc.callTimerHeap.Cancel(seq) cs.callTimerHeap.Cancel(seq)
delete(bc.pending, seq) delete(cs.pending, seq)
return v return v
} }
func (bc *CallSet) FindPending(seq uint64) (pCall *Call) { func (cs *CallSet) FindPending(seq uint64) (pCall *Call) {
if seq == 0 { if seq == 0 {
return nil return nil
} }
bc.pendingLock.Lock() cs.pendingLock.Lock()
pCall = bc.pending[seq] pCall = cs.pending[seq]
bc.pendingLock.Unlock() cs.pendingLock.Unlock()
return pCall return pCall
} }
func (bc *CallSet) cleanPending(){ func (cs *CallSet) cleanPending() {
bc.pendingLock.Lock() cs.pendingLock.Lock()
for { for {
callSeq := bc.callTimerHeap.PopFirst() callSeq := cs.callTimerHeap.PopFirst()
if callSeq == 0 { if callSeq == 0 {
break break
} }
pCall := bc.pending[callSeq] pCall := cs.pending[callSeq]
if pCall == nil { if pCall == nil {
log.Error("call Seq is not find",log.Uint64("seq",callSeq)) log.Error("call Seq is not find", log.Uint64("seq", callSeq))
continue continue
} }
delete(bc.pending,callSeq) delete(cs.pending, callSeq)
pCall.Err = errors.New("nodeid is disconnect ") pCall.Err = errors.New("node is disconnect ")
bc.makeCallFail(pCall) cs.makeCallFail(pCall)
} }
bc.pendingLock.Unlock() cs.pendingLock.Unlock()
} }
func (bc *CallSet) generateSeq() uint64 { func (cs *CallSet) generateSeq() uint64 {
return atomic.AddUint64(&bc.startSeq, 1) return atomic.AddUint64(&cs.startSeq, 1)
} }

View File

@@ -2,39 +2,39 @@ package rpc
import ( import (
"errors" "errors"
"fmt"
"github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/network" "github.com/duanhf2012/origin/v2/network"
"reflect" "reflect"
"time" "time"
"github.com/duanhf2012/origin/v2/log"
"fmt"
) )
const( const (
DefaultRpcConnNum = 1 DefaultRpcConnNum = 1
DefaultRpcLenMsgLen = 4 DefaultRpcLenMsgLen = 4
DefaultRpcMinMsgLen = 2 DefaultRpcMinMsgLen = 2
DefaultMaxCheckCallRpcCount = 1000 DefaultMaxCheckCallRpcCount = 1000
DefaultMaxPendingWriteNum = 1000000 DefaultMaxPendingWriteNum = 1000000
DefaultConnectInterval = 2*time.Second DefaultConnectInterval = 2 * time.Second
DefaultCheckRpcCallTimeoutInterval = 1*time.Second DefaultCheckRpcCallTimeoutInterval = 1 * time.Second
DefaultRpcTimeout = 15*time.Second DefaultRpcTimeout = 15 * time.Second
) )
var clientSeq uint32 var clientSeq uint32
type IWriter interface { type IWriter interface {
WriteMsg (nodeId string,args ...[]byte) error WriteMsg(nodeId string, args ...[]byte) error
IsConnected() bool IsConnected() bool
} }
type IRealClient interface { type IRealClient interface {
SetConn(conn *network.TCPConn) SetConn(conn *network.NetConn)
Close(waitDone bool) Close(waitDone bool)
AsyncCall(NodeId string,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error) AsyncCall(NodeId string, timeout time.Duration, rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{}) (CancelRpc, error)
Go(NodeId string,timeout time.Duration,rpcHandler IRpcHandler, noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call Go(NodeId string, timeout time.Duration, rpcHandler IRpcHandler, noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call
RawGo(NodeId string,timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call RawGo(NodeId string, timeout time.Duration, rpcHandler IRpcHandler, processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call
IsConnected() bool IsConnected() bool
Run() Run()
@@ -43,18 +43,16 @@ type IRealClient interface {
Bind(server IServer) Bind(server IServer)
} }
type Client struct { type Client struct {
clientId uint32 clientId uint32
targetNodeId string targetNodeId string
compressBytesLen int compressBytesLen int
*CallSet *CallSet
IRealClient IRealClient
} }
func (client *Client) NewClientAgent(conn *network.TCPConn) network.Agent { func (client *Client) NewClientAgent(conn *network.NetConn) network.Agent {
client.SetConn(conn) client.SetConn(conn)
return client return client
@@ -68,13 +66,12 @@ func (client *Client) GetClientId() uint32 {
return client.clientId return client.clientId
} }
func (client *Client) processRpcResponse(responseData []byte) error {
func (client *Client) processRpcResponse(responseData []byte) error{ bCompress := (responseData[0] >> 7) > 0
bCompress := (responseData[0]>>7) > 0 processor := GetProcessor(responseData[0] & 0x7f)
processor := GetProcessor(responseData[0]&0x7f)
if processor == nil { if processor == nil {
//rc.conn.ReleaseReadMsg(responseData) //rc.conn.ReleaseReadMsg(responseData)
err:= errors.New(fmt.Sprintf("cannot find process %d",responseData[0]&0x7f)) err := errors.New(fmt.Sprintf("cannot find process %d", responseData[0]&0x7f))
log.Error(err.Error()) log.Error(err.Error())
return err return err
} }
@@ -89,10 +86,10 @@ func (client *Client) processRpcResponse(responseData []byte) error{
if bCompress == true { if bCompress == true {
var unCompressErr error var unCompressErr error
compressBuff,unCompressErr = compressor.UncompressBlock(byteData) compressBuff, unCompressErr = compressor.UncompressBlock(byteData)
if unCompressErr!= nil { if unCompressErr != nil {
//rc.conn.ReleaseReadMsg(responseData) //rc.conn.ReleaseReadMsg(responseData)
err := fmt.Errorf("uncompressBlock failed,err :%s",unCompressErr.Error()) err := fmt.Errorf("uncompressBlock failed,err :%s", unCompressErr.Error())
return err return err
} }
@@ -107,19 +104,19 @@ func (client *Client) processRpcResponse(responseData []byte) error{
//rc.conn.ReleaseReadMsg(bytes) //rc.conn.ReleaseReadMsg(bytes)
if err != nil { if err != nil {
processor.ReleaseRpcResponse(response.RpcResponseData) processor.ReleaseRpcResponse(response.RpcResponseData)
log.Error("rpcClient Unmarshal head error",log.ErrorAttr("error",err)) log.Error("rpcClient Unmarshal head error", log.ErrorField("error", err))
return nil return nil
} }
v := client.RemovePending(response.RpcResponseData.GetSeq()) v := client.RemovePending(response.RpcResponseData.GetSeq())
if v == nil { if v == nil {
log.Error("rpcClient cannot find seq",log.Uint64("seq",response.RpcResponseData.GetSeq())) log.Error("rpcClient cannot find seq", log.Uint64("seq", response.RpcResponseData.GetSeq()))
} else { } else {
v.Err = nil v.Err = nil
if len(response.RpcResponseData.GetReply()) > 0 { if len(response.RpcResponseData.GetReply()) > 0 {
err = processor.Unmarshal(response.RpcResponseData.GetReply(), v.Reply) err = processor.Unmarshal(response.RpcResponseData.GetReply(), v.Reply)
if err != nil { if err != nil {
log.Error("rpcClient Unmarshal body failed",log.ErrorAttr("error",err)) log.Error("rpcClient Unmarshal body failed", log.ErrorField("error", err))
v.Err = err v.Err = err
} }
} }
@@ -140,7 +137,6 @@ func (client *Client) processRpcResponse(responseData []byte) error{
return nil return nil
} }
//func (rc *Client) Go(timeout time.Duration,rpcHandler IRpcHandler,noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call { //func (rc *Client) Go(timeout time.Duration,rpcHandler IRpcHandler,noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call {
// _, processor := GetProcessorType(args) // _, processor := GetProcessorType(args)
// InParam, err := processor.Marshal(args) // InParam, err := processor.Marshal(args)
@@ -154,11 +150,11 @@ func (client *Client) processRpcResponse(responseData []byte) error{
// return rc.RawGo(timeout,rpcHandler,processor, noReply, 0, serviceMethod, InParam, reply) // return rc.RawGo(timeout,rpcHandler,processor, noReply, 0, serviceMethod, InParam, reply)
//} //}
func (rc *Client) rawGo(nodeId string,w IWriter,timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call { func (client *Client) rawGo(nodeId string, w IWriter, timeout time.Duration, rpcHandler IRpcHandler, processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call {
call := MakeCall() call := MakeCall()
call.ServiceMethod = serviceMethod call.ServiceMethod = serviceMethod
call.Reply = reply call.Reply = reply
call.Seq = rc.generateSeq() call.Seq = client.generateSeq()
call.TimeOut = timeout call.TimeOut = timeout
request := MakeRpcRequest(processor, call.Seq, rpcMethodId, serviceMethod, noReply, rawArgs) request := MakeRpcRequest(processor, call.Seq, rpcMethodId, serviceMethod, noReply, rawArgs)
@@ -167,47 +163,47 @@ func (rc *Client) rawGo(nodeId string,w IWriter,timeout time.Duration,rpcHandler
if err != nil { if err != nil {
call.Seq = 0 call.Seq = 0
log.Error("marshal is fail",log.String("error",err.Error())) log.Error("marshal is fail", log.String("error", err.Error()))
call.DoError(err) call.DoError(err)
return call return call
} }
if w == nil || w.IsConnected()==false { if w == nil || w.IsConnected() == false {
call.Seq = 0 call.Seq = 0
sErr := errors.New(serviceMethod + " was called failed,rpc client is disconnect") sErr := errors.New(serviceMethod + " was called failed,rpc client is disconnect")
log.Error("conn is disconnect",log.String("error",sErr.Error())) log.Error("conn is disconnect", log.String("error", sErr.Error()))
call.DoError(sErr) call.DoError(sErr)
return call return call
} }
var compressBuff[]byte var compressBuff []byte
bCompress := uint8(0) bCompress := uint8(0)
if rc.compressBytesLen > 0 && len(bytes) >= rc.compressBytesLen { if client.compressBytesLen > 0 && len(bytes) >= client.compressBytesLen {
var cErr error var cErr error
compressBuff,cErr = compressor.CompressBlock(bytes) compressBuff, cErr = compressor.CompressBlock(bytes)
if cErr != nil { if cErr != nil {
call.Seq = 0 call.Seq = 0
log.Error("compress fail",log.String("error",cErr.Error())) log.Error("compress fail", log.String("error", cErr.Error()))
call.DoError(cErr) call.DoError(cErr)
return call return call
} }
if len(compressBuff) < len(bytes) { if len(compressBuff) < len(bytes) {
bytes = compressBuff bytes = compressBuff
bCompress = 1<<7 bCompress = 1 << 7
} }
} }
if noReply == false { if noReply == false {
rc.AddPending(call) client.AddPending(call)
} }
err = w.WriteMsg(nodeId,[]byte{uint8(processor.GetProcessorType())|bCompress}, bytes) err = w.WriteMsg(nodeId, []byte{uint8(processor.GetProcessorType()) | bCompress}, bytes)
if cap(compressBuff) >0 { if cap(compressBuff) > 0 {
compressor.CompressBufferCollection(compressBuff) compressor.CompressBufferCollection(compressBuff)
} }
if err != nil { if err != nil {
rc.RemovePending(call.Seq) client.RemovePending(call.Seq)
log.Error("WiteMsg is fail",log.ErrorAttr("error",err)) log.Error("WriteMsg is fail", log.ErrorField("error", err))
call.Seq = 0 call.Seq = 0
call.DoError(err) call.DoError(err)
} }
@@ -215,37 +211,37 @@ func (rc *Client) rawGo(nodeId string,w IWriter,timeout time.Duration,rpcHandler
return call return call
} }
func (rc *Client) asyncCall(nodeId string,w IWriter,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error) { func (client *Client) asyncCall(nodeId string, w IWriter, timeout time.Duration, rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{}) (CancelRpc, error) {
processorType, processor := GetProcessorType(args) processorType, processor := GetProcessorType(args)
InParam, herr := processor.Marshal(args) InParam, herr := processor.Marshal(args)
if herr != nil { if herr != nil {
return emptyCancelRpc,herr return emptyCancelRpc, herr
} }
seq := rc.generateSeq() seq := client.generateSeq()
request := MakeRpcRequest(processor, seq, 0, serviceMethod, false, InParam) request := MakeRpcRequest(processor, seq, 0, serviceMethod, false, InParam)
bytes, err := processor.Marshal(request.RpcRequestData) bytes, err := processor.Marshal(request.RpcRequestData)
ReleaseRpcRequest(request) ReleaseRpcRequest(request)
if err != nil { if err != nil {
return emptyCancelRpc,err return emptyCancelRpc, err
} }
if w == nil || w.IsConnected()==false { if w == nil || w.IsConnected() == false {
return emptyCancelRpc,errors.New("Rpc server is disconnect,call " + serviceMethod) return emptyCancelRpc, errors.New("Rpc server is disconnect,call " + serviceMethod)
} }
var compressBuff[]byte var compressBuff []byte
bCompress := uint8(0) bCompress := uint8(0)
if rc.compressBytesLen>0 &&len(bytes) >= rc.compressBytesLen { if client.compressBytesLen > 0 && len(bytes) >= client.compressBytesLen {
var cErr error var cErr error
compressBuff,cErr = compressor.CompressBlock(bytes) compressBuff, cErr = compressor.CompressBlock(bytes)
if cErr != nil { if cErr != nil {
return emptyCancelRpc,cErr return emptyCancelRpc, cErr
} }
if len(compressBuff) < len(bytes) { if len(compressBuff) < len(bytes) {
bytes = compressBuff bytes = compressBuff
bCompress = 1<<7 bCompress = 1 << 7
} }
} }
@@ -256,22 +252,19 @@ func (rc *Client) asyncCall(nodeId string,w IWriter,timeout time.Duration,rpcHan
call.ServiceMethod = serviceMethod call.ServiceMethod = serviceMethod
call.Seq = seq call.Seq = seq
call.TimeOut = timeout call.TimeOut = timeout
rc.AddPending(call) client.AddPending(call)
err = w.WriteMsg(nodeId,[]byte{uint8(processorType)|bCompress}, bytes) err = w.WriteMsg(nodeId, []byte{uint8(processorType) | bCompress}, bytes)
if cap(compressBuff) >0 { if cap(compressBuff) > 0 {
compressor.CompressBufferCollection(compressBuff) compressor.CompressBufferCollection(compressBuff)
} }
if err != nil { if err != nil {
rc.RemovePending(call.Seq) client.RemovePending(call.Seq)
ReleaseCall(call) ReleaseCall(call)
return emptyCancelRpc,err return emptyCancelRpc, err
} }
if cancelable {
rpcCancel := RpcCancel{CallSeq:seq,Cli: rc}
return rpcCancel.CancelRpc,nil
}
return emptyCancelRpc,nil rpcCancel := RpcCancel{CallSeq: seq, Cli: client}
} return rpcCancel.CancelRpc, nil
}

View File

@@ -8,22 +8,23 @@ import (
"runtime" "runtime"
) )
var memPool bytespool.IBytesMempool = bytespool.NewMemAreaPool() var memPool bytespool.IBytesMemPool = bytespool.NewMemAreaPool()
type ICompressor interface { type ICompressor interface {
CompressBlock(src []byte) ([]byte, error) //dst如果有预申请使用dst内存传入nil时内部申请 CompressBlock(src []byte) ([]byte, error) //dst如果有预申请使用dst内存传入nil时内部申请
UncompressBlock(src []byte) ([]byte, error) //dst如果有预申请使用dst内存传入nil时内部申请 UncompressBlock(src []byte) ([]byte, error) //dst如果有预申请使用dst内存传入nil时内部申请
CompressBufferCollection(buffer []byte) //压缩的Buffer内存回收 CompressBufferCollection(buffer []byte) //压缩的Buffer内存回收
UnCompressBufferCollection(buffer []byte) //解压缩的Buffer内存回收 UnCompressBufferCollection(buffer []byte) //解压缩的Buffer内存回收
} }
var compressor ICompressor var compressor ICompressor
func init(){
func init() {
SetCompressor(&Lz4Compressor{}) SetCompressor(&Lz4Compressor{})
} }
func SetCompressor(cp ICompressor){ func SetCompressor(cp ICompressor) {
compressor = cp compressor = cp
} }
@@ -42,21 +43,21 @@ func (lc *Lz4Compressor) CompressBlock(src []byte) (dest []byte, err error) {
var c lz4.Compressor var c lz4.Compressor
var cnt int var cnt int
dest = memPool.MakeBytes(lz4.CompressBlockBound(len(src))+1) dest = memPool.MakeBytes(lz4.CompressBlockBound(len(src)) + 1)
cnt, err = c.CompressBlock(src, dest[1:]) cnt, err = c.CompressBlock(src, dest[1:])
if err != nil { if err != nil {
memPool.ReleaseBytes(dest) memPool.ReleaseBytes(dest)
return nil,err return nil, err
} }
ratio := len(src) / cnt ratio := len(src) / cnt
if len(src) % cnt > 0 { if len(src)%cnt > 0 {
ratio += 1 ratio += 1
} }
if ratio > 255 { if ratio > 255 {
memPool.ReleaseBytes(dest) memPool.ReleaseBytes(dest)
return nil,fmt.Errorf("Impermissible errors") return nil, fmt.Errorf("impermissible errors")
} }
dest[0] = uint8(ratio) dest[0] = uint8(ratio)
@@ -76,24 +77,24 @@ func (lc *Lz4Compressor) UncompressBlock(src []byte) (dest []byte, err error) {
radio := uint8(src[0]) radio := uint8(src[0])
if radio == 0 { if radio == 0 {
return nil,fmt.Errorf("Impermissible errors") return nil, fmt.Errorf("impermissible errors")
} }
dest = memPool.MakeBytes(len(src)*int(radio)) dest = memPool.MakeBytes(len(src) * int(radio))
cnt, err := lz4.UncompressBlock(src[1:], dest) cnt, err := lz4.UncompressBlock(src[1:], dest)
if err != nil { if err != nil {
memPool.ReleaseBytes(dest) memPool.ReleaseBytes(dest)
return nil,err return nil, err
} }
return dest[:cnt],nil return dest[:cnt], nil
} }
func (lc *Lz4Compressor) compressBlockBound(n int) int{ func (lc *Lz4Compressor) compressBlockBound(n int) int {
return lz4.CompressBlockBound(n) return lz4.CompressBlockBound(n)
} }
func (lc *Lz4Compressor) CompressBufferCollection(buffer []byte){ func (lc *Lz4Compressor) CompressBufferCollection(buffer []byte) {
memPool.ReleaseBytes(buffer) memPool.ReleaseBytes(buffer)
} }

View File

@@ -10,40 +10,40 @@ import (
"time" "time"
) )
//本结点的Client // LClient 本结点的Client
type LClient struct { type LClient struct {
selfClient *Client selfClient *Client
} }
func (rc *LClient) Lock(){ func (lc *LClient) Lock() {
} }
func (rc *LClient) Unlock(){ func (lc *LClient) Unlock() {
} }
func (lc *LClient) Run(){ func (lc *LClient) Run() {
} }
func (lc *LClient) OnClose(){ func (lc *LClient) OnClose() {
} }
func (lc *LClient) IsConnected() bool { func (lc *LClient) IsConnected() bool {
return true return true
} }
func (lc *LClient) SetConn(conn *network.TCPConn){ func (lc *LClient) SetConn(conn *network.NetConn) {
} }
func (lc *LClient) Close(waitDone bool){ func (lc *LClient) Close(waitDone bool) {
} }
func (lc *LClient) Go(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call { func (lc *LClient) Go(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call {
pLocalRpcServer := rpcHandler.GetRpcServer()() pLocalRpcServer := rpcHandler.GetRpcServer()()
//判断是否是同一服务 //判断是否是同一服务
findIndex := strings.Index(serviceMethod, ".") findIndex := strings.Index(serviceMethod, ".")
if findIndex == -1 { if findIndex == -1 {
sErr := errors.New("Call serviceMethod " + serviceMethod + " is error!") sErr := errors.New("Call serviceMethod " + serviceMethod + " is error!")
log.Error("call rpc fail",log.String("error",sErr.Error())) log.Error("call rpc fail", log.String("error", sErr.Error()))
call := MakeCall() call := MakeCall()
call.DoError(sErr) call.DoError(sErr)
@@ -53,7 +53,7 @@ func (lc *LClient) Go(nodeId string,timeout time.Duration,rpcHandler IRpcHandler
serviceName := serviceMethod[:findIndex] serviceName := serviceMethod[:findIndex]
if serviceName == rpcHandler.GetName() { //自己服务调用 if serviceName == rpcHandler.GetName() { //自己服务调用
//调用自己rpcHandler处理器 //调用自己rpcHandler处理器
err := pLocalRpcServer.myselfRpcHandlerGo(lc.selfClient,serviceName, serviceMethod, args, requestHandlerNull,reply) err := pLocalRpcServer.myselfRpcHandlerGo(lc.selfClient, serviceName, serviceMethod, args, requestHandlerNull, reply)
call := MakeCall() call := MakeCall()
if err != nil { if err != nil {
@@ -66,13 +66,12 @@ func (lc *LClient) Go(nodeId string,timeout time.Duration,rpcHandler IRpcHandler
} }
//其他的rpcHandler的处理器 //其他的rpcHandler的处理器
return pLocalRpcServer.selfNodeRpcHandlerGo(timeout,nil, lc.selfClient, noReply, serviceName, 0, serviceMethod, args, reply, nil) return pLocalRpcServer.selfNodeRpcHandlerGo(timeout, nil, lc.selfClient, noReply, serviceName, 0, serviceMethod, args, reply, nil)
} }
func (lc *LClient) RawGo(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceName string, rawArgs []byte, reply interface{}) *Call {
func (rc *LClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceName string, rawArgs []byte, reply interface{}) *Call {
pLocalRpcServer := rpcHandler.GetRpcServer()() pLocalRpcServer := rpcHandler.GetRpcServer()()
//服务自我调用 //服务自我调用
if serviceName == rpcHandler.GetName() { if serviceName == rpcHandler.GetName() {
call := MakeCall() call := MakeCall()
@@ -80,7 +79,7 @@ func (rc *LClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHand
call.Reply = reply call.Reply = reply
call.TimeOut = timeout call.TimeOut = timeout
err := pLocalRpcServer.myselfRpcHandlerGo(rc.selfClient,serviceName, serviceName, rawArgs, requestHandlerNull,nil) err := pLocalRpcServer.myselfRpcHandlerGo(lc.selfClient, serviceName, serviceName, rawArgs, requestHandlerNull, nil)
call.Err = err call.Err = err
call.done <- call call.done <- call
@@ -88,11 +87,10 @@ func (rc *LClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHand
} }
//其他的rpcHandler的处理器 //其他的rpcHandler的处理器
return pLocalRpcServer.selfNodeRpcHandlerGo(timeout,processor,rc.selfClient, true, serviceName, rpcMethodId, serviceName, nil, nil, rawArgs) return pLocalRpcServer.selfNodeRpcHandlerGo(timeout, processor, lc.selfClient, true, serviceName, rpcMethodId, serviceName, nil, nil, rawArgs)
} }
func (lc *LClient) AsyncCall(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, reply interface{}) (CancelRpc, error) {
func (lc *LClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, reply interface{},cancelable bool) (CancelRpc,error) {
pLocalRpcServer := rpcHandler.GetRpcServer()() pLocalRpcServer := rpcHandler.GetRpcServer()()
//判断是否是同一服务 //判断是否是同一服务
@@ -100,32 +98,29 @@ func (lc *LClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpc
if findIndex == -1 { if findIndex == -1 {
err := errors.New("Call serviceMethod " + serviceMethod + " is error!") err := errors.New("Call serviceMethod " + serviceMethod + " is error!")
callback.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)}) callback.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
log.Error("serviceMethod format is error",log.String("error",err.Error())) log.Error("serviceMethod format is error", log.String("error", err.Error()))
return emptyCancelRpc,nil return emptyCancelRpc, nil
} }
serviceName := serviceMethod[:findIndex] serviceName := serviceMethod[:findIndex]
//调用自己rpcHandler处理器 //调用自己rpcHandler处理器
if serviceName == rpcHandler.GetName() { //自己服务调用 if serviceName == rpcHandler.GetName() { //自己服务调用
return emptyCancelRpc,pLocalRpcServer.myselfRpcHandlerGo(lc.selfClient,serviceName, serviceMethod, args,callback ,reply) return emptyCancelRpc, pLocalRpcServer.myselfRpcHandlerGo(lc.selfClient, serviceName, serviceMethod, args, callback, reply)
} }
//其他的rpcHandler的处理器 //其他的rpcHandler的处理器
calcelRpc,err := pLocalRpcServer.selfNodeRpcHandlerAsyncGo(timeout,lc.selfClient, rpcHandler, false, serviceName, serviceMethod, args, reply, callback,cancelable) cancelRpc, err := pLocalRpcServer.selfNodeRpcHandlerAsyncGo(timeout, lc.selfClient, rpcHandler, false, serviceName, serviceMethod, args, reply, callback)
if err != nil { if err != nil {
callback.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)}) callback.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
} }
return calcelRpc,nil return cancelRpc, nil
} }
func NewLClient(localNodeId string,callSet *CallSet) *Client{ func NewLClient(localNodeId string, callSet *CallSet) *Client {
client := &Client{} client := &Client{}
client.clientId = atomic.AddUint32(&clientSeq, 1) client.clientId = atomic.AddUint32(&clientSeq, 1)
client.targetNodeId = localNodeId client.targetNodeId = localNodeId
//client.maxCheckCallRpcCount = DefaultMaxCheckCallRpcCount
//client.callRpcTimeout = DefaultRpcTimeout
lClient := &LClient{} lClient := &LClient{}
lClient.selfClient = client lClient.selfClient = client
client.IRealClient = lClient client.IRealClient = lClient
@@ -133,5 +128,5 @@ func NewLClient(localNodeId string,callSet *CallSet) *Client{
return client return client
} }
func (rc *LClient) Bind(server IServer){ func (lc *LClient) Bind(_ IServer) {
} }

View File

@@ -1,48 +1,48 @@
package rpc package rpc
import ( import (
"errors" "errors"
"fmt"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"reflect" "reflect"
"time"
"strings" "strings"
"fmt" "time"
) )
type BaseServer struct { type BaseServer struct {
localNodeId string localNodeId string
compressBytesLen int compressBytesLen int
rpcHandleFinder RpcHandleFinder rpcHandleFinder RpcHandleFinder
iServer IServer iServer IServer
} }
func (ls *BaseServer) initBaseServer(compressBytesLen int,rpcHandleFinder RpcHandleFinder){ func (server *BaseServer) initBaseServer(compressBytesLen int, rpcHandleFinder RpcHandleFinder) {
ls.compressBytesLen = compressBytesLen server.compressBytesLen = compressBytesLen
ls.rpcHandleFinder = rpcHandleFinder server.rpcHandleFinder = rpcHandleFinder
} }
func (ls *BaseServer) myselfRpcHandlerGo(client *Client,handlerName string, serviceMethod string, args interface{},callBack reflect.Value, reply interface{}) error { func (server *BaseServer) myselfRpcHandlerGo(client *Client, handlerName string, serviceMethod string, args interface{}, callBack reflect.Value, reply interface{}) error {
rpcHandler := ls.rpcHandleFinder.FindRpcHandler(handlerName) rpcHandler := server.rpcHandleFinder.FindRpcHandler(handlerName)
if rpcHandler == nil { if rpcHandler == nil {
err := errors.New("service method " + serviceMethod + " not config!") err := errors.New("service method " + serviceMethod + " not config!")
log.Error("service method not config",log.String("serviceMethod",serviceMethod)) log.Error("service method not config", log.String("serviceMethod", serviceMethod))
return err return err
} }
return rpcHandler.CallMethod(client,serviceMethod, args,callBack, reply) return rpcHandler.CallMethod(client, serviceMethod, args, callBack, reply)
} }
func (ls *BaseServer) selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcProcessor, client *Client, noReply bool, handlerName string, rpcMethodId uint32, serviceMethod string, args interface{}, reply interface{}, rawArgs []byte) *Call { func (server *BaseServer) selfNodeRpcHandlerGo(timeout time.Duration, processor IRpcProcessor, client *Client, noReply bool, handlerName string, rpcMethodId uint32, serviceMethod string, args interface{}, reply interface{}, rawArgs []byte) *Call {
pCall := MakeCall() pCall := MakeCall()
pCall.Seq = client.generateSeq() pCall.Seq = client.generateSeq()
pCall.TimeOut = timeout pCall.TimeOut = timeout
pCall.ServiceMethod = serviceMethod pCall.ServiceMethod = serviceMethod
rpcHandler := ls.rpcHandleFinder.FindRpcHandler(handlerName) rpcHandler := server.rpcHandleFinder.FindRpcHandler(handlerName)
if rpcHandler == nil { if rpcHandler == nil {
err := errors.New("service method " + serviceMethod + " not config!") err := errors.New("service method " + serviceMethod + " not config!")
log.Error("service method not config",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err)) log.Error("service method not config", log.String("serviceMethod", serviceMethod), log.ErrorField("error", err))
pCall.Seq = 0 pCall.Seq = 0
pCall.DoError(err) pCall.DoError(err)
@@ -56,10 +56,10 @@ func (ls *BaseServer) selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcP
if args != nil { if args != nil {
var err error var err error
iParam,err = processor.Clone(args) iParam, err = processor.Clone(args)
if err != nil { if err != nil {
sErr := errors.New("RpcHandler " + handlerName + "."+serviceMethod+" deep copy inParam is error:" + err.Error()) sErr := errors.New("RpcHandler " + handlerName + "." + serviceMethod + " deep copy inParam is error:" + err.Error())
log.Error("deep copy inParam is failed",log.String("handlerName",handlerName),log.String("serviceMethod",serviceMethod)) log.Error("deep copy inParam is failed", log.String("handlerName", handlerName), log.String("serviceMethod", serviceMethod))
pCall.Seq = 0 pCall.Seq = 0
pCall.DoError(sErr) pCall.DoError(sErr)
@@ -74,7 +74,7 @@ func (ls *BaseServer) selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcP
var err error var err error
req.inParam, err = rpcHandler.UnmarshalInParam(processor, serviceMethod, rpcMethodId, rawArgs) req.inParam, err = rpcHandler.UnmarshalInParam(processor, serviceMethod, rpcMethodId, rawArgs)
if err != nil { if err != nil {
log.Error("unmarshalInParam is failed",log.String("serviceMethod",serviceMethod),log.Uint32("rpcMethodId",rpcMethodId),log.ErrorAttr("error",err)) log.Error("unmarshalInParam is failed", log.String("serviceMethod", serviceMethod), log.Uint32("rpcMethodId", rpcMethodId), log.ErrorField("error", err))
pCall.Seq = 0 pCall.Seq = 0
pCall.DoError(err) pCall.DoError(err)
ReleaseRpcRequest(req) ReleaseRpcRequest(req)
@@ -90,12 +90,12 @@ func (ls *BaseServer) selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcP
byteReturns, err := req.rpcProcessor.Marshal(Returns) byteReturns, err := req.rpcProcessor.Marshal(Returns)
if err != nil { if err != nil {
Err = ConvertError(err) Err = ConvertError(err)
log.Error("returns data cannot be marshal",log.Uint64("seq",callSeq),log.ErrorAttr("error",err)) log.Error("returns data cannot be marshal", log.Uint64("seq", callSeq), log.ErrorField("error", err))
}else{ } else {
err = req.rpcProcessor.Unmarshal(byteReturns, reply) err = req.rpcProcessor.Unmarshal(byteReturns, reply)
if err != nil { if err != nil {
Err = ConvertError(err) Err = ConvertError(err)
log.Error("returns data cannot be Unmarshal",log.Uint64("seq",callSeq),log.ErrorAttr("error",err)) log.Error("returns data cannot be Unmarshal", log.Uint64("seq", callSeq), log.ErrorField("error", err))
} }
} }
} }
@@ -103,7 +103,7 @@ func (ls *BaseServer) selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcP
ReleaseRpcRequest(req) ReleaseRpcRequest(req)
v := client.RemovePending(callSeq) v := client.RemovePending(callSeq)
if v == nil { if v == nil {
log.Error("rpcClient cannot find seq",log.Uint64("seq",callSeq)) log.Error("rpcClient cannot find seq", log.Uint64("seq", callSeq))
return return
} }
@@ -127,20 +127,20 @@ func (ls *BaseServer) selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcP
return pCall return pCall
} }
func (server *BaseServer) selfNodeRpcHandlerAsyncGo(timeout time.Duration,client *Client, callerRpcHandler IRpcHandler, noReply bool, handlerName string, serviceMethod string, args interface{}, reply interface{}, callback reflect.Value,cancelable bool) (CancelRpc,error) { func (server *BaseServer) selfNodeRpcHandlerAsyncGo(timeout time.Duration, client *Client, callerRpcHandler IRpcHandler, noReply bool, handlerName string, serviceMethod string, args interface{}, reply interface{}, callback reflect.Value) (CancelRpc, error) {
rpcHandler := server.rpcHandleFinder.FindRpcHandler(handlerName) rpcHandler := server.rpcHandleFinder.FindRpcHandler(handlerName)
if rpcHandler == nil { if rpcHandler == nil {
err := errors.New("service method " + serviceMethod + " not config!") err := errors.New("service method " + serviceMethod + " not config!")
log.Error(err.Error()) log.Error(err.Error())
return emptyCancelRpc,err return emptyCancelRpc, err
} }
_, processor := GetProcessorType(args) _, processor := GetProcessorType(args)
iParam,err := processor.Clone(args) iParam, err := processor.Clone(args)
if err != nil { if err != nil {
errM := errors.New("RpcHandler " + handlerName + "."+serviceMethod+" deep copy inParam is error:" + err.Error()) errM := errors.New("RpcHandler " + handlerName + "." + serviceMethod + " deep copy inParam is error:" + err.Error())
log.Error(errM.Error()) log.Error(errM.Error())
return emptyCancelRpc,errM return emptyCancelRpc, errM
} }
req := MakeRpcRequest(processor, 0, 0, serviceMethod, noReply, nil) req := MakeRpcRequest(processor, 0, 0, serviceMethod, noReply, nil)
@@ -159,7 +159,7 @@ func (server *BaseServer) selfNodeRpcHandlerAsyncGo(timeout time.Duration,client
pCall.ServiceMethod = serviceMethod pCall.ServiceMethod = serviceMethod
pCall.TimeOut = timeout pCall.TimeOut = timeout
client.AddPending(pCall) client.AddPending(pCall)
rpcCancel := RpcCancel{CallSeq: callSeq,Cli: client} rpcCancel := RpcCancel{CallSeq: callSeq, Cli: client}
cancelRpc = rpcCancel.CancelRpc cancelRpc = rpcCancel.CancelRpc
req.requestHandle = func(Returns interface{}, Err RpcError) { req.requestHandle = func(Returns interface{}, Err RpcError) {
@@ -188,15 +188,15 @@ func (server *BaseServer) selfNodeRpcHandlerAsyncGo(timeout time.Duration,client
if callSeq > 0 { if callSeq > 0 {
client.RemovePending(callSeq) client.RemovePending(callSeq)
} }
return emptyCancelRpc,err return emptyCancelRpc, err
} }
return cancelRpc,nil return cancelRpc, nil
} }
func (bs *BaseServer) processRpcRequest(data []byte,connTag string,wrResponse writeResponse) error{ func (server *BaseServer) processRpcRequest(data []byte, connTag string, wrResponse writeResponse) error {
bCompress := (data[0]>>7) > 0 bCompress := (data[0] >> 7) > 0
processor := GetProcessor(data[0]&0x7f) processor := GetProcessor(data[0] & 0x7f)
if processor == nil { if processor == nil {
return errors.New("cannot find processor") return errors.New("cannot find processor")
} }
@@ -207,9 +207,9 @@ func (bs *BaseServer) processRpcRequest(data []byte,connTag string,wrResponse wr
if bCompress == true { if bCompress == true {
var unCompressErr error var unCompressErr error
compressBuff,unCompressErr = compressor.UncompressBlock(byteData) compressBuff, unCompressErr = compressor.UncompressBlock(byteData)
if unCompressErr!= nil { if unCompressErr != nil {
return errors.New("UncompressBlock failed") return errors.New("uncompressBlock failed")
} }
byteData = compressBuff byteData = compressBuff
@@ -225,7 +225,7 @@ func (bs *BaseServer) processRpcRequest(data []byte,connTag string,wrResponse wr
if req.RpcRequestData.GetSeq() > 0 { if req.RpcRequestData.GetSeq() > 0 {
rpcError := RpcError(err.Error()) rpcError := RpcError(err.Error())
if req.RpcRequestData.IsNoReply() == false { if req.RpcRequestData.IsNoReply() == false {
wrResponse(processor,connTag, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError) wrResponse(processor, connTag, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
} }
} }
@@ -238,27 +238,27 @@ func (bs *BaseServer) processRpcRequest(data []byte,connTag string,wrResponse wr
if len(serviceMethod) < 1 { if len(serviceMethod) < 1 {
rpcError := RpcError("rpc request req.ServiceMethod is error") rpcError := RpcError("rpc request req.ServiceMethod is error")
if req.RpcRequestData.IsNoReply() == false { if req.RpcRequestData.IsNoReply() == false {
wrResponse(processor,connTag, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError) wrResponse(processor, connTag, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
} }
ReleaseRpcRequest(req) ReleaseRpcRequest(req)
log.Error("rpc request req.ServiceMethod is error") log.Error("rpc request req.ServiceMethod is error")
return nil return nil
} }
rpcHandler := bs.rpcHandleFinder.FindRpcHandler(serviceMethod[0]) rpcHandler := server.rpcHandleFinder.FindRpcHandler(serviceMethod[0])
if rpcHandler == nil { if rpcHandler == nil {
rpcError := RpcError(fmt.Sprintf("service method %s not config!", req.RpcRequestData.GetServiceMethod())) rpcError := RpcError(fmt.Sprintf("service method %s not config!", req.RpcRequestData.GetServiceMethod()))
if req.RpcRequestData.IsNoReply() == false { if req.RpcRequestData.IsNoReply() == false {
wrResponse(processor,connTag, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError) wrResponse(processor, connTag, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
} }
log.Error("serviceMethod not config",log.String("serviceMethod",req.RpcRequestData.GetServiceMethod())) log.Error("serviceMethod not config", log.String("serviceMethod", req.RpcRequestData.GetServiceMethod()))
ReleaseRpcRequest(req) ReleaseRpcRequest(req)
return nil return nil
} }
if req.RpcRequestData.IsNoReply() == false { if req.RpcRequestData.IsNoReply() == false {
req.requestHandle = func(Returns interface{}, Err RpcError) { req.requestHandle = func(Returns interface{}, Err RpcError) {
wrResponse(processor,connTag, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), Returns, Err) wrResponse(processor, connTag, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), Returns, Err)
ReleaseRpcRequest(req) ReleaseRpcRequest(req)
} }
} }
@@ -266,7 +266,7 @@ func (bs *BaseServer) processRpcRequest(data []byte,connTag string,wrResponse wr
req.inParam, err = rpcHandler.UnmarshalInParam(req.rpcProcessor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetRpcMethodId(), req.RpcRequestData.GetInParam()) req.inParam, err = rpcHandler.UnmarshalInParam(req.rpcProcessor, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetRpcMethodId(), req.RpcRequestData.GetInParam())
if err != nil { if err != nil {
rErr := "Call Rpc " + req.RpcRequestData.GetServiceMethod() + " Param error " + err.Error() rErr := "Call Rpc " + req.RpcRequestData.GetServiceMethod() + " Param error " + err.Error()
log.Error("call rpc param error",log.String("serviceMethod",req.RpcRequestData.GetServiceMethod()),log.ErrorAttr("error",err)) log.Error("call rpc param error", log.String("serviceMethod", req.RpcRequestData.GetServiceMethod()), log.ErrorField("error", err))
if req.requestHandle != nil { if req.requestHandle != nil {
req.requestHandle(nil, RpcError(rErr)) req.requestHandle(nil, RpcError(rErr))
} else { } else {
@@ -281,11 +281,11 @@ func (bs *BaseServer) processRpcRequest(data []byte,connTag string,wrResponse wr
rpcError := RpcError(err.Error()) rpcError := RpcError(err.Error())
if req.RpcRequestData.IsNoReply() { if req.RpcRequestData.IsNoReply() {
wrResponse(processor, connTag,req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError) wrResponse(processor, connTag, req.RpcRequestData.GetServiceMethod(), req.RpcRequestData.GetSeq(), nil, rpcError)
} }
ReleaseRpcRequest(req) ReleaseRpcRequest(req)
} }
return nil return nil
} }

View File

@@ -1,8 +1,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.31.0 // protoc-gen-go v1.31.0
// protoc v3.11.4 // protoc v4.24.0
// source: test/rpc/messagequeue.proto // source: rpcproto/messagequeue.proto
package rpc package rpc
@@ -50,11 +50,11 @@ func (x SubscribeType) String() string {
} }
func (SubscribeType) Descriptor() protoreflect.EnumDescriptor { func (SubscribeType) Descriptor() protoreflect.EnumDescriptor {
return file_test_rpc_messagequeue_proto_enumTypes[0].Descriptor() return file_rpcproto_messagequeue_proto_enumTypes[0].Descriptor()
} }
func (SubscribeType) Type() protoreflect.EnumType { func (SubscribeType) Type() protoreflect.EnumType {
return &file_test_rpc_messagequeue_proto_enumTypes[0] return &file_rpcproto_messagequeue_proto_enumTypes[0]
} }
func (x SubscribeType) Number() protoreflect.EnumNumber { func (x SubscribeType) Number() protoreflect.EnumNumber {
@@ -63,7 +63,7 @@ func (x SubscribeType) Number() protoreflect.EnumNumber {
// Deprecated: Use SubscribeType.Descriptor instead. // Deprecated: Use SubscribeType.Descriptor instead.
func (SubscribeType) EnumDescriptor() ([]byte, []int) { func (SubscribeType) EnumDescriptor() ([]byte, []int) {
return file_test_rpc_messagequeue_proto_rawDescGZIP(), []int{0} return file_rpcproto_messagequeue_proto_rawDescGZIP(), []int{0}
} }
type SubscribeMethod int32 type SubscribeMethod int32
@@ -96,11 +96,11 @@ func (x SubscribeMethod) String() string {
} }
func (SubscribeMethod) Descriptor() protoreflect.EnumDescriptor { func (SubscribeMethod) Descriptor() protoreflect.EnumDescriptor {
return file_test_rpc_messagequeue_proto_enumTypes[1].Descriptor() return file_rpcproto_messagequeue_proto_enumTypes[1].Descriptor()
} }
func (SubscribeMethod) Type() protoreflect.EnumType { func (SubscribeMethod) Type() protoreflect.EnumType {
return &file_test_rpc_messagequeue_proto_enumTypes[1] return &file_rpcproto_messagequeue_proto_enumTypes[1]
} }
func (x SubscribeMethod) Number() protoreflect.EnumNumber { func (x SubscribeMethod) Number() protoreflect.EnumNumber {
@@ -109,7 +109,7 @@ func (x SubscribeMethod) Number() protoreflect.EnumNumber {
// Deprecated: Use SubscribeMethod.Descriptor instead. // Deprecated: Use SubscribeMethod.Descriptor instead.
func (SubscribeMethod) EnumDescriptor() ([]byte, []int) { func (SubscribeMethod) EnumDescriptor() ([]byte, []int) {
return file_test_rpc_messagequeue_proto_rawDescGZIP(), []int{1} return file_rpcproto_messagequeue_proto_rawDescGZIP(), []int{1}
} }
type DBQueuePopReq struct { type DBQueuePopReq struct {
@@ -127,7 +127,7 @@ type DBQueuePopReq struct {
func (x *DBQueuePopReq) Reset() { func (x *DBQueuePopReq) Reset() {
*x = DBQueuePopReq{} *x = DBQueuePopReq{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_test_rpc_messagequeue_proto_msgTypes[0] mi := &file_rpcproto_messagequeue_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -140,7 +140,7 @@ func (x *DBQueuePopReq) String() string {
func (*DBQueuePopReq) ProtoMessage() {} func (*DBQueuePopReq) ProtoMessage() {}
func (x *DBQueuePopReq) ProtoReflect() protoreflect.Message { func (x *DBQueuePopReq) ProtoReflect() protoreflect.Message {
mi := &file_test_rpc_messagequeue_proto_msgTypes[0] mi := &file_rpcproto_messagequeue_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -153,7 +153,7 @@ func (x *DBQueuePopReq) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBQueuePopReq.ProtoReflect.Descriptor instead. // Deprecated: Use DBQueuePopReq.ProtoReflect.Descriptor instead.
func (*DBQueuePopReq) Descriptor() ([]byte, []int) { func (*DBQueuePopReq) Descriptor() ([]byte, []int) {
return file_test_rpc_messagequeue_proto_rawDescGZIP(), []int{0} return file_rpcproto_messagequeue_proto_rawDescGZIP(), []int{0}
} }
func (x *DBQueuePopReq) GetCustomerId() string { func (x *DBQueuePopReq) GetCustomerId() string {
@@ -203,7 +203,7 @@ type DBQueuePopRes struct {
func (x *DBQueuePopRes) Reset() { func (x *DBQueuePopRes) Reset() {
*x = DBQueuePopRes{} *x = DBQueuePopRes{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_test_rpc_messagequeue_proto_msgTypes[1] mi := &file_rpcproto_messagequeue_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -216,7 +216,7 @@ func (x *DBQueuePopRes) String() string {
func (*DBQueuePopRes) ProtoMessage() {} func (*DBQueuePopRes) ProtoMessage() {}
func (x *DBQueuePopRes) ProtoReflect() protoreflect.Message { func (x *DBQueuePopRes) ProtoReflect() protoreflect.Message {
mi := &file_test_rpc_messagequeue_proto_msgTypes[1] mi := &file_rpcproto_messagequeue_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -229,7 +229,7 @@ func (x *DBQueuePopRes) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBQueuePopRes.ProtoReflect.Descriptor instead. // Deprecated: Use DBQueuePopRes.ProtoReflect.Descriptor instead.
func (*DBQueuePopRes) Descriptor() ([]byte, []int) { func (*DBQueuePopRes) Descriptor() ([]byte, []int) {
return file_test_rpc_messagequeue_proto_rawDescGZIP(), []int{1} return file_rpcproto_messagequeue_proto_rawDescGZIP(), []int{1}
} }
func (x *DBQueuePopRes) GetQueueName() string { func (x *DBQueuePopRes) GetQueueName() string {
@@ -255,7 +255,7 @@ type DBQueueSubscribeReq struct {
SubType SubscribeType `protobuf:"varint,1,opt,name=SubType,proto3,enum=SubscribeType" json:"SubType,omitempty"` //订阅类型 SubType SubscribeType `protobuf:"varint,1,opt,name=SubType,proto3,enum=SubscribeType" json:"SubType,omitempty"` //订阅类型
Method SubscribeMethod `protobuf:"varint,2,opt,name=Method,proto3,enum=SubscribeMethod" json:"Method,omitempty"` //订阅方法 Method SubscribeMethod `protobuf:"varint,2,opt,name=Method,proto3,enum=SubscribeMethod" json:"Method,omitempty"` //订阅方法
CustomerId string `protobuf:"bytes,3,opt,name=CustomerId,proto3" json:"CustomerId,omitempty"` //消费者Id CustomerId string `protobuf:"bytes,3,opt,name=CustomerId,proto3" json:"CustomerId,omitempty"` //消费者Id
FromNodeId int32 `protobuf:"varint,4,opt,name=FromNodeId,proto3" json:"FromNodeId,omitempty"` FromNodeId string `protobuf:"bytes,4,opt,name=FromNodeId,proto3" json:"FromNodeId,omitempty"`
RpcMethod string `protobuf:"bytes,5,opt,name=RpcMethod,proto3" json:"RpcMethod,omitempty"` RpcMethod string `protobuf:"bytes,5,opt,name=RpcMethod,proto3" json:"RpcMethod,omitempty"`
TopicName string `protobuf:"bytes,6,opt,name=TopicName,proto3" json:"TopicName,omitempty"` //主题名称 TopicName string `protobuf:"bytes,6,opt,name=TopicName,proto3" json:"TopicName,omitempty"` //主题名称
StartIndex uint64 `protobuf:"varint,7,opt,name=StartIndex,proto3" json:"StartIndex,omitempty"` //开始位置 ,格式前4位是时间戳秒后面是序号。如果填0时服务自动修改成(4bit 当前时间秒)| (0000 4bit) StartIndex uint64 `protobuf:"varint,7,opt,name=StartIndex,proto3" json:"StartIndex,omitempty"` //开始位置 ,格式前4位是时间戳秒后面是序号。如果填0时服务自动修改成(4bit 当前时间秒)| (0000 4bit)
@@ -265,7 +265,7 @@ type DBQueueSubscribeReq struct {
func (x *DBQueueSubscribeReq) Reset() { func (x *DBQueueSubscribeReq) Reset() {
*x = DBQueueSubscribeReq{} *x = DBQueueSubscribeReq{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_test_rpc_messagequeue_proto_msgTypes[2] mi := &file_rpcproto_messagequeue_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -278,7 +278,7 @@ func (x *DBQueueSubscribeReq) String() string {
func (*DBQueueSubscribeReq) ProtoMessage() {} func (*DBQueueSubscribeReq) ProtoMessage() {}
func (x *DBQueueSubscribeReq) ProtoReflect() protoreflect.Message { func (x *DBQueueSubscribeReq) ProtoReflect() protoreflect.Message {
mi := &file_test_rpc_messagequeue_proto_msgTypes[2] mi := &file_rpcproto_messagequeue_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -291,7 +291,7 @@ func (x *DBQueueSubscribeReq) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBQueueSubscribeReq.ProtoReflect.Descriptor instead. // Deprecated: Use DBQueueSubscribeReq.ProtoReflect.Descriptor instead.
func (*DBQueueSubscribeReq) Descriptor() ([]byte, []int) { func (*DBQueueSubscribeReq) Descriptor() ([]byte, []int) {
return file_test_rpc_messagequeue_proto_rawDescGZIP(), []int{2} return file_rpcproto_messagequeue_proto_rawDescGZIP(), []int{2}
} }
func (x *DBQueueSubscribeReq) GetSubType() SubscribeType { func (x *DBQueueSubscribeReq) GetSubType() SubscribeType {
@@ -315,11 +315,11 @@ func (x *DBQueueSubscribeReq) GetCustomerId() string {
return "" return ""
} }
func (x *DBQueueSubscribeReq) GetFromNodeId() int32 { func (x *DBQueueSubscribeReq) GetFromNodeId() string {
if x != nil { if x != nil {
return x.FromNodeId return x.FromNodeId
} }
return 0 return ""
} }
func (x *DBQueueSubscribeReq) GetRpcMethod() string { func (x *DBQueueSubscribeReq) GetRpcMethod() string {
@@ -359,7 +359,7 @@ type DBQueueSubscribeRes struct {
func (x *DBQueueSubscribeRes) Reset() { func (x *DBQueueSubscribeRes) Reset() {
*x = DBQueueSubscribeRes{} *x = DBQueueSubscribeRes{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_test_rpc_messagequeue_proto_msgTypes[3] mi := &file_rpcproto_messagequeue_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -372,7 +372,7 @@ func (x *DBQueueSubscribeRes) String() string {
func (*DBQueueSubscribeRes) ProtoMessage() {} func (*DBQueueSubscribeRes) ProtoMessage() {}
func (x *DBQueueSubscribeRes) ProtoReflect() protoreflect.Message { func (x *DBQueueSubscribeRes) ProtoReflect() protoreflect.Message {
mi := &file_test_rpc_messagequeue_proto_msgTypes[3] mi := &file_rpcproto_messagequeue_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -385,7 +385,7 @@ func (x *DBQueueSubscribeRes) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBQueueSubscribeRes.ProtoReflect.Descriptor instead. // Deprecated: Use DBQueueSubscribeRes.ProtoReflect.Descriptor instead.
func (*DBQueueSubscribeRes) Descriptor() ([]byte, []int) { func (*DBQueueSubscribeRes) Descriptor() ([]byte, []int) {
return file_test_rpc_messagequeue_proto_rawDescGZIP(), []int{3} return file_rpcproto_messagequeue_proto_rawDescGZIP(), []int{3}
} }
type DBQueuePublishReq struct { type DBQueuePublishReq struct {
@@ -400,7 +400,7 @@ type DBQueuePublishReq struct {
func (x *DBQueuePublishReq) Reset() { func (x *DBQueuePublishReq) Reset() {
*x = DBQueuePublishReq{} *x = DBQueuePublishReq{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_test_rpc_messagequeue_proto_msgTypes[4] mi := &file_rpcproto_messagequeue_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -413,7 +413,7 @@ func (x *DBQueuePublishReq) String() string {
func (*DBQueuePublishReq) ProtoMessage() {} func (*DBQueuePublishReq) ProtoMessage() {}
func (x *DBQueuePublishReq) ProtoReflect() protoreflect.Message { func (x *DBQueuePublishReq) ProtoReflect() protoreflect.Message {
mi := &file_test_rpc_messagequeue_proto_msgTypes[4] mi := &file_rpcproto_messagequeue_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -426,7 +426,7 @@ func (x *DBQueuePublishReq) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBQueuePublishReq.ProtoReflect.Descriptor instead. // Deprecated: Use DBQueuePublishReq.ProtoReflect.Descriptor instead.
func (*DBQueuePublishReq) Descriptor() ([]byte, []int) { func (*DBQueuePublishReq) Descriptor() ([]byte, []int) {
return file_test_rpc_messagequeue_proto_rawDescGZIP(), []int{4} return file_rpcproto_messagequeue_proto_rawDescGZIP(), []int{4}
} }
func (x *DBQueuePublishReq) GetTopicName() string { func (x *DBQueuePublishReq) GetTopicName() string {
@@ -452,7 +452,7 @@ type DBQueuePublishRes struct {
func (x *DBQueuePublishRes) Reset() { func (x *DBQueuePublishRes) Reset() {
*x = DBQueuePublishRes{} *x = DBQueuePublishRes{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_test_rpc_messagequeue_proto_msgTypes[5] mi := &file_rpcproto_messagequeue_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -465,7 +465,7 @@ func (x *DBQueuePublishRes) String() string {
func (*DBQueuePublishRes) ProtoMessage() {} func (*DBQueuePublishRes) ProtoMessage() {}
func (x *DBQueuePublishRes) ProtoReflect() protoreflect.Message { func (x *DBQueuePublishRes) ProtoReflect() protoreflect.Message {
mi := &file_test_rpc_messagequeue_proto_msgTypes[5] mi := &file_rpcproto_messagequeue_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -478,13 +478,13 @@ func (x *DBQueuePublishRes) ProtoReflect() protoreflect.Message {
// Deprecated: Use DBQueuePublishRes.ProtoReflect.Descriptor instead. // Deprecated: Use DBQueuePublishRes.ProtoReflect.Descriptor instead.
func (*DBQueuePublishRes) Descriptor() ([]byte, []int) { func (*DBQueuePublishRes) Descriptor() ([]byte, []int) {
return file_test_rpc_messagequeue_proto_rawDescGZIP(), []int{5} return file_rpcproto_messagequeue_proto_rawDescGZIP(), []int{5}
} }
var File_test_rpc_messagequeue_proto protoreflect.FileDescriptor var File_rpcproto_messagequeue_proto protoreflect.FileDescriptor
var file_test_rpc_messagequeue_proto_rawDesc = []byte{ var file_rpcproto_messagequeue_proto_rawDesc = []byte{
0x0a, 0x1b, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x0a, 0x1b, 0x72, 0x70, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x71, 0x75, 0x65, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa3, 0x01, 0x67, 0x65, 0x71, 0x75, 0x65, 0x75, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa3, 0x01,
0x0a, 0x0d, 0x44, 0x42, 0x51, 0x75, 0x65, 0x75, 0x65, 0x50, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x12, 0x0a, 0x0d, 0x44, 0x42, 0x51, 0x75, 0x65, 0x75, 0x65, 0x50, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x12,
0x1e, 0x0a, 0x0a, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x1e, 0x0a, 0x0a, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20,
@@ -510,7 +510,7 @@ var file_test_rpc_messagequeue_proto_rawDesc = []byte{
0x6f, 0x64, 0x52, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x43, 0x75, 0x6f, 0x64, 0x52, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x43, 0x75,
0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x46, 0x72, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x46, 0x72,
0x6f, 0x6d, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6f, 0x6d, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x52, 0x70, 0x46, 0x72, 0x6f, 0x6d, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x52, 0x70,
0x63, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x52, 0x63, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x52,
0x70, 0x63, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x6f, 0x70, 0x69, 0x70, 0x63, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x6f, 0x70, 0x69,
@@ -539,20 +539,20 @@ var file_test_rpc_messagequeue_proto_rawDesc = []byte{
} }
var ( var (
file_test_rpc_messagequeue_proto_rawDescOnce sync.Once file_rpcproto_messagequeue_proto_rawDescOnce sync.Once
file_test_rpc_messagequeue_proto_rawDescData = file_test_rpc_messagequeue_proto_rawDesc file_rpcproto_messagequeue_proto_rawDescData = file_rpcproto_messagequeue_proto_rawDesc
) )
func file_test_rpc_messagequeue_proto_rawDescGZIP() []byte { func file_rpcproto_messagequeue_proto_rawDescGZIP() []byte {
file_test_rpc_messagequeue_proto_rawDescOnce.Do(func() { file_rpcproto_messagequeue_proto_rawDescOnce.Do(func() {
file_test_rpc_messagequeue_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_rpc_messagequeue_proto_rawDescData) file_rpcproto_messagequeue_proto_rawDescData = protoimpl.X.CompressGZIP(file_rpcproto_messagequeue_proto_rawDescData)
}) })
return file_test_rpc_messagequeue_proto_rawDescData return file_rpcproto_messagequeue_proto_rawDescData
} }
var file_test_rpc_messagequeue_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_rpcproto_messagequeue_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_test_rpc_messagequeue_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_rpcproto_messagequeue_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_test_rpc_messagequeue_proto_goTypes = []interface{}{ var file_rpcproto_messagequeue_proto_goTypes = []interface{}{
(SubscribeType)(0), // 0: SubscribeType (SubscribeType)(0), // 0: SubscribeType
(SubscribeMethod)(0), // 1: SubscribeMethod (SubscribeMethod)(0), // 1: SubscribeMethod
(*DBQueuePopReq)(nil), // 2: DBQueuePopReq (*DBQueuePopReq)(nil), // 2: DBQueuePopReq
@@ -562,7 +562,7 @@ var file_test_rpc_messagequeue_proto_goTypes = []interface{}{
(*DBQueuePublishReq)(nil), // 6: DBQueuePublishReq (*DBQueuePublishReq)(nil), // 6: DBQueuePublishReq
(*DBQueuePublishRes)(nil), // 7: DBQueuePublishRes (*DBQueuePublishRes)(nil), // 7: DBQueuePublishRes
} }
var file_test_rpc_messagequeue_proto_depIdxs = []int32{ var file_rpcproto_messagequeue_proto_depIdxs = []int32{
0, // 0: DBQueueSubscribeReq.SubType:type_name -> SubscribeType 0, // 0: DBQueueSubscribeReq.SubType:type_name -> SubscribeType
1, // 1: DBQueueSubscribeReq.Method:type_name -> SubscribeMethod 1, // 1: DBQueueSubscribeReq.Method:type_name -> SubscribeMethod
2, // [2:2] is the sub-list for method output_type 2, // [2:2] is the sub-list for method output_type
@@ -572,13 +572,13 @@ var file_test_rpc_messagequeue_proto_depIdxs = []int32{
0, // [0:2] is the sub-list for field type_name 0, // [0:2] is the sub-list for field type_name
} }
func init() { file_test_rpc_messagequeue_proto_init() } func init() { file_rpcproto_messagequeue_proto_init() }
func file_test_rpc_messagequeue_proto_init() { func file_rpcproto_messagequeue_proto_init() {
if File_test_rpc_messagequeue_proto != nil { if File_rpcproto_messagequeue_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled { if !protoimpl.UnsafeEnabled {
file_test_rpc_messagequeue_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { file_rpcproto_messagequeue_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DBQueuePopReq); i { switch v := v.(*DBQueuePopReq); i {
case 0: case 0:
return &v.state return &v.state
@@ -590,7 +590,7 @@ func file_test_rpc_messagequeue_proto_init() {
return nil return nil
} }
} }
file_test_rpc_messagequeue_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { file_rpcproto_messagequeue_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DBQueuePopRes); i { switch v := v.(*DBQueuePopRes); i {
case 0: case 0:
return &v.state return &v.state
@@ -602,7 +602,7 @@ func file_test_rpc_messagequeue_proto_init() {
return nil return nil
} }
} }
file_test_rpc_messagequeue_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { file_rpcproto_messagequeue_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DBQueueSubscribeReq); i { switch v := v.(*DBQueueSubscribeReq); i {
case 0: case 0:
return &v.state return &v.state
@@ -614,7 +614,7 @@ func file_test_rpc_messagequeue_proto_init() {
return nil return nil
} }
} }
file_test_rpc_messagequeue_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { file_rpcproto_messagequeue_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DBQueueSubscribeRes); i { switch v := v.(*DBQueueSubscribeRes); i {
case 0: case 0:
return &v.state return &v.state
@@ -626,7 +626,7 @@ func file_test_rpc_messagequeue_proto_init() {
return nil return nil
} }
} }
file_test_rpc_messagequeue_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { file_rpcproto_messagequeue_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DBQueuePublishReq); i { switch v := v.(*DBQueuePublishReq); i {
case 0: case 0:
return &v.state return &v.state
@@ -638,7 +638,7 @@ func file_test_rpc_messagequeue_proto_init() {
return nil return nil
} }
} }
file_test_rpc_messagequeue_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { file_rpcproto_messagequeue_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DBQueuePublishRes); i { switch v := v.(*DBQueuePublishRes); i {
case 0: case 0:
return &v.state return &v.state
@@ -655,19 +655,19 @@ func file_test_rpc_messagequeue_proto_init() {
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_test_rpc_messagequeue_proto_rawDesc, RawDescriptor: file_rpcproto_messagequeue_proto_rawDesc,
NumEnums: 2, NumEnums: 2,
NumMessages: 6, NumMessages: 6,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },
GoTypes: file_test_rpc_messagequeue_proto_goTypes, GoTypes: file_rpcproto_messagequeue_proto_goTypes,
DependencyIndexes: file_test_rpc_messagequeue_proto_depIdxs, DependencyIndexes: file_rpcproto_messagequeue_proto_depIdxs,
EnumInfos: file_test_rpc_messagequeue_proto_enumTypes, EnumInfos: file_rpcproto_messagequeue_proto_enumTypes,
MessageInfos: file_test_rpc_messagequeue_proto_msgTypes, MessageInfos: file_rpcproto_messagequeue_proto_msgTypes,
}.Build() }.Build()
File_test_rpc_messagequeue_proto = out.File File_rpcproto_messagequeue_proto = out.File
file_test_rpc_messagequeue_proto_rawDesc = nil file_rpcproto_messagequeue_proto_rawDesc = nil
file_test_rpc_messagequeue_proto_goTypes = nil file_rpcproto_messagequeue_proto_goTypes = nil
file_test_rpc_messagequeue_proto_depIdxs = nil file_rpcproto_messagequeue_proto_depIdxs = nil
} }

View File

@@ -31,7 +31,7 @@ message DBQueueSubscribeReq {
SubscribeType SubType = 1; //订阅类型 SubscribeType SubType = 1; //订阅类型
SubscribeMethod Method = 2; //订阅方法 SubscribeMethod Method = 2; //订阅方法
string CustomerId = 3; //消费者Id string CustomerId = 3; //消费者Id
int32 FromNodeId = 4; string FromNodeId = 4;
string RpcMethod = 5; string RpcMethod = 5;
string TopicName = 6; //主题名称 string TopicName = 6; //主题名称
uint64 StartIndex = 7; //开始位置 ,格式前4位是时间戳秒后面是序号。如果填0时服务自动修改成(4bit 当前时间秒)| (0000 4bit) uint64 StartIndex = 7; //开始位置 ,格式前4位是时间戳秒后面是序号。如果填0时服务自动修改成(4bit 当前时间秒)| (0000 4bit)

View File

@@ -1,90 +1,91 @@
package rpc package rpc
import ( import (
"github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/network" "github.com/duanhf2012/origin/v2/network"
"github.com/nats-io/nats.go"
"reflect" "reflect"
"time" "time"
"github.com/nats-io/nats.go"
"github.com/duanhf2012/origin/v2/log"
) )
//跨结点连接的Client // NatsClient 跨结点连接的Client
type NatsClient struct { type NatsClient struct {
localNodeId string localNodeId string
notifyEventFun NotifyEventFun notifyEventFun NotifyEventFun
natsConn *nats.Conn natsConn *nats.Conn
client *Client client *Client
} }
func (nc *NatsClient) Start(natsConn *nats.Conn) error{ func (nc *NatsClient) Start(natsConn *nats.Conn) error {
nc.natsConn = natsConn nc.natsConn = natsConn
_,err := nc.natsConn.QueueSubscribe("oc."+nc.localNodeId, "oc",nc.onSubscribe) _, err := nc.natsConn.QueueSubscribe("oc."+nc.localNodeId, "oc", nc.onSubscribe)
return err return err
} }
func (nc *NatsClient) onSubscribe(msg *nats.Msg){ func (nc *NatsClient) onSubscribe(msg *nats.Msg) {
//处理消息 //处理消息
nc.client.processRpcResponse(msg.Data) nc.client.processRpcResponse(msg.Data)
} }
func (nc *NatsClient) SetConn(conn *network.TCPConn){ func (nc *NatsClient) SetConn(conn *network.NetConn) {
} }
func (nc *NatsClient) Close(waitDone bool){ func (nc *NatsClient) Close(waitDone bool) {
} }
func (nc *NatsClient) Run(){ func (nc *NatsClient) Run() {
} }
func (nc *NatsClient) OnClose(){ func (nc *NatsClient) OnClose() {
} }
func (rc *NatsClient) Bind(server IServer){ func (nc *NatsClient) Bind(server IServer) {
s := server.(*NatsServer) s := server.(*NatsServer)
rc.natsConn = s.natsConn nc.natsConn = s.natsConn
} }
func (rc *NatsClient) Go(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call { func (nc *NatsClient) Go(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call {
_, processor := GetProcessorType(args) _, processor := GetProcessorType(args)
InParam, err := processor.Marshal(args) InParam, err := processor.Marshal(args)
if err != nil { if err != nil {
log.Error("Marshal is fail",log.ErrorAttr("error",err)) log.Error("Marshal is fail", log.ErrorField("error", err))
call := MakeCall() call := MakeCall()
call.DoError(err) call.DoError(err)
return call return call
} }
return rc.client.rawGo(nodeId,rc,timeout,rpcHandler,processor, noReply, 0, serviceMethod, InParam, reply) return nc.client.rawGo(nodeId, nc, timeout, rpcHandler, processor, noReply, 0, serviceMethod, InParam, reply)
} }
func (rc *NatsClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call { func (nc *NatsClient) RawGo(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call {
return rc.client.rawGo(nodeId,rc,timeout,rpcHandler,processor, noReply, rpcMethodId, serviceMethod, rawArgs, reply) return nc.client.rawGo(nodeId, nc, timeout, rpcHandler, processor, noReply, rpcMethodId, serviceMethod, rawArgs, reply)
} }
func (rc *NatsClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error) { func (nc *NatsClient) AsyncCall(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{}) (CancelRpc, error) {
cancelRpc,err := rc.client.asyncCall(nodeId,rc,timeout,rpcHandler, serviceMethod, callback, args, replyParam,cancelable) cancelRpc, err := nc.client.asyncCall(nodeId, nc, timeout, rpcHandler, serviceMethod, callback, args, replyParam)
if err != nil { if err != nil {
callback.Call([]reflect.Value{reflect.ValueOf(replyParam), reflect.ValueOf(err)}) callback.Call([]reflect.Value{reflect.ValueOf(replyParam), reflect.ValueOf(err)})
} }
return cancelRpc,nil return cancelRpc, nil
} }
func (rc *NatsClient) WriteMsg (nodeId string,args ...[]byte) error{ func (nc *NatsClient) WriteMsg(nodeId string, args ...[]byte) error {
buff := make([]byte,0,4096) buff := make([]byte, 0, 4096)
for _,ar := range args { for _, ar := range args {
buff = append(buff,ar...) buff = append(buff, ar...)
} }
var msg nats.Msg var msg nats.Msg
msg.Subject = "os."+nodeId msg.Subject = "os." + nodeId
msg.Data = buff msg.Data = buff
msg.Header = nats.Header{} msg.Header = nats.Header{}
msg.Header.Set("fnode",rc.localNodeId) msg.Header.Set("fnode", nc.localNodeId)
return rc.natsConn.PublishMsg(&msg) return nc.natsConn.PublishMsg(&msg)
} }
func (rc *NatsClient) IsConnected() bool{ func (nc *NatsClient) IsConnected() bool {
return rc.natsConn!=nil && rc.natsConn.Status() == nats.CONNECTED return nc.natsConn != nil && nc.natsConn.Status() == nats.CONNECTED
} }

View File

@@ -1,66 +1,66 @@
package rpc package rpc
import ( import (
"github.com/nats-io/nats.go"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"github.com/nats-io/nats.go"
"time" "time"
) )
type NatsServer struct { type NatsServer struct {
BaseServer BaseServer
natsUrl string natsUrl string
natsConn *nats.Conn natsConn *nats.Conn
NoRandomize bool NoRandomize bool
nodeSubTopic string nodeSubTopic string
compressBytesLen int compressBytesLen int
notifyEventFun NotifyEventFun notifyEventFun NotifyEventFun
} }
const reconnectWait = 3*time.Second const reconnectWait = 3 * time.Second
func (ns *NatsServer) Start() error{
func (ns *NatsServer) Start() error {
var err error var err error
var options []nats.Option var options []nats.Option
options = append(options,nats.DisconnectErrHandler(func(nc *nats.Conn, err error) { options = append(options, nats.DisconnectErrHandler(func(nc *nats.Conn, err error) {
log.Error("nats is disconnected",log.String("connUrl",nc.ConnectedUrl())) log.Error("nats is disconnected", log.String("connUrl", nc.ConnectedUrl()))
ns.notifyEventFun(&NatsConnEvent{IsConnect:false}) ns.notifyEventFun(&NatsConnEvent{IsConnect: false})
})) }))
options = append(options,nats.ConnectHandler(func(nc *nats.Conn) { options = append(options, nats.ConnectHandler(func(nc *nats.Conn) {
log.Info("nats is connected",log.String("connUrl",nc.ConnectedUrl())) log.Info("nats is connected", log.String("connUrl", nc.ConnectedUrl()))
ns.notifyEventFun(&NatsConnEvent{IsConnect:true}) ns.notifyEventFun(&NatsConnEvent{IsConnect: true})
//log.Error("nats is connect",log.String("connUrl",nc.ConnectedUrl()))
})) }))
options = append(options,nats.ReconnectHandler(func(nc *nats.Conn) { options = append(options, nats.ReconnectHandler(func(nc *nats.Conn) {
ns.notifyEventFun(&NatsConnEvent{IsConnect:true}) ns.notifyEventFun(&NatsConnEvent{IsConnect: true})
log.Info("nats is reconnected",log.String("connUrl",nc.ConnectedUrl())) log.Info("nats is reconnected", log.String("connUrl", nc.ConnectedUrl()))
})) }))
options = append(options,nats.MaxReconnects(-1)) options = append(options, nats.MaxReconnects(-1))
options = append(options,nats.ReconnectWait(reconnectWait)) options = append(options, nats.ReconnectWait(reconnectWait))
if ns.NoRandomize { if ns.NoRandomize {
options = append(options,nats.DontRandomize()) options = append(options, nats.DontRandomize())
} }
ns.natsConn,err = nats.Connect(ns.natsUrl,options...) ns.natsConn, err = nats.Connect(ns.natsUrl, options...)
if err != nil { if err != nil {
log.Error("Connect to nats fail",log.String("natsUrl",ns.natsUrl),log.ErrorAttr("err",err)) log.Error("Connect to nats fail", log.String("natsUrl", ns.natsUrl), log.ErrorField("err", err))
return err return err
} }
//开始订阅 //开始订阅
_,err = ns.natsConn.QueueSubscribe(ns.nodeSubTopic,"os", func(msg *nats.Msg) { _, err = ns.natsConn.QueueSubscribe(ns.nodeSubTopic, "os", func(msg *nats.Msg) {
ns.processRpcRequest(msg.Data,msg.Header.Get("fnode"),ns.WriteResponse) ns.processRpcRequest(msg.Data, msg.Header.Get("fnode"), ns.WriteResponse)
}) })
return err return err
} }
func (ns *NatsServer) WriteResponse(processor IRpcProcessor, nodeId string,serviceMethod string, seq uint64, reply interface{}, rpcError RpcError){ func (ns *NatsServer) WriteResponse(processor IRpcProcessor, nodeId string, serviceMethod string, seq uint64, reply interface{}, rpcError RpcError) {
var mReply []byte var mReply []byte
var err error var err error
@@ -77,51 +77,51 @@ func (ns *NatsServer) WriteResponse(processor IRpcProcessor, nodeId string,servi
defer processor.ReleaseRpcResponse(rpcResponse.RpcResponseData) defer processor.ReleaseRpcResponse(rpcResponse.RpcResponseData)
if err != nil { if err != nil {
log.Error("mashal RpcResponseData failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err)) log.Error("marshal RpcResponseData failed", log.String("serviceMethod", serviceMethod), log.ErrorField("error", err))
return return
} }
var compressBuff[]byte var compressBuff []byte
bCompress := uint8(0) bCompress := uint8(0)
if ns.compressBytesLen >0 && len(bytes) >= ns.compressBytesLen { if ns.compressBytesLen > 0 && len(bytes) >= ns.compressBytesLen {
compressBuff,err = compressor.CompressBlock(bytes) compressBuff, err = compressor.CompressBlock(bytes)
if err != nil { if err != nil {
log.Error("CompressBlock failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err)) log.Error("CompressBlock failed", log.String("serviceMethod", serviceMethod), log.ErrorField("error", err))
return return
} }
if len(compressBuff) < len(bytes) { if len(compressBuff) < len(bytes) {
bytes = compressBuff bytes = compressBuff
bCompress = 1<<7 bCompress = 1 << 7
} }
} }
sendData := make([]byte,0,4096) sendData := make([]byte, 0, 4096)
byteTypeAndCompress := []byte{uint8(processor.GetProcessorType())|bCompress} byteTypeAndCompress := []byte{uint8(processor.GetProcessorType()) | bCompress}
sendData = append(sendData,byteTypeAndCompress...) sendData = append(sendData, byteTypeAndCompress...)
sendData = append(sendData,bytes...) sendData = append(sendData, bytes...)
err = ns.natsConn.PublishMsg(&nats.Msg{Subject: "oc."+nodeId, Data: sendData}) err = ns.natsConn.PublishMsg(&nats.Msg{Subject: "oc." + nodeId, Data: sendData})
if cap(compressBuff) >0 { if cap(compressBuff) > 0 {
compressor.CompressBufferCollection(compressBuff) compressor.CompressBufferCollection(compressBuff)
} }
if err != nil { if err != nil {
log.Error("WriteMsg error,Rpc return is fail",log.String("nodeId",nodeId),log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err)) log.Error("WriteMsg error,Rpc return is fail", log.String("nodeId", nodeId), log.String("serviceMethod", serviceMethod), log.ErrorField("error", err))
} }
} }
func (ns *NatsServer) Stop(){ func (ns *NatsServer) Stop() {
if ns.natsConn != nil { if ns.natsConn != nil {
ns.natsConn.Close() ns.natsConn.Close()
} }
} }
func (ns *NatsServer) initServer(natsUrl string, noRandomize bool,localNodeId string,compressBytesLen int,rpcHandleFinder RpcHandleFinder,notifyEventFun NotifyEventFun){ func (ns *NatsServer) initServer(natsUrl string, noRandomize bool, localNodeId string, compressBytesLen int, rpcHandleFinder RpcHandleFinder, notifyEventFun NotifyEventFun) {
ns.natsUrl = natsUrl ns.natsUrl = natsUrl
ns.NoRandomize = noRandomize ns.NoRandomize = noRandomize
ns.localNodeId = localNodeId ns.localNodeId = localNodeId
ns.compressBytesLen = compressBytesLen ns.compressBytesLen = compressBytesLen
ns.notifyEventFun = notifyEventFun ns.notifyEventFun = notifyEventFun
ns.initBaseServer(compressBytesLen,rpcHandleFinder) ns.initBaseServer(compressBytesLen, rpcHandleFinder)
ns.nodeSubTopic = "os."+localNodeId //服务器 ns.nodeSubTopic = "os." + localNodeId //服务器
} }

View File

@@ -1,23 +1,23 @@
package rpc package rpc
import ( import (
"fmt"
"github.com/duanhf2012/origin/v2/util/sync" "github.com/duanhf2012/origin/v2/util/sync"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
"fmt"
) )
type PBProcessor struct { type PBProcessor struct {
} }
var rpcPbResponseDataPool =sync.NewPool(make(chan interface{},10240), func()interface{}{ var rpcPbResponseDataPool = sync.NewPool(make(chan interface{}, 10240), func() interface{} {
return &PBRpcResponseData{} return &PBRpcResponseData{}
}) })
var rpcPbRequestDataPool =sync.NewPool(make(chan interface{},10240), func()interface{}{ var rpcPbRequestDataPool = sync.NewPool(make(chan interface{}, 10240), func() interface{} {
return &PBRpcRequestData{} return &PBRpcRequestData{}
}) })
func (slf *PBRpcRequestData) MakeRequest(seq uint64,rpcMethodId uint32,serviceMethod string,noReply bool,inParam []byte) *PBRpcRequestData{ func (slf *PBRpcRequestData) MakeRequest(seq uint64, rpcMethodId uint32, serviceMethod string, noReply bool, inParam []byte) *PBRpcRequestData {
slf.Seq = seq slf.Seq = seq
slf.RpcMethodId = rpcMethodId slf.RpcMethodId = rpcMethodId
slf.ServiceMethod = serviceMethod slf.ServiceMethod = serviceMethod
@@ -27,8 +27,7 @@ func (slf *PBRpcRequestData) MakeRequest(seq uint64,rpcMethodId uint32,serviceMe
return slf return slf
} }
func (slf *PBRpcResponseData) MakeResponse(seq uint64, err RpcError, reply []byte) *PBRpcResponseData {
func (slf *PBRpcResponseData) MakeRespone(seq uint64,err RpcError,reply []byte) *PBRpcResponseData{
slf.Seq = seq slf.Seq = seq
slf.Error = err.Error() slf.Error = err.Error()
slf.Reply = reply slf.Reply = reply
@@ -36,61 +35,61 @@ func (slf *PBRpcResponseData) MakeRespone(seq uint64,err RpcError,reply []byte)
return slf return slf
} }
func (slf *PBProcessor) Marshal(v interface{}) ([]byte, error){ func (slf *PBProcessor) Marshal(v interface{}) ([]byte, error) {
return proto.Marshal(v.(proto.Message)) return proto.Marshal(v.(proto.Message))
} }
func (slf *PBProcessor) Unmarshal(data []byte, msg interface{}) error{ func (slf *PBProcessor) Unmarshal(data []byte, msg interface{}) error {
protoMsg,ok := msg.(proto.Message) protoMsg, ok := msg.(proto.Message)
if ok == false { if ok == false {
return fmt.Errorf("%+v is not of proto.Message type",msg) return fmt.Errorf("%+v is not of proto.Message type", msg)
} }
return proto.Unmarshal(data, protoMsg) return proto.Unmarshal(data, protoMsg)
} }
func (slf *PBProcessor) MakeRpcRequest(seq uint64,rpcMethodId uint32,serviceMethod string,noReply bool,inParam []byte) IRpcRequestData{ func (slf *PBProcessor) MakeRpcRequest(seq uint64, rpcMethodId uint32, serviceMethod string, noReply bool, inParam []byte) IRpcRequestData {
pGogoPbRpcRequestData := rpcPbRequestDataPool.Get().(*PBRpcRequestData) pGogoPbRpcRequestData := rpcPbRequestDataPool.Get().(*PBRpcRequestData)
pGogoPbRpcRequestData.MakeRequest(seq,rpcMethodId,serviceMethod,noReply,inParam) pGogoPbRpcRequestData.MakeRequest(seq, rpcMethodId, serviceMethod, noReply, inParam)
return pGogoPbRpcRequestData return pGogoPbRpcRequestData
} }
func (slf *PBProcessor) MakeRpcResponse(seq uint64,err RpcError,reply []byte) IRpcResponseData { func (slf *PBProcessor) MakeRpcResponse(seq uint64, err RpcError, reply []byte) IRpcResponseData {
pPBRpcResponseData := rpcPbResponseDataPool.Get().(*PBRpcResponseData) pPBRpcResponseData := rpcPbResponseDataPool.Get().(*PBRpcResponseData)
pPBRpcResponseData.MakeRespone(seq,err,reply) pPBRpcResponseData.MakeResponse(seq, err, reply)
return pPBRpcResponseData return pPBRpcResponseData
} }
func (slf *PBProcessor) ReleaseRpcRequest(rpcRequestData IRpcRequestData){ func (slf *PBProcessor) ReleaseRpcRequest(rpcRequestData IRpcRequestData) {
rpcPbRequestDataPool.Put(rpcRequestData) rpcPbRequestDataPool.Put(rpcRequestData)
} }
func (slf *PBProcessor) ReleaseRpcResponse(rpcResponseData IRpcResponseData){ func (slf *PBProcessor) ReleaseRpcResponse(rpcResponseData IRpcResponseData) {
rpcPbResponseDataPool.Put(rpcResponseData) rpcPbResponseDataPool.Put(rpcResponseData)
} }
func (slf *PBProcessor) IsParse(param interface{}) bool { func (slf *PBProcessor) IsParse(param interface{}) bool {
_,ok := param.(proto.Message) _, ok := param.(proto.Message)
return ok return ok
} }
func (slf *PBProcessor) GetProcessorType() RpcProcessorType{ func (slf *PBProcessor) GetProcessorType() RpcProcessorType {
return RpcProcessorPB return RpcProcessorPB
} }
func (slf *PBProcessor) Clone(src interface{}) (interface{},error){ func (slf *PBProcessor) Clone(src interface{}) (interface{}, error) {
srcMsg,ok := src.(proto.Message) srcMsg, ok := src.(proto.Message)
if ok == false { if ok == false {
return nil,fmt.Errorf("param is not of proto.message type") return nil, fmt.Errorf("param is not of proto.message type")
} }
return proto.Clone(srcMsg),nil return proto.Clone(srcMsg), nil
} }
func (slf *PBRpcRequestData) IsNoReply() bool{ func (slf *PBRpcRequestData) IsNoReply() bool {
return slf.GetNoReply() return slf.GetNoReply()
} }
func (slf *PBRpcResponseData) GetErr() *RpcError { func (slf *PBRpcResponseData) GetErr() *RpcError {
if slf.GetError() == "" { if slf.GetError() == "" {
return nil return nil
} }
@@ -98,9 +97,3 @@ func (slf *PBRpcResponseData) GetErr() *RpcError {
err := RpcError(slf.GetError()) err := RpcError(slf.GetError())
return &err return &err
} }

View File

@@ -6,16 +6,16 @@ import (
"github.com/duanhf2012/origin/v2/network" "github.com/duanhf2012/origin/v2/network"
"math" "math"
"reflect" "reflect"
"runtime"
"sync/atomic" "sync/atomic"
"time" "time"
) )
//跨结点连接的Client // RClient 跨结点连接的Client
type RClient struct { type RClient struct {
selfClient *Client selfClient *Client
network.TCPClient network.TCPClient
conn *network.TCPConn conn *network.NetConn
notifyEventFun NotifyEventFun notifyEventFun NotifyEventFun
} }
@@ -27,7 +27,7 @@ func (rc *RClient) IsConnected() bool {
return rc.conn != nil && rc.conn.IsConnected() == true return rc.conn != nil && rc.conn.IsConnected() == true
} }
func (rc *RClient) GetConn() *network.TCPConn{ func (rc *RClient) GetConn() *network.NetConn {
rc.Lock() rc.Lock()
conn := rc.conn conn := rc.conn
rc.Unlock() rc.Unlock()
@@ -35,61 +35,58 @@ func (rc *RClient) GetConn() *network.TCPConn{
return conn return conn
} }
func (rc *RClient) SetConn(conn *network.TCPConn){ func (rc *RClient) SetConn(conn *network.NetConn) {
rc.Lock() rc.Lock()
rc.conn = conn rc.conn = conn
rc.Unlock() rc.Unlock()
} }
func (rc *RClient) WriteMsg (nodeId string,args ...[]byte) error{ func (rc *RClient) WriteMsg(nodeId string, args ...[]byte) error {
return rc.conn.WriteMsg(args...) return rc.conn.WriteMsg(args...)
} }
func (rc *RClient) Go(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call { func (rc *RClient) Go(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, noReply bool, serviceMethod string, args interface{}, reply interface{}) *Call {
_, processor := GetProcessorType(args) _, processor := GetProcessorType(args)
InParam, err := processor.Marshal(args) InParam, err := processor.Marshal(args)
if err != nil { if err != nil {
log.Error("Marshal is fail",log.ErrorAttr("error",err)) log.Error("Marshal is fail", log.ErrorField("error", err))
call := MakeCall() call := MakeCall()
call.DoError(err) call.DoError(err)
return call return call
} }
return rc.selfClient.rawGo(nodeId,rc,timeout,rpcHandler,processor, noReply, 0, serviceMethod, InParam, reply) return rc.selfClient.rawGo(nodeId, rc, timeout, rpcHandler, processor, noReply, 0, serviceMethod, InParam, reply)
} }
func (rc *RClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHandler,processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call { func (rc *RClient) RawGo(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, processor IRpcProcessor, noReply bool, rpcMethodId uint32, serviceMethod string, rawArgs []byte, reply interface{}) *Call {
return rc.selfClient.rawGo(nodeId,rc,timeout,rpcHandler,processor, noReply, rpcMethodId, serviceMethod, rawArgs, reply) return rc.selfClient.rawGo(nodeId, rc, timeout, rpcHandler, processor, noReply, rpcMethodId, serviceMethod, rawArgs, reply)
} }
func (rc *RClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{},cancelable bool) (CancelRpc,error) { func (rc *RClient) AsyncCall(nodeId string, timeout time.Duration, rpcHandler IRpcHandler, serviceMethod string, callback reflect.Value, args interface{}, replyParam interface{}) (CancelRpc, error) {
cancelRpc,err := rc.selfClient.asyncCall(nodeId,rc,timeout,rpcHandler, serviceMethod, callback, args, replyParam,cancelable) cancelRpc, err := rc.selfClient.asyncCall(nodeId, rc, timeout, rpcHandler, serviceMethod, callback, args, replyParam)
if err != nil { if err != nil {
callback.Call([]reflect.Value{reflect.ValueOf(replyParam), reflect.ValueOf(err)}) callback.Call([]reflect.Value{reflect.ValueOf(replyParam), reflect.ValueOf(err)})
} }
return cancelRpc,nil return cancelRpc, nil
} }
func (rc *RClient) Run() { func (rc *RClient) Run() {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096) log.StackError(fmt.Sprint(r))
l := runtime.Stack(buf, false)
errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString))
} }
}() }()
var eventData RpcConnEvent var eventData RpcConnEvent
eventData.IsConnect = true eventData.IsConnect = true
eventData.NodeId = rc.selfClient.GetTargetNodeId() eventData.NodeId = rc.selfClient.GetTargetNodeId()
rc.notifyEventFun(&eventData) rc.notifyEventFun(&eventData)
for { for {
bytes, err := rc.conn.ReadMsg() bytes, err := rc.conn.ReadMsg()
if err != nil { if err != nil {
log.Error("rclient read msg is failed",log.ErrorAttr("error",err)) log.Error("RClient read msg is failed", log.ErrorField("error", err))
return return
} }
@@ -108,13 +105,13 @@ func (rc *RClient) OnClose() {
rc.notifyEventFun(&connEvent) rc.notifyEventFun(&connEvent)
} }
func NewRClient(targetNodeId string, addr string, maxRpcParamLen uint32,compressBytesLen int,callSet *CallSet,notifyEventFun NotifyEventFun) *Client{ func NewRClient(targetNodeId string, addr string, maxRpcParamLen uint32, compressBytesLen int, callSet *CallSet, notifyEventFun NotifyEventFun) *Client {
client := &Client{} client := &Client{}
client.clientId = atomic.AddUint32(&clientSeq, 1) client.clientId = atomic.AddUint32(&clientSeq, 1)
client.targetNodeId = targetNodeId client.targetNodeId = targetNodeId
client.compressBytesLen = compressBytesLen client.compressBytesLen = compressBytesLen
c:= &RClient{} c := &RClient{}
c.selfClient = client c.selfClient = client
c.Addr = addr c.Addr = addr
c.ConnectInterval = DefaultConnectInterval c.ConnectInterval = DefaultConnectInterval
@@ -140,13 +137,11 @@ func NewRClient(targetNodeId string, addr string, maxRpcParamLen uint32,compress
return client return client
} }
func (rc *RClient) Close(waitDone bool) { func (rc *RClient) Close(waitDone bool) {
rc.TCPClient.Close(waitDone) rc.TCPClient.Close(waitDone)
rc.selfClient.cleanPending() rc.selfClient.cleanPending()
} }
func (rc *RClient) Bind(server IServer) {
func (rc *RClient) Bind(server IServer){ }
}

View File

@@ -3,20 +3,21 @@ package rpc
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"reflect" "reflect"
"runtime"
"strings" "strings"
"time"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
"github.com/duanhf2012/origin/v2/event"
"time"
) )
const maxClusterNode int = 128 const maxClusterNode int = 32
type FuncRpcClient func(nodeId string, serviceMethod string,filterRetire bool, client []*Client) (error, int) type FuncRpcClient func(nodeId string, serviceMethod string, filterRetire bool, client []*Client) (error, []*Client)
type FuncRpcServer func() IServer type FuncRpcServer func() IServer
const NodeIdNull = "" const NodeIdNull = ""
var nilError = reflect.Zero(reflect.TypeOf((*error)(nil)).Elem()) var nilError = reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())
@@ -47,7 +48,7 @@ type RpcMethodInfo struct {
rpcProcessorType RpcProcessorType rpcProcessorType RpcProcessorType
} }
type RawRpcCallBack func(rawData []byte) type RawRpcCallBack func(rawData []byte)
type IRpcHandlerChannel interface { type IRpcHandlerChannel interface {
PushRpcResponse(call *Call) error PushRpcResponse(call *Call) error
@@ -63,10 +64,10 @@ type RpcHandler struct {
funcRpcClient FuncRpcClient funcRpcClient FuncRpcClient
funcRpcServer FuncRpcServer funcRpcServer FuncRpcServer
pClientList []*Client //pClientList []*Client
} }
//type TriggerRpcConnEvent func(bConnect bool, clientSeq uint32, nodeId string) // NotifyEventToAllService type TriggerRpcConnEvent func(bConnect bool, clientSeq uint32, nodeId string)
type NotifyEventToAllService func(event event.IEvent) type NotifyEventToAllService func(event event.IEvent)
type INodeConnListener interface { type INodeConnListener interface {
@@ -85,7 +86,8 @@ type IDiscoveryServiceListener interface {
} }
type CancelRpc func() type CancelRpc func()
func emptyCancelRpc(){}
func emptyCancelRpc() {}
type IRpcHandler interface { type IRpcHandler interface {
IRpcHandlerChannel IRpcHandlerChannel
@@ -94,23 +96,22 @@ type IRpcHandler interface {
GetRpcHandler() IRpcHandler GetRpcHandler() IRpcHandler
HandlerRpcRequest(request *RpcRequest) HandlerRpcRequest(request *RpcRequest)
HandlerRpcResponseCB(call *Call) HandlerRpcResponseCB(call *Call)
CallMethod(client *Client,ServiceMethod string, param interface{},callBack reflect.Value, reply interface{}) error CallMethod(client *Client, ServiceMethod string, param interface{}, callBack reflect.Value, reply interface{}) error
Call(serviceMethod string, args interface{}, reply interface{}) error Call(serviceMethod string, args interface{}, reply interface{}) error
CallNode(nodeId string, serviceMethod string, args interface{}, reply interface{}) error CallNode(nodeId string, serviceMethod string, args interface{}, reply interface{}) error
AsyncCall(serviceMethod string, args interface{}, callback interface{}) error AsyncCall(serviceMethod string, args interface{}, callback interface{}) error
AsyncCallNode(nodeId string, serviceMethod string, args interface{}, callback interface{}) error AsyncCallNode(nodeId string, serviceMethod string, args interface{}, callback interface{}) error
CallWithTimeout(timeout time.Duration,serviceMethod string, args interface{}, reply interface{}) error CallWithTimeout(timeout time.Duration, serviceMethod string, args interface{}, reply interface{}) error
CallNodeWithTimeout(timeout time.Duration,nodeId string, serviceMethod string, args interface{}, reply interface{}) error CallNodeWithTimeout(timeout time.Duration, nodeId string, serviceMethod string, args interface{}, reply interface{}) error
AsyncCallWithTimeout(timeout time.Duration,serviceMethod string, args interface{}, callback interface{}) (CancelRpc,error) AsyncCallWithTimeout(timeout time.Duration, serviceMethod string, args interface{}, callback interface{}) (CancelRpc, error)
AsyncCallNodeWithTimeout(timeout time.Duration,nodeId string, serviceMethod string, args interface{}, callback interface{}) (CancelRpc,error) AsyncCallNodeWithTimeout(timeout time.Duration, nodeId string, serviceMethod string, args interface{}, callback interface{}) (CancelRpc, error)
Go(serviceMethod string, args interface{}) error Go(serviceMethod string, args interface{}) error
GoNode(nodeId string, serviceMethod string, args interface{}) error GoNode(nodeId string, serviceMethod string, args interface{}) error
RawGoNode(rpcProcessorType RpcProcessorType, nodeId string, rpcMethodId uint32, serviceName string, rawArgs []byte) error RawGoNode(rpcProcessorType RpcProcessorType, nodeId string, rpcMethodId uint32, serviceName string, rawArgs []byte) error
CastGo(serviceMethod string, args interface{}) error CastGo(serviceMethod string, args interface{}) error
IsSingleCoroutine() bool
UnmarshalInParam(rpcProcessor IRpcProcessor, serviceMethod string, rawRpcMethodId uint32, inParam []byte) (interface{}, error) UnmarshalInParam(rpcProcessor IRpcProcessor, serviceMethod string, rawRpcMethodId uint32, inParam []byte) (interface{}, error)
GetRpcServer() FuncRpcServer GetRpcServer() FuncRpcServer
} }
@@ -135,7 +136,6 @@ func (handler *RpcHandler) InitRpcHandler(rpcHandler IRpcHandler, getClientFun F
handler.mapFunctions = map[string]RpcMethodInfo{} handler.mapFunctions = map[string]RpcMethodInfo{}
handler.funcRpcClient = getClientFun handler.funcRpcClient = getClientFun
handler.funcRpcServer = getServerFun handler.funcRpcServer = getServerFun
handler.pClientList = make([]*Client, maxClusterNode)
handler.RegisterRpc(rpcHandler) handler.RegisterRpc(rpcHandler)
} }
@@ -164,13 +164,6 @@ func (handler *RpcHandler) suitableMethods(method reflect.Method) error {
//取出输入参数类型 //取出输入参数类型
var rpcMethodInfo RpcMethodInfo var rpcMethodInfo RpcMethodInfo
typ := method.Type typ := method.Type
if typ.NumOut() != 1 {
return fmt.Errorf("%s The number of returned arguments must be 1", method.Name)
}
if typ.Out(0).String() != "error" {
return fmt.Errorf("%s The return parameter must be of type error", method.Name)
}
if typ.NumIn() < 2 || typ.NumIn() > 4 { if typ.NumIn() < 2 || typ.NumIn() > 4 {
return fmt.Errorf("%s Unsupported parameter format", method.Name) return fmt.Errorf("%s Unsupported parameter format", method.Name)
@@ -183,6 +176,18 @@ func (handler *RpcHandler) suitableMethods(method reflect.Method) error {
rpcMethodInfo.hasResponder = true rpcMethodInfo.hasResponder = true
} }
if rpcMethodInfo.hasResponder && typ.NumOut() > 0 {
return fmt.Errorf("%s should not have return parameters", method.Name)
}
if !rpcMethodInfo.hasResponder && typ.NumOut() != 1 {
return fmt.Errorf("%s The number of returned arguments must be 1", method.Name)
}
if !rpcMethodInfo.hasResponder && typ.Out(0).String() != "error" {
return fmt.Errorf("%s The return parameter must be of type error", method.Name)
}
for i := parIdx; i < typ.NumIn(); i++ { for i := parIdx; i < typ.NumIn(); i++ {
if handler.isExportedOrBuiltinType(typ.In(i)) == false { if handler.isExportedOrBuiltinType(typ.In(i)) == false {
return fmt.Errorf("%s Unsupported parameter types", method.Name) return fmt.Errorf("%s Unsupported parameter types", method.Name)
@@ -220,10 +225,7 @@ func (handler *RpcHandler) RegisterRpc(rpcHandler IRpcHandler) error {
func (handler *RpcHandler) HandlerRpcResponseCB(call *Call) { func (handler *RpcHandler) HandlerRpcResponseCB(call *Call) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096) log.StackError(fmt.Sprint(r))
l := runtime.Stack(buf, false)
errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString))
} }
}() }()
@@ -242,10 +244,7 @@ func (handler *RpcHandler) HandlerRpcRequest(request *RpcRequest) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096) log.StackError(fmt.Sprint(r))
l := runtime.Stack(buf, false)
errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString))
rpcErr := RpcError("call error : core dumps") rpcErr := RpcError("call error : core dumps")
if request.requestHandle != nil { if request.requestHandle != nil {
request.requestHandle(nil, rpcErr) request.requestHandle(nil, rpcErr)
@@ -258,12 +257,12 @@ func (handler *RpcHandler) HandlerRpcRequest(request *RpcRequest) {
if rawRpcId > 0 { if rawRpcId > 0 {
v, ok := handler.mapRawFunctions[rawRpcId] v, ok := handler.mapRawFunctions[rawRpcId]
if ok == false { if ok == false {
log.Error("RpcHandler cannot find request rpc id",log.Uint32("rawRpcId",rawRpcId)) log.Error("RpcHandler cannot find request rpc id", log.Uint32("rawRpcId", rawRpcId))
return return
} }
rawData,ok := request.inParam.([]byte) rawData, ok := request.inParam.([]byte)
if ok == false { if ok == false {
log.Error("RpcHandler cannot convert",log.String("RpcHandlerName",handler.rpcHandler.GetName()),log.Uint32("rawRpcId",rawRpcId)) log.Error("RpcHandler cannot convert", log.String("RpcHandlerName", handler.rpcHandler.GetName()), log.Uint32("rawRpcId", rawRpcId))
return return
} }
@@ -274,8 +273,8 @@ func (handler *RpcHandler) HandlerRpcRequest(request *RpcRequest) {
//普通的rpc请求 //普通的rpc请求
v, ok := handler.mapFunctions[request.RpcRequestData.GetServiceMethod()] v, ok := handler.mapFunctions[request.RpcRequestData.GetServiceMethod()]
if ok == false { if ok == false {
err := "RpcHandler " + handler.rpcHandler.GetName() + "cannot find " + request.RpcRequestData.GetServiceMethod() err := "RpcHandler " + handler.rpcHandler.GetName() + " cannot find " + request.RpcRequestData.GetServiceMethod()
log.Error("HandlerRpcRequest cannot find serviceMethod",log.String("RpcHandlerName",handler.rpcHandler.GetName()),log.String("serviceMethod",request.RpcRequestData.GetServiceMethod())) log.Error("HandlerRpcRequest cannot find serviceMethod", log.String("RpcHandlerName", handler.rpcHandler.GetName()), log.String("serviceMethod", request.RpcRequestData.GetServiceMethod()))
if request.requestHandle != nil { if request.requestHandle != nil {
request.requestHandle(nil, RpcError(err)) request.requestHandle(nil, RpcError(err))
} }
@@ -306,29 +305,31 @@ func (handler *RpcHandler) HandlerRpcRequest(request *RpcRequest) {
paramList = append(paramList, oParam) //输出参数 paramList = append(paramList, oParam) //输出参数
} else if request.requestHandle != nil && v.hasResponder == false { //调用方有返回值,但被调用函数没有返回参数 } else if request.requestHandle != nil && v.hasResponder == false { //调用方有返回值,但被调用函数没有返回参数
rErr := "Call Rpc " + request.RpcRequestData.GetServiceMethod() + " without return parameter!" rErr := "Call Rpc " + request.RpcRequestData.GetServiceMethod() + " without return parameter!"
log.Error("call serviceMethod without return parameter",log.String("serviceMethod",request.RpcRequestData.GetServiceMethod())) log.Error("call serviceMethod without return parameter", log.String("serviceMethod", request.RpcRequestData.GetServiceMethod()))
request.requestHandle(nil, RpcError(rErr)) request.requestHandle(nil, RpcError(rErr))
return return
} }
requestHanle := request.requestHandle requestHandle := request.requestHandle
returnValues := v.method.Func.Call(paramList) returnValues := v.method.Func.Call(paramList)
errInter := returnValues[0].Interface() if len(returnValues) > 0 {
if errInter != nil { errInter := returnValues[0].Interface()
err = errInter.(error) if errInter != nil {
err = errInter.(error)
}
} }
if v.hasResponder == false && requestHanle != nil { if v.hasResponder == false && requestHandle != nil {
requestHanle(oParam.Interface(), ConvertError(err)) requestHandle(oParam.Interface(), ConvertError(err))
} }
} }
func (handler *RpcHandler) CallMethod(client *Client,ServiceMethod string, param interface{},callBack reflect.Value, reply interface{}) error { func (handler *RpcHandler) CallMethod(client *Client, ServiceMethod string, param interface{}, callBack reflect.Value, reply interface{}) error {
var err error var err error
v, ok := handler.mapFunctions[ServiceMethod] v, ok := handler.mapFunctions[ServiceMethod]
if ok == false { if ok == false {
err = errors.New("RpcHandler " + handler.rpcHandler.GetName() + " cannot find" + ServiceMethod) err = errors.New("RpcHandler " + handler.rpcHandler.GetName() + " cannot find" + ServiceMethod)
log.Error("CallMethod cannot find serviceMethod",log.String("rpcHandlerName",handler.rpcHandler.GetName()),log.String("serviceMethod",ServiceMethod)) log.Error("CallMethod cannot find serviceMethod", log.String("rpcHandlerName", handler.rpcHandler.GetName()), log.String("serviceMethod", ServiceMethod))
return err return err
} }
@@ -349,31 +350,31 @@ func (handler *RpcHandler) CallMethod(client *Client,ServiceMethod string, param
//有返回值时 //有返回值时
if reply != nil { if reply != nil {
//如果是Call同步调用 //如果是Call同步调用
hander :=func(Returns interface{}, Err RpcError) { hd := func(Returns interface{}, Err RpcError) {
rpcCall := client.RemovePending(callSeq) rpcCall := client.RemovePending(callSeq)
if rpcCall == nil { if rpcCall == nil {
log.Error("cannot find call seq",log.Uint64("seq",callSeq)) log.Error("cannot find call seq", log.Uint64("seq", callSeq))
return return
} }
//解析数据 //解析数据
if len(Err)!=0 { if len(Err) != 0 {
rpcCall.Err = Err rpcCall.Err = Err
}else if Returns != nil { } else if Returns != nil {
_, processor := GetProcessorType(Returns) _, processor := GetProcessorType(Returns)
var bytes []byte var bytes []byte
bytes,rpcCall.Err = processor.Marshal(Returns) bytes, rpcCall.Err = processor.Marshal(Returns)
if rpcCall.Err == nil { if rpcCall.Err == nil {
rpcCall.Err = processor.Unmarshal(bytes,reply) rpcCall.Err = processor.Unmarshal(bytes, reply)
} }
} }
//如果找不到,说明已经超时 //如果找不到,说明已经超时
rpcCall.Reply = reply rpcCall.Reply = reply
rpcCall.done<-rpcCall rpcCall.done <- rpcCall
} }
paramList = append(paramList, reflect.ValueOf(hander)) paramList = append(paramList, reflect.ValueOf(hd))
}else{//无返回值时,是一个requestHandlerNull空回调 } else { //无返回值时,是一个requestHandlerNull空回调
paramList = append(paramList, callBack) paramList = append(paramList, callBack)
} }
paramList = append(paramList, reflect.ValueOf(param)) paramList = append(paramList, reflect.ValueOf(param))
@@ -383,11 +384,11 @@ func (handler *RpcHandler) CallMethod(client *Client,ServiceMethod string, param
//判断返回值是否错误,有错误时则回调 //判断返回值是否错误,有错误时则回调
errInter := returnValues[0].Interface() errInter := returnValues[0].Interface()
if errInter != nil && callBack!=requestHandlerNull{ if errInter != nil && callBack != requestHandlerNull {
err = errInter.(error) err = errInter.(error)
callBack.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)}) callBack.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
} }
}else{ } else {
paramList = append(paramList, reflect.ValueOf(handler.GetRpcHandler())) //接受者 paramList = append(paramList, reflect.ValueOf(handler.GetRpcHandler())) //接受者
paramList = append(paramList, reflect.ValueOf(param)) paramList = append(paramList, reflect.ValueOf(param))
@@ -396,7 +397,7 @@ func (handler *RpcHandler) CallMethod(client *Client,ServiceMethod string, param
//不带返回值参数的RPC函数 //不带返回值参数的RPC函数
if reply == nil { if reply == nil {
paramList = append(paramList, reflect.New(v.outParamValue.Type().Elem())) paramList = append(paramList, reflect.New(v.outParamValue.Type().Elem()))
}else{ } else {
//带返回值参数的RPC函数 //带返回值参数的RPC函数
paramList = append(paramList, reflect.ValueOf(reply)) //输出参数 paramList = append(paramList, reflect.ValueOf(reply)) //输出参数
} }
@@ -413,14 +414,14 @@ func (handler *RpcHandler) CallMethod(client *Client,ServiceMethod string, param
valErr = reflect.ValueOf(err) valErr = reflect.ValueOf(err)
} }
callBack.Call([]reflect.Value{reflect.ValueOf(reply),valErr }) callBack.Call([]reflect.Value{reflect.ValueOf(reply), valErr})
} }
} }
rpcCall := client.FindPending(callSeq) rpcCall := client.FindPending(callSeq)
if rpcCall!=nil { if rpcCall != nil {
err = rpcCall.Done().Err err = rpcCall.Done().Err
if rpcCall.callback!= nil { if rpcCall.callback != nil {
valErr := nilError valErr := nilError
if rpcCall.Err != nil { if rpcCall.Err != nil {
valErr = reflect.ValueOf(rpcCall.Err) valErr = reflect.ValueOf(rpcCall.Err)
@@ -435,25 +436,25 @@ func (handler *RpcHandler) CallMethod(client *Client,ServiceMethod string, param
} }
func (handler *RpcHandler) goRpc(processor IRpcProcessor, bCast bool, nodeId string, serviceMethod string, args interface{}) error { func (handler *RpcHandler) goRpc(processor IRpcProcessor, bCast bool, nodeId string, serviceMethod string, args interface{}) error {
var pClientList [maxClusterNode]*Client pClientList := make([]*Client, 0, maxClusterNode)
err, count := handler.funcRpcClient(nodeId, serviceMethod,false, pClientList[:]) err, pClientList := handler.funcRpcClient(nodeId, serviceMethod, false, pClientList)
if count == 0 { if len(pClientList) == 0 {
if err != nil { if err != nil {
log.Error("call serviceMethod is failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",err)) log.Error("call serviceMethod is failed", log.String("serviceMethod", serviceMethod), log.ErrorField("error", err))
} else { } else {
log.Error("cannot find serviceMethod",log.String("serviceMethod",serviceMethod)) log.Error("cannot find serviceMethod", log.String("serviceMethod", serviceMethod))
} }
return err return err
} }
if count > 1 && bCast == false { if len(pClientList) > 1 && bCast == false {
log.Error("cannot call serviceMethod more then 1 node",log.String("serviceMethod",serviceMethod)) log.Error("cannot call serviceMethod more then 1 node", log.String("serviceMethod", serviceMethod))
return errors.New("cannot call more then 1 node") return errors.New("cannot call more then 1 node")
} }
//2.rpcClient调用 //2.rpcClient调用
for i := 0; i < count; i++ { for i := 0; i < len(pClientList); i++ {
pCall := pClientList[i].Go(pClientList[i].GetTargetNodeId(),DefaultRpcTimeout,handler.rpcHandler,true, serviceMethod, args, nil) pCall := pClientList[i].Go(pClientList[i].GetTargetNodeId(), DefaultRpcTimeout, handler.rpcHandler, true, serviceMethod, args, nil)
if pCall.Err != nil { if pCall.Err != nil {
err = pCall.Err err = pCall.Err
} }
@@ -464,23 +465,23 @@ func (handler *RpcHandler) goRpc(processor IRpcProcessor, bCast bool, nodeId str
return err return err
} }
func (handler *RpcHandler) callRpc(timeout time.Duration,nodeId string, serviceMethod string, args interface{}, reply interface{}) error { func (handler *RpcHandler) callRpc(timeout time.Duration, nodeId string, serviceMethod string, args interface{}, reply interface{}) error {
var pClientList [maxClusterNode]*Client pClientList := make([]*Client, 0, maxClusterNode)
err, count := handler.funcRpcClient(nodeId, serviceMethod,false, pClientList[:]) err, pClientList := handler.funcRpcClient(nodeId, serviceMethod, false, pClientList)
if err != nil { if err != nil {
log.Error("Call serviceMethod is failed",log.ErrorAttr("error",err)) log.Error("Call serviceMethod is failed", log.ErrorField("error", err))
return err return err
} else if count <= 0 { } else if len(pClientList) <= 0 {
err = errors.New("Call serviceMethod is error:cannot find " + serviceMethod) err = errors.New("Call serviceMethod is error:cannot find " + serviceMethod)
log.Error("cannot find serviceMethod",log.String("serviceMethod",serviceMethod)) log.Error("cannot find serviceMethod", log.String("serviceMethod", serviceMethod))
return err return err
} else if count > 1 { } else if len(pClientList) > 1 {
log.Error("Cannot call more then 1 node!",log.String("serviceMethod",serviceMethod)) log.Error("Cannot call more then 1 node!", log.String("serviceMethod", serviceMethod))
return errors.New("cannot call more then 1 node") return errors.New("cannot call more then 1 node")
} }
pClient := pClientList[0] pClient := pClientList[0]
pCall := pClient.Go(pClient.GetTargetNodeId(),timeout,handler.rpcHandler,false, serviceMethod, args, reply) pCall := pClient.Go(pClient.GetTargetNodeId(), timeout, handler.rpcHandler, false, serviceMethod, args, reply)
err = pCall.Done().Err err = pCall.Done().Err
pClient.RemovePending(pCall.Seq) pClient.RemovePending(pCall.Seq)
@@ -488,85 +489,80 @@ func (handler *RpcHandler) callRpc(timeout time.Duration,nodeId string, serviceM
return err return err
} }
func (handler *RpcHandler) asyncCallRpc(timeout time.Duration,nodeId string, serviceMethod string, args interface{}, callback interface{}) (CancelRpc,error) { func (handler *RpcHandler) asyncCallRpc(timeout time.Duration, nodeId string, serviceMethod string, args interface{}, callback interface{}) (CancelRpc, error) {
fVal := reflect.ValueOf(callback) fVal := reflect.ValueOf(callback)
if fVal.Kind() != reflect.Func { if fVal.Kind() != reflect.Func {
err := errors.New("call " + serviceMethod + " input callback param is error!") err := errors.New("call " + serviceMethod + " input callback param is error!")
log.Error("input callback param is error",log.String("serviceMethod",serviceMethod)) log.Error("input callback param is error", log.String("serviceMethod", serviceMethod))
return emptyCancelRpc,err return emptyCancelRpc, err
} }
if fVal.Type().NumIn() != 2 { if fVal.Type().NumIn() != 2 {
err := errors.New("call " + serviceMethod + " callback param function is error!") err := errors.New("call " + serviceMethod + " callback param function is error!")
log.Error("callback param function is error",log.String("serviceMethod",serviceMethod)) log.Error("callback param function is error", log.String("serviceMethod", serviceMethod))
return emptyCancelRpc,err return emptyCancelRpc, err
} }
if fVal.Type().In(0).Kind() != reflect.Ptr || fVal.Type().In(1).String() != "error" { if fVal.Type().In(0).Kind() != reflect.Ptr || fVal.Type().In(1).String() != "error" {
err := errors.New("call " + serviceMethod + " callback param function is error!") err := errors.New("call " + serviceMethod + " callback param function is error!")
log.Error("callback param function is error",log.String("serviceMethod",serviceMethod)) log.Error("callback param function is error", log.String("serviceMethod", serviceMethod))
return emptyCancelRpc,err return emptyCancelRpc, err
} }
reply := reflect.New(fVal.Type().In(0).Elem()).Interface() reply := reflect.New(fVal.Type().In(0).Elem()).Interface()
var pClientList [2]*Client pClientList := make([]*Client, 0, 1)
err, count := handler.funcRpcClient(nodeId, serviceMethod,false, pClientList[:]) err, pClientList := handler.funcRpcClient(nodeId, serviceMethod, false, pClientList[:])
if count == 0 || err != nil { if len(pClientList) == 0 || err != nil {
if err == nil { if err == nil {
if nodeId != NodeIdNull { if nodeId != NodeIdNull {
err = fmt.Errorf("cannot find %s from nodeId %d",serviceMethod,nodeId) err = fmt.Errorf("cannot find %s from nodeId %s", serviceMethod, nodeId)
}else { } else {
err = fmt.Errorf("No %s service found in the origin network",serviceMethod) err = fmt.Errorf("no %s service found in the origin network", serviceMethod)
} }
} }
fVal.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)}) fVal.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
log.Error("cannot find serviceMethod from node",log.String("serviceMethod",serviceMethod),log.String("nodeId",nodeId)) log.Error("cannot find serviceMethod from node", log.String("serviceMethod", serviceMethod), log.String("nodeId", nodeId))
return emptyCancelRpc,nil return emptyCancelRpc, nil
} }
if count > 1 { if len(pClientList) > 1 {
err := errors.New("cannot call more then 1 node") err := errors.New("cannot call more then 1 node")
fVal.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)}) fVal.Call([]reflect.Value{reflect.ValueOf(reply), reflect.ValueOf(err)})
log.Error("cannot call more then 1 node",log.String("serviceMethod",serviceMethod)) log.Error("cannot call more then 1 node", log.String("serviceMethod", serviceMethod))
return emptyCancelRpc,nil return emptyCancelRpc, nil
} }
//2.rpcClient调用 //2.rpcClient调用
//如果调用本结点服务 return pClientList[0].AsyncCall(pClientList[0].GetTargetNodeId(), timeout, handler.rpcHandler, serviceMethod, fVal, args, reply, )
return pClientList[0].AsyncCall(pClientList[0].GetTargetNodeId(),timeout,handler.rpcHandler, serviceMethod, fVal, args, reply,false)
} }
func (handler *RpcHandler) GetName() string { func (handler *RpcHandler) GetName() string {
return handler.rpcHandler.GetName() return handler.rpcHandler.GetName()
} }
func (handler *RpcHandler) IsSingleCoroutine() bool { func (handler *RpcHandler) CallWithTimeout(timeout time.Duration, serviceMethod string, args interface{}, reply interface{}) error {
return handler.rpcHandler.IsSingleCoroutine() return handler.callRpc(timeout, NodeIdNull, serviceMethod, args, reply)
} }
func (handler *RpcHandler) CallWithTimeout(timeout time.Duration,serviceMethod string, args interface{}, reply interface{}) error { func (handler *RpcHandler) CallNodeWithTimeout(timeout time.Duration, nodeId string, serviceMethod string, args interface{}, reply interface{}) error {
return handler.callRpc(timeout,NodeIdNull, serviceMethod, args, reply) return handler.callRpc(timeout, nodeId, serviceMethod, args, reply)
} }
func (handler *RpcHandler) CallNodeWithTimeout(timeout time.Duration,nodeId string, serviceMethod string, args interface{}, reply interface{}) error{ func (handler *RpcHandler) AsyncCallWithTimeout(timeout time.Duration, serviceMethod string, args interface{}, callback interface{}) (CancelRpc, error) {
return handler.callRpc(timeout,nodeId, serviceMethod, args, reply) return handler.asyncCallRpc(timeout, NodeIdNull, serviceMethod, args, callback)
} }
func (handler *RpcHandler) AsyncCallWithTimeout(timeout time.Duration,serviceMethod string, args interface{}, callback interface{}) (CancelRpc,error){ func (handler *RpcHandler) AsyncCallNodeWithTimeout(timeout time.Duration, nodeId string, serviceMethod string, args interface{}, callback interface{}) (CancelRpc, error) {
return handler.asyncCallRpc(timeout,NodeIdNull, serviceMethod, args, callback) return handler.asyncCallRpc(timeout, nodeId, serviceMethod, args, callback)
}
func (handler *RpcHandler) AsyncCallNodeWithTimeout(timeout time.Duration,nodeId string, serviceMethod string, args interface{}, callback interface{}) (CancelRpc,error){
return handler.asyncCallRpc(timeout,nodeId, serviceMethod, args, callback)
} }
func (handler *RpcHandler) AsyncCall(serviceMethod string, args interface{}, callback interface{}) error { func (handler *RpcHandler) AsyncCall(serviceMethod string, args interface{}, callback interface{}) error {
_,err := handler.asyncCallRpc(DefaultRpcTimeout,NodeIdNull, serviceMethod, args, callback) _, err := handler.asyncCallRpc(DefaultRpcTimeout, NodeIdNull, serviceMethod, args, callback)
return err return err
} }
func (handler *RpcHandler) Call(serviceMethod string, args interface{}, reply interface{}) error { func (handler *RpcHandler) Call(serviceMethod string, args interface{}, reply interface{}) error {
return handler.callRpc(DefaultRpcTimeout,NodeIdNull, serviceMethod, args, reply) return handler.callRpc(DefaultRpcTimeout, NodeIdNull, serviceMethod, args, reply)
} }
func (handler *RpcHandler) Go(serviceMethod string, args interface{}) error { func (handler *RpcHandler) Go(serviceMethod string, args interface{}) error {
@@ -574,13 +570,13 @@ func (handler *RpcHandler) Go(serviceMethod string, args interface{}) error {
} }
func (handler *RpcHandler) AsyncCallNode(nodeId string, serviceMethod string, args interface{}, callback interface{}) error { func (handler *RpcHandler) AsyncCallNode(nodeId string, serviceMethod string, args interface{}, callback interface{}) error {
_,err:= handler.asyncCallRpc(DefaultRpcTimeout,nodeId, serviceMethod, args, callback) _, err := handler.asyncCallRpc(DefaultRpcTimeout, nodeId, serviceMethod, args, callback)
return err return err
} }
func (handler *RpcHandler) CallNode(nodeId string, serviceMethod string, args interface{}, reply interface{}) error { func (handler *RpcHandler) CallNode(nodeId string, serviceMethod string, args interface{}, reply interface{}) error {
return handler.callRpc(DefaultRpcTimeout,nodeId, serviceMethod, args, reply) return handler.callRpc(DefaultRpcTimeout, nodeId, serviceMethod, args, reply)
} }
func (handler *RpcHandler) GoNode(nodeId string, serviceMethod string, args interface{}) error { func (handler *RpcHandler) GoNode(nodeId string, serviceMethod string, args interface{}) error {
@@ -593,27 +589,28 @@ func (handler *RpcHandler) CastGo(serviceMethod string, args interface{}) error
func (handler *RpcHandler) RawGoNode(rpcProcessorType RpcProcessorType, nodeId string, rpcMethodId uint32, serviceName string, rawArgs []byte) error { func (handler *RpcHandler) RawGoNode(rpcProcessorType RpcProcessorType, nodeId string, rpcMethodId uint32, serviceName string, rawArgs []byte) error {
processor := GetProcessor(uint8(rpcProcessorType)) processor := GetProcessor(uint8(rpcProcessorType))
err, count := handler.funcRpcClient(nodeId, serviceName,false, handler.pClientList) pClientList := make([]*Client, 0, 1)
if count == 0 || err != nil { err, pClientList := handler.funcRpcClient(nodeId, serviceName, false, pClientList)
log.Error("call serviceMethod is failed",log.ErrorAttr("error",err)) if len(pClientList) == 0 || err != nil {
log.Error("call serviceMethod is failed", log.ErrorField("error", err))
return err return err
} }
if count > 1 { if len(pClientList) > 1 {
err := errors.New("cannot call more then 1 node") err := errors.New("cannot call more then 1 node")
log.Error("cannot call more then 1 node",log.String("serviceName",serviceName)) log.Error("cannot call more then 1 node", log.String("serviceName", serviceName))
return err return err
} }
//2.rpcClient调用 //2.rpcClient调用
//如果调用本结点服务 //如果调用本结点服务
for i := 0; i < count; i++ { for i := 0; i < len(pClientList); i++ {
//跨node调用 //跨node调用
pCall := handler.pClientList[i].RawGo(handler.pClientList[i].GetTargetNodeId(),DefaultRpcTimeout,handler.rpcHandler,processor, true, rpcMethodId, serviceName, rawArgs, nil) pCall := pClientList[i].RawGo(pClientList[i].GetTargetNodeId(), DefaultRpcTimeout, handler.rpcHandler, processor, true, rpcMethodId, serviceName, rawArgs, nil)
if pCall.Err != nil { if pCall.Err != nil {
err = pCall.Err err = pCall.Err
} }
handler.pClientList[i].RemovePending(pCall.Seq) pClientList[i].RemovePending(pCall.Seq)
ReleaseCall(pCall) ReleaseCall(pCall)
} }
@@ -626,7 +623,7 @@ func (handler *RpcHandler) RegRawRpc(rpcMethodId uint32, rawRpcCB RawRpcCallBack
func (handler *RpcHandler) UnmarshalInParam(rpcProcessor IRpcProcessor, serviceMethod string, rawRpcMethodId uint32, inParam []byte) (interface{}, error) { func (handler *RpcHandler) UnmarshalInParam(rpcProcessor IRpcProcessor, serviceMethod string, rawRpcMethodId uint32, inParam []byte) (interface{}, error) {
if rawRpcMethodId > 0 { if rawRpcMethodId > 0 {
return inParam,nil return inParam, nil
} }
v, ok := handler.mapFunctions[serviceMethod] v, ok := handler.mapFunctions[serviceMethod]
@@ -640,7 +637,6 @@ func (handler *RpcHandler) UnmarshalInParam(rpcProcessor IRpcProcessor, serviceM
return param, err return param, err
} }
func (handler *RpcHandler) GetRpcServer() FuncRpcServer {
func (handler *RpcHandler) GetRpcServer() FuncRpcServer{
return handler.funcRpcServer return handler.funcRpcServer
} }

View File

@@ -27,9 +27,6 @@ func (rn *RpcNats) NewNatsClient(targetNodeId string,localNodeId string,callSet
client.clientId = atomic.AddUint32(&clientSeq, 1) client.clientId = atomic.AddUint32(&clientSeq, 1)
client.targetNodeId = targetNodeId client.targetNodeId = targetNodeId
//client.maxCheckCallRpcCount = DefaultMaxCheckCallRpcCount
//client.callRpcTimeout = DefaultRpcTimeout
natsClient := &rn.NatsClient natsClient := &rn.NatsClient
natsClient.localNodeId = localNodeId natsClient.localNodeId = localNodeId
natsClient.client = &client natsClient.client = &client

View File

@@ -7,17 +7,18 @@ import (
"math" "math"
"net" "net"
"reflect" "reflect"
"strings" "strings"
"time" "time"
"runtime"
) )
const Default_ReadWriteDeadline = 15*time.Second const Default_ReadWriteDeadline = 15 * time.Second
type RpcProcessorType uint8 type RpcProcessorType uint8
const ( const (
RpcProcessorJson RpcProcessorType = 0 RpcProcessorJson RpcProcessorType = 0
RpcProcessorPB RpcProcessorType = 1 RpcProcessorPB RpcProcessorType = 1
) )
var arrayProcessor = []IRpcProcessor{&JsonProcessor{}, &PBProcessor{}} var arrayProcessor = []IRpcProcessor{&JsonProcessor{}, &PBProcessor{}}
@@ -28,20 +29,20 @@ type IServer interface {
Start() error Start() error
Stop() Stop()
selfNodeRpcHandlerGo(timeout time.Duration,processor IRpcProcessor, client *Client, noReply bool, handlerName string, rpcMethodId uint32, serviceMethod string, args interface{}, reply interface{}, rawArgs []byte) *Call selfNodeRpcHandlerGo(timeout time.Duration, processor IRpcProcessor, client *Client, noReply bool, handlerName string, rpcMethodId uint32, serviceMethod string, args interface{}, reply interface{}, rawArgs []byte) *Call
myselfRpcHandlerGo(client *Client,handlerName string, serviceMethod string, args interface{},callBack reflect.Value, reply interface{}) error myselfRpcHandlerGo(client *Client, handlerName string, serviceMethod string, args interface{}, callBack reflect.Value, reply interface{}) error
selfNodeRpcHandlerAsyncGo(timeout time.Duration,client *Client, callerRpcHandler IRpcHandler, noReply bool, handlerName string, serviceMethod string, args interface{}, reply interface{}, callback reflect.Value,cancelable bool) (CancelRpc,error) selfNodeRpcHandlerAsyncGo(timeout time.Duration, client *Client, callerRpcHandler IRpcHandler, noReply bool, handlerName string, serviceMethod string, args interface{}, reply interface{}, callback reflect.Value) (CancelRpc, error)
} }
type writeResponse func(processor IRpcProcessor,connTag string, serviceMethod string, seq uint64, reply interface{}, rpcError RpcError) type writeResponse func(processor IRpcProcessor, connTag string, serviceMethod string, seq uint64, reply interface{}, rpcError RpcError)
type Server struct { type Server struct {
BaseServer BaseServer
functions map[interface{}]interface{} functions map[interface{}]interface{}
rpcServer *network.TCPServer rpcServer *network.TCPServer
listenAddr string listenAddr string
maxRpcParamLen uint32 maxRpcParamLen uint32
} }
@@ -73,15 +74,15 @@ func GetProcessor(processorType uint8) IRpcProcessor {
return arrayProcessor[processorType] return arrayProcessor[processorType]
} }
func (server *Server) Init(listenAddr string, maxRpcParamLen uint32,compressBytesLen int,rpcHandleFinder RpcHandleFinder) { func (server *Server) Init(listenAddr string, maxRpcParamLen uint32, compressBytesLen int, rpcHandleFinder RpcHandleFinder) {
server.initBaseServer(compressBytesLen,rpcHandleFinder) server.initBaseServer(compressBytesLen, rpcHandleFinder)
server.listenAddr = listenAddr server.listenAddr = listenAddr
server.maxRpcParamLen = maxRpcParamLen server.maxRpcParamLen = maxRpcParamLen
server.rpcServer = &network.TCPServer{} server.rpcServer = &network.TCPServer{}
} }
func (server *Server) Start() error{ func (server *Server) Start() error {
splitAddr := strings.Split(server.listenAddr, ":") splitAddr := strings.Split(server.listenAddr, ":")
if len(splitAddr) != 2 { if len(splitAddr) != 2 {
return fmt.Errorf("listen addr is failed,listenAddr:%s", server.listenAddr) return fmt.Errorf("listen addr is failed,listenAddr:%s", server.listenAddr)
@@ -89,7 +90,6 @@ func (server *Server) Start() error{
server.rpcServer.Addr = ":" + splitAddr[1] server.rpcServer.Addr = ":" + splitAddr[1]
server.rpcServer.MinMsgLen = 2 server.rpcServer.MinMsgLen = 2
server.compressBytesLen = server.compressBytesLen
if server.maxRpcParamLen > 0 { if server.maxRpcParamLen > 0 {
server.rpcServer.MaxMsgLen = server.maxRpcParamLen server.rpcServer.MaxMsgLen = server.maxRpcParamLen
} else { } else {
@@ -107,7 +107,7 @@ func (server *Server) Start() error{
return server.rpcServer.Start() return server.rpcServer.Start()
} }
func (server *Server) Stop(){ func (server *Server) Stop() {
server.rpcServer.Close() server.rpcServer.Close()
} }
@@ -130,60 +130,59 @@ func (agent *RpcAgent) WriteResponse(processor IRpcProcessor, connTag string, se
defer processor.ReleaseRpcResponse(rpcResponse.RpcResponseData) defer processor.ReleaseRpcResponse(rpcResponse.RpcResponseData)
if errM != nil { if errM != nil {
log.Error("mashal RpcResponseData failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",errM)) log.Error("marshal RpcResponseData failed", log.String("serviceMethod", serviceMethod), log.ErrorField("error", errM))
return return
} }
var compressBuff[]byte var compressBuff []byte
bCompress := uint8(0) bCompress := uint8(0)
if agent.rpcServer.compressBytesLen >0 && len(bytes) >= agent.rpcServer.compressBytesLen { if agent.rpcServer.compressBytesLen > 0 && len(bytes) >= agent.rpcServer.compressBytesLen {
var cErr error var cErr error
compressBuff,cErr = compressor.CompressBlock(bytes) compressBuff, cErr = compressor.CompressBlock(bytes)
if cErr != nil { if cErr != nil {
log.Error("CompressBlock failed",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",cErr)) log.Error("CompressBlock failed", log.String("serviceMethod", serviceMethod), log.ErrorField("error", cErr))
return return
} }
if len(compressBuff) < len(bytes) { if len(compressBuff) < len(bytes) {
bytes = compressBuff bytes = compressBuff
bCompress = 1<<7 bCompress = 1 << 7
} }
} }
errM = agent.conn.WriteMsg([]byte{uint8(processor.GetProcessorType())|bCompress}, bytes) errM = agent.conn.WriteMsg([]byte{uint8(processor.GetProcessorType()) | bCompress}, bytes)
if cap(compressBuff) >0 { if cap(compressBuff) > 0 {
compressor.CompressBufferCollection(compressBuff) compressor.CompressBufferCollection(compressBuff)
} }
if errM != nil { if errM != nil {
log.Error("WriteMsg error,Rpc return is fail",log.String("serviceMethod",serviceMethod),log.ErrorAttr("error",errM)) log.Error("WriteMsg error,Rpc return is fail", log.String("serviceMethod", serviceMethod), log.ErrorField("error", errM))
} }
} }
func (agent *RpcAgent) Run() { func (agent *RpcAgent) Run() {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096) log.StackError(fmt.Sprint(r))
l := runtime.Stack(buf, false)
errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString))
} }
}() }()
for { for {
data, err := agent.conn.ReadMsg() data, err := agent.conn.ReadMsg()
if err != nil { if err != nil {
log.Error("read message is error",log.String("remoteAddress",agent.conn.RemoteAddr().String()),log.ErrorAttr("error",err)) //will close conn
//will close tcpconn log.Error("read message is error", log.String("remoteAddress", agent.conn.RemoteAddr().String()), log.ErrorField("error", err))
break break
} }
defer agent.conn.ReleaseReadMsg(data) err = agent.rpcServer.processRpcRequest(data, "", agent.WriteResponse)
err = agent.rpcServer.processRpcRequest( data,"",agent.WriteResponse)
if err != nil { if err != nil {
log.Error("processRpcRequest is error",log.String("remoteAddress",agent.conn.RemoteAddr().String()),log.ErrorAttr("error",err)) //will close conn
//will close tcpconn agent.conn.ReleaseReadMsg(data)
log.Error("processRpcRequest is error", log.String("remoteAddress", agent.conn.RemoteAddr().String()), log.ErrorField("error", err))
break break
} }
agent.conn.ReleaseReadMsg(data)
} }
} }
@@ -209,9 +208,8 @@ func (agent *RpcAgent) Destroy() {
agent.conn.Destroy() agent.conn.Destroy()
} }
func (server *Server) NewAgent(c *network.TCPConn) network.Agent { func (server *Server) NewAgent(c network.Conn) network.Agent {
agent := &RpcAgent{conn: c, rpcServer: server} agent := &RpcAgent{conn: c, rpcServer: server}
return agent return agent
} }

View File

@@ -6,11 +6,12 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/duanhf2012/origin/v2/concurrent"
"github.com/duanhf2012/origin/v2/event" "github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
rpcHandle "github.com/duanhf2012/origin/v2/rpc" rpcHandle "github.com/duanhf2012/origin/v2/rpc"
"github.com/duanhf2012/origin/v2/util/timer" "github.com/duanhf2012/origin/v2/util/timer"
"github.com/duanhf2012/origin/v2/concurrent" "slices"
) )
const InitModuleId = 1e9 const InitModuleId = 1e9
@@ -35,9 +36,9 @@ type IModule interface {
} }
type IModuleTimer interface { type IModuleTimer interface {
AfterFunc(d time.Duration, cb func(*timer.Timer)) *timer.Timer SafeAfterFunc(d time.Duration, cb func(*timer.Timer)) *timer.Timer
CronFunc(cronExpr *timer.CronExpr, cb func(*timer.Cron)) *timer.Cron SafeCronFunc(cronExpr *timer.CronExpr, cb func(*timer.Cron)) *timer.Cron
NewTicker(d time.Duration, cb func(*timer.Ticker)) *timer.Ticker SafeNewTicker(d time.Duration, cb func(*timer.Ticker)) *timer.Ticker
} }
type Module struct { type Module struct {
@@ -46,7 +47,7 @@ type Module struct {
moduleName string //模块名称 moduleName string //模块名称
parent IModule //父亲 parent IModule //父亲
self IModule //自己 self IModule //自己
child map[uint32]IModule //孩子们 child []IModule //孩子们
mapActiveTimer map[timer.ITimer]struct{} mapActiveTimer map[timer.ITimer]struct{}
mapActiveIdTimer map[uint64]timer.ITimer mapActiveIdTimer map[uint64]timer.ITimer
dispatcher *timer.Dispatcher //timer dispatcher *timer.Dispatcher //timer
@@ -93,10 +94,7 @@ func (m *Module) AddModule(module IModule) (uint32, error) {
pAddModule.moduleId = m.NewModuleId() pAddModule.moduleId = m.NewModuleId()
} }
if m.child == nil { _,ok := m.ancestor.getBaseModule().(*Module).descendants[module.GetModuleId()]
m.child = map[uint32]IModule{}
}
_, ok := m.child[module.GetModuleId()]
if ok == true { if ok == true {
return 0, fmt.Errorf("exists module id %d", module.GetModuleId()) return 0, fmt.Errorf("exists module id %d", module.GetModuleId())
} }
@@ -109,29 +107,33 @@ func (m *Module) AddModule(module IModule) (uint32, error) {
pAddModule.eventHandler = event.NewEventHandler() pAddModule.eventHandler = event.NewEventHandler()
pAddModule.eventHandler.Init(m.eventHandler.GetEventProcessor()) pAddModule.eventHandler.Init(m.eventHandler.GetEventProcessor())
pAddModule.IConcurrent = m.IConcurrent pAddModule.IConcurrent = m.IConcurrent
m.child = append(m.child,module)
m.ancestor.getBaseModule().(*Module).descendants[module.GetModuleId()] = module
err := module.OnInit() err := module.OnInit()
if err != nil { if err != nil {
delete(m.ancestor.getBaseModule().(*Module).descendants, module.GetModuleId())
m.child = m.child[:len(m.child)-1]
log.Error("module OnInit error",log.String("ModuleName",module.GetModuleName()),log.ErrorField("err",err))
return 0, err return 0, err
} }
m.child[module.GetModuleId()] = module log.Debug("Add module " + module.GetModuleName() + " completed")
m.ancestor.getBaseModule().(*Module).descendants[module.GetModuleId()] = module
log.Debug("Add module "+module.GetModuleName()+ " completed")
return module.GetModuleId(), nil return module.GetModuleId(), nil
} }
func (m *Module) ReleaseModule(moduleId uint32) { func (m *Module) ReleaseModule(moduleId uint32) {
pModule := m.GetModule(moduleId).getBaseModule().(*Module) pModule := m.GetModule(moduleId).getBaseModule().(*Module)
pModule.self.OnRelease()
log.Debug("Release module " + pModule.GetModuleName())
//释放子孙 for i:=len(pModule.child)-1; i>=0; i-- {
for id := range pModule.child { m.ReleaseModule(pModule.child[i].GetModuleId())
m.ReleaseModule(id)
} }
pModule.self.OnRelease()
pModule.GetEventHandler().Destroy() pModule.GetEventHandler().Destroy()
log.Debug("Release module "+ pModule.GetModuleName())
for pTimer := range pModule.mapActiveTimer { for pTimer := range pModule.mapActiveTimer {
pTimer.Cancel() pTimer.Cancel()
} }
@@ -140,7 +142,10 @@ func (m *Module) ReleaseModule(moduleId uint32) {
t.Cancel() t.Cancel()
} }
delete(m.child, moduleId) m.child = slices.DeleteFunc(m.child, func(module IModule) bool {
return module.GetModuleId() == moduleId
})
delete(m.ancestor.getBaseModule().(*Module).descendants, moduleId) delete(m.ancestor.getBaseModule().(*Module).descendants, moduleId)
//清理被删除的Module //清理被删除的Module
@@ -208,6 +213,7 @@ func (m *Module) OnAddTimer(t timer.ITimer) {
} }
} }
// Deprecated: this function simply calls SafeAfterFunc
func (m *Module) AfterFunc(d time.Duration, cb func(*timer.Timer)) *timer.Timer { func (m *Module) AfterFunc(d time.Duration, cb func(*timer.Timer)) *timer.Timer {
if m.mapActiveTimer == nil { if m.mapActiveTimer == nil {
m.mapActiveTimer = map[timer.ITimer]struct{}{} m.mapActiveTimer = map[timer.ITimer]struct{}{}
@@ -216,6 +222,7 @@ func (m *Module) AfterFunc(d time.Duration, cb func(*timer.Timer)) *timer.Timer
return m.dispatcher.AfterFunc(d, nil, cb, m.OnCloseTimer, m.OnAddTimer) return m.dispatcher.AfterFunc(d, nil, cb, m.OnCloseTimer, m.OnAddTimer)
} }
// Deprecated: this function simply calls SafeCronFunc
func (m *Module) CronFunc(cronExpr *timer.CronExpr, cb func(*timer.Cron)) *timer.Cron { func (m *Module) CronFunc(cronExpr *timer.CronExpr, cb func(*timer.Cron)) *timer.Cron {
if m.mapActiveTimer == nil { if m.mapActiveTimer == nil {
m.mapActiveTimer = map[timer.ITimer]struct{}{} m.mapActiveTimer = map[timer.ITimer]struct{}{}
@@ -224,6 +231,7 @@ func (m *Module) CronFunc(cronExpr *timer.CronExpr, cb func(*timer.Cron)) *timer
return m.dispatcher.CronFunc(cronExpr, nil, cb, m.OnCloseTimer, m.OnAddTimer) return m.dispatcher.CronFunc(cronExpr, nil, cb, m.OnCloseTimer, m.OnAddTimer)
} }
// Deprecated: this function simply calls SafeNewTicker
func (m *Module) NewTicker(d time.Duration, cb func(*timer.Ticker)) *timer.Ticker { func (m *Module) NewTicker(d time.Duration, cb func(*timer.Ticker)) *timer.Ticker {
if m.mapActiveTimer == nil { if m.mapActiveTimer == nil {
m.mapActiveTimer = map[timer.ITimer]struct{}{} m.mapActiveTimer = map[timer.ITimer]struct{}{}
@@ -277,8 +285,8 @@ func (m *Module) SafeNewTicker(tickerId *uint64, d time.Duration, AdditionData i
} }
func (m *Module) CancelTimerId(timerId *uint64) bool { func (m *Module) CancelTimerId(timerId *uint64) bool {
if timerId==nil || *timerId == 0 { if timerId == nil || *timerId == 0 {
log.Warning("timerId is invalid") log.Warn("timerId is invalid")
return false return false
} }
@@ -289,7 +297,7 @@ func (m *Module) CancelTimerId(timerId *uint64) bool {
t, ok := m.mapActiveIdTimer[*timerId] t, ok := m.mapActiveIdTimer[*timerId]
if ok == false { if ok == false {
log.Stack("cannot find timer id ", log.Uint64("timerId",*timerId)) log.StackError("cannot find timer id ", log.Uint64("timerId", *timerId))
return false return false
} }

View File

@@ -1,19 +1,19 @@
package service package service
import ( import (
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/duanhf2012/origin/v2/concurrent"
"github.com/duanhf2012/origin/v2/event" "github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/profiler" "github.com/duanhf2012/origin/v2/profiler"
"github.com/duanhf2012/origin/v2/rpc" "github.com/duanhf2012/origin/v2/rpc"
"github.com/duanhf2012/origin/v2/util/timer" "github.com/duanhf2012/origin/v2/util/timer"
"reflect" "reflect"
"runtime"
"strconv" "strconv"
"sync" "sync"
"sync/atomic" "sync/atomic"
"github.com/duanhf2012/origin/v2/concurrent"
) )
var timerDispatcherLen = 100000 var timerDispatcherLen = 100000
@@ -21,7 +21,7 @@ var maxServiceEventChannelNum = 2000000
type IService interface { type IService interface {
concurrent.IConcurrent concurrent.IConcurrent
Init(iService IService,getClientFun rpc.FuncRpcClient,getServerFun rpc.FuncRpcServer,serviceCfg interface{}) Init(iService IService, getClientFun rpc.FuncRpcClient, getServerFun rpc.FuncRpcServer, serviceCfg interface{})
Stop() Stop()
Start() Start()
@@ -34,7 +34,7 @@ type IService interface {
SetName(serviceName string) SetName(serviceName string)
GetName() string GetName() string
GetRpcHandler() rpc.IRpcHandler GetRpcHandler() rpc.IRpcHandler
GetServiceCfg()interface{} GetServiceCfg() interface{}
GetProfiler() *profiler.Profiler GetProfiler() *profiler.Profiler
GetServiceEventChannelNum() int GetServiceEventChannelNum() int
GetServiceTimerChannelNum() int GetServiceTimerChannelNum() int
@@ -49,70 +49,67 @@ type IService interface {
type Service struct { type Service struct {
Module Module
rpcHandler rpc.RpcHandler //rpc rpcHandler rpc.RpcHandler //rpc
name string //service name name string //service name
wg sync.WaitGroup wg sync.WaitGroup
serviceCfg interface{} serviceCfg interface{}
goroutineNum int32 goroutineNum int32
startStatus bool startStatus bool
retire int32 isRelease int32
eventProcessor event.IEventProcessor retire int32
profiler *profiler.Profiler //性能分析器 eventProcessor event.IEventProcessor
nodeConnLister rpc.INodeConnListener profiler *profiler.Profiler //性能分析器
natsConnListener rpc.INatsConnListener nodeConnLister rpc.INodeConnListener
natsConnListener rpc.INatsConnListener
discoveryServiceLister rpc.IDiscoveryServiceListener discoveryServiceLister rpc.IDiscoveryServiceListener
chanEvent chan event.IEvent chanEvent chan event.IEvent
closeSig chan struct{} closeSig chan struct{}
} }
// DiscoveryServiceEvent 发现服务结点 // DiscoveryServiceEvent 发现服务结点
type DiscoveryServiceEvent struct{ type DiscoveryServiceEvent struct {
IsDiscovery bool IsDiscovery bool
ServiceName []string ServiceName []string
NodeId string NodeId string
} }
type EtcdServiceRecordEvent struct { type EtcdServiceRecordEvent struct {
NetworkName string NetworkName string
TTLSecond int64 TTLSecond int64
RecordKey string RecordKey string
RecordInfo string RecordInfo string
} }
type Empty struct { type Empty struct {
} }
func SetMaxServiceChannel(maxEventChannel int){ func SetMaxServiceChannel(maxEventChannel int) {
maxServiceEventChannelNum = maxEventChannel maxServiceEventChannelNum = maxEventChannel
} }
func (rpcEventData *DiscoveryServiceEvent) GetEventType() event.EventType{ func (rpcEventData *DiscoveryServiceEvent) GetEventType() event.EventType {
return event.Sys_Event_DiscoverService return event.Sys_Event_DiscoverService
} }
func (s *Service) OnSetup(iService IService) {
func (s *Service) OnSetup(iService IService){
if iService.GetName() == "" { if iService.GetName() == "" {
s.name = reflect.Indirect(reflect.ValueOf(iService)).Type().Name() s.name = reflect.Indirect(reflect.ValueOf(iService)).Type().Name()
} }
} }
func (s *Service) OpenProfiler() { func (s *Service) OpenProfiler() {
s.profiler = profiler.RegProfiler(s.GetName()) s.profiler = profiler.RegProfiler(s.GetName())
if s.profiler==nil { if s.profiler == nil {
log.Fatal("rofiler.RegProfiler "+s.GetName()+" fail.") log.Fatal("profiler.RegProfiler " + s.GetName() + " fail.")
} }
} }
func (s *Service) IsRetire() bool{ func (s *Service) IsRetire() bool {
return atomic.LoadInt32(&s.retire) != 0 return atomic.LoadInt32(&s.retire) != 0
} }
func (s *Service) SetRetire(){ func (s *Service) SetRetire() {
atomic.StoreInt32(&s.retire,1) atomic.StoreInt32(&s.retire, 1)
ev := event.NewEvent() ev := event.NewEvent()
ev.Type = event.Sys_Event_Retire ev.Type = event.Sys_Event_Retire
@@ -120,122 +117,124 @@ func (s *Service) SetRetire(){
s.pushEvent(ev) s.pushEvent(ev)
} }
func (s *Service) Init(iService IService,getClientFun rpc.FuncRpcClient,getServerFun rpc.FuncRpcServer,serviceCfg interface{}) { func (s *Service) Init(iService IService, getClientFun rpc.FuncRpcClient, getServerFun rpc.FuncRpcServer, serviceCfg interface{}) {
s.closeSig = make(chan struct{}) s.closeSig = make(chan struct{})
s.dispatcher =timer.NewDispatcher(timerDispatcherLen) s.dispatcher = timer.NewDispatcher(timerDispatcherLen)
if s.chanEvent == nil { if s.chanEvent == nil {
s.chanEvent = make(chan event.IEvent,maxServiceEventChannelNum) s.chanEvent = make(chan event.IEvent, maxServiceEventChannelNum)
} }
s.rpcHandler.InitRpcHandler(iService.(rpc.IRpcHandler),getClientFun,getServerFun,iService.(rpc.IRpcHandlerChannel)) s.rpcHandler.InitRpcHandler(iService.(rpc.IRpcHandler), getClientFun, getServerFun, iService.(rpc.IRpcHandlerChannel))
s.IRpcHandler = &s.rpcHandler s.IRpcHandler = &s.rpcHandler
s.self = iService.(IModule) s.self = iService.(IModule)
//初始化祖先 //初始化祖先
s.ancestor = iService.(IModule) s.ancestor = iService.(IModule)
s.seedModuleId =InitModuleId s.seedModuleId = InitModuleId
s.descendants = map[uint32]IModule{} s.descendants = map[uint32]IModule{}
s.serviceCfg = serviceCfg s.serviceCfg = serviceCfg
s.goroutineNum = 1 s.goroutineNum = 1
s.eventProcessor = event.NewEventProcessor() s.eventProcessor = event.NewEventProcessor()
s.eventProcessor.Init(s) s.eventProcessor.Init(s)
s.eventHandler = event.NewEventHandler() s.eventHandler = event.NewEventHandler()
s.eventHandler.Init(s.eventProcessor) s.eventHandler.Init(s.eventProcessor)
s.Module.IConcurrent = &concurrent.Concurrent{} s.Module.IConcurrent = &concurrent.Concurrent{}
} }
func (s *Service) Start() { func (s *Service) Start() {
s.startStatus = true s.startStatus = true
atomic.StoreInt32(&s.isRelease, 0)
var waitRun sync.WaitGroup var waitRun sync.WaitGroup
log.Info(s.GetName() + " service is running")
s.self.(IService).OnStart()
for i:=int32(0);i< s.goroutineNum;i++{ for i := int32(0); i < s.goroutineNum; i++ {
s.wg.Add(1) s.wg.Add(1)
waitRun.Add(1) waitRun.Add(1)
go func(){ go func() {
log.Info(s.GetName()+" service is running",)
waitRun.Done() waitRun.Done()
s.Run() s.run()
}() }()
} }
waitRun.Wait() waitRun.Wait()
} }
func (s *Service) Run() { func (s *Service) run() {
defer s.wg.Done() defer s.wg.Done()
var bStop = false var bStop = false
concurrent := s.IConcurrent.(*concurrent.Concurrent)
concurrentCBChannel := concurrent.GetCallBackChannel()
s.self.(IService).OnStart() cr := s.IConcurrent.(*concurrent.Concurrent)
for{ concurrentCBChannel := cr.GetCallBackChannel()
for {
var analyzer *profiler.Analyzer var analyzer *profiler.Analyzer
select { select {
case <- s.closeSig: case <-s.closeSig:
bStop = true bStop = true
concurrent.Close() s.Release()
case cb:=<-concurrentCBChannel: cr.Close()
concurrent.DoCallback(cb) case cb := <-concurrentCBChannel:
case ev := <- s.chanEvent: cr.DoCallback(cb)
case ev := <-s.chanEvent:
switch ev.GetEventType() { switch ev.GetEventType() {
case event.Sys_Event_Retire: case event.Sys_Event_Retire:
log.Info("service OnRetire",log.String("servceName",s.GetName())) log.Info("service OnRetire", log.String("serviceName", s.GetName()))
s.self.(IService).OnRetire() s.self.(IService).OnRetire()
case event.ServiceRpcRequestEvent: case event.ServiceRpcRequestEvent:
cEvent,ok := ev.(*event.Event) cEvent, ok := ev.(*event.Event)
if ok == false { if ok == false {
log.Error("Type event conversion error") log.Error("Type event conversion error")
break break
} }
rpcRequest,ok := cEvent.Data.(*rpc.RpcRequest) rpcRequest, ok := cEvent.Data.(*rpc.RpcRequest)
if ok == false { if ok == false {
log.Error("Type *rpc.RpcRequest conversion error") log.Error("Type *rpc.RpcRequest conversion error")
break break
} }
if s.profiler!=nil { if s.profiler != nil {
analyzer = s.profiler.Push("[Req]"+rpcRequest.RpcRequestData.GetServiceMethod()) analyzer = s.profiler.Push("[RpcReq]" + rpcRequest.RpcRequestData.GetServiceMethod()+"."+strconv.Itoa(int(rpcRequest.RpcRequestData.GetRpcMethodId())))
} }
s.GetRpcHandler().HandlerRpcRequest(rpcRequest) s.GetRpcHandler().HandlerRpcRequest(rpcRequest)
if analyzer!=nil { if analyzer != nil {
analyzer.Pop() analyzer.Pop()
analyzer = nil analyzer = nil
} }
event.DeleteEvent(cEvent) event.DeleteEvent(cEvent)
case event.ServiceRpcResponseEvent: case event.ServiceRpcResponseEvent:
cEvent,ok := ev.(*event.Event) cEvent, ok := ev.(*event.Event)
if ok == false { if ok == false {
log.Error("Type event conversion error") log.Error("Type event conversion error")
break break
} }
rpcResponseCB,ok := cEvent.Data.(*rpc.Call) rpcResponseCB, ok := cEvent.Data.(*rpc.Call)
if ok == false { if ok == false {
log.Error("Type *rpc.Call conversion error") log.Error("Type *rpc.Call conversion error")
break break
} }
if s.profiler!=nil { if s.profiler != nil {
analyzer = s.profiler.Push("[Res]" + rpcResponseCB.ServiceMethod) analyzer = s.profiler.Push("[Res]" + rpcResponseCB.ServiceMethod)
} }
s.GetRpcHandler().HandlerRpcResponseCB(rpcResponseCB) s.GetRpcHandler().HandlerRpcResponseCB(rpcResponseCB)
if analyzer!=nil { if analyzer != nil {
analyzer.Pop() analyzer.Pop()
analyzer = nil analyzer = nil
} }
event.DeleteEvent(cEvent) event.DeleteEvent(cEvent)
default: default:
if s.profiler!=nil { if s.profiler != nil {
analyzer = s.profiler.Push("[SEvent]"+strconv.Itoa(int(ev.GetEventType()))) analyzer = s.profiler.Push("[SEvent]" + strconv.Itoa(int(ev.GetEventType())))
} }
s.eventProcessor.EventHandler(ev) s.eventProcessor.EventHandler(ev)
if analyzer!=nil { if analyzer != nil {
analyzer.Pop() analyzer.Pop()
analyzer = nil analyzer = nil
} }
} }
case t := <- s.dispatcher.ChanTimer: case t := <-s.dispatcher.ChanTimer:
if s.profiler != nil { if s.profiler != nil {
analyzer = s.profiler.Push("[timer]"+t.GetName()) analyzer = s.profiler.Push("[timer]" + t.GetName())
} }
t.Do() t.Do()
if analyzer != nil { if analyzer != nil {
@@ -245,16 +244,12 @@ func (s *Service) Run() {
} }
if bStop == true { if bStop == true {
if atomic.AddInt32(&s.goroutineNum,-1)<=0 {
s.startStatus = false
s.Release()
}
break break
} }
} }
} }
func (s *Service) GetName() string{ func (s *Service) GetName() string {
return s.name return s.name
} }
@@ -262,121 +257,137 @@ func (s *Service) SetName(serviceName string) {
s.name = serviceName s.name = serviceName
} }
func (s *Service) Release(){ func (s *Service) Release() {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096) log.StackError(fmt.Sprint(r))
l := runtime.Stack(buf, false)
errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString))
} }
}() }()
s.self.OnRelease() if atomic.AddInt32(&s.isRelease, -1) == -1 {
s.self.OnRelease()
for i:=len(s.child)-1; i>=0; i-- {
s.ReleaseModule(s.child[i].GetModuleId())
}
}
} }
func (s *Service) OnRelease(){ func (s *Service) OnRelease() {
} }
func (s *Service) OnInit() error { func (s *Service) OnInit() error {
return nil return nil
} }
func (s *Service) Stop(){ func (s *Service) Stop() {
log.Info("stop "+s.GetName()+" service ") log.Info("stop " + s.GetName() + " service ")
close(s.closeSig) close(s.closeSig)
s.wg.Wait() s.wg.Wait()
log.Info(s.GetName()+" service has been stopped") log.Info(s.GetName() + " service has been stopped")
} }
func (s *Service) GetServiceCfg()interface{}{ func (s *Service) GetServiceCfg() interface{} {
return s.serviceCfg return s.serviceCfg
} }
func (s *Service) GetProfiler() *profiler.Profiler{ func (s *Service) ParseServiceCfg(cfg interface{}) error {
if s.serviceCfg == nil {
return errors.New("no service configuration found")
}
rv := reflect.ValueOf(s.serviceCfg)
if rv.Kind() == reflect.Ptr && rv.IsNil() {
return errors.New("no service configuration found")
}
bytes, err := json.Marshal(s.serviceCfg)
if err != nil {
return err
}
return json.Unmarshal(bytes, cfg)
}
func (s *Service) GetProfiler() *profiler.Profiler {
return s.profiler return s.profiler
} }
func (s *Service) RegEventReceiverFunc(eventType event.EventType, receiver event.IEventHandler,callback event.EventCallBack){ func (s *Service) RegEventReceiverFunc(eventType event.EventType, receiver event.IEventHandler, callback event.EventCallBack) {
s.eventProcessor.RegEventReceiverFunc(eventType, receiver,callback) s.eventProcessor.RegEventReceiverFunc(eventType, receiver, callback)
} }
func (s *Service) UnRegEventReceiverFunc(eventType event.EventType, receiver event.IEventHandler){ func (s *Service) UnRegEventReceiverFunc(eventType event.EventType, receiver event.IEventHandler) {
s.eventProcessor.UnRegEventReceiverFun(eventType, receiver) s.eventProcessor.UnRegEventReceiverFun(eventType, receiver)
} }
func (s *Service) IsSingleCoroutine() bool { func (s *Service) RegRawRpc(rpcMethodId uint32, rawRpcCB rpc.RawRpcCallBack) {
return s.goroutineNum == 1 s.rpcHandler.RegRawRpc(rpcMethodId, rawRpcCB)
} }
func (s *Service) RegRawRpc(rpcMethodId uint32,rawRpcCB rpc.RawRpcCallBack){ func (s *Service) OnStart() {
s.rpcHandler.RegRawRpc(rpcMethodId,rawRpcCB)
} }
func (s *Service) OnStart(){ func (s *Service) OnNodeConnEvent(ev event.IEvent) {
} re := ev.(*rpc.RpcConnEvent)
if re.IsConnect {
func (s *Service) OnNodeConnEvent(ev event.IEvent){ s.nodeConnLister.OnNodeConnected(re.NodeId)
event := ev.(*rpc.RpcConnEvent) } else {
if event.IsConnect { s.nodeConnLister.OnNodeDisconnect(re.NodeId)
s.nodeConnLister.OnNodeConnected(event.NodeId)
}else{
s.nodeConnLister.OnNodeDisconnect(event.NodeId)
} }
} }
func (s *Service) OnNatsConnEvent(ev event.IEvent){ func (s *Service) OnNatsConnEvent(ev event.IEvent) {
event := ev.(*rpc.NatsConnEvent) event := ev.(*rpc.NatsConnEvent)
if event.IsConnect { if event.IsConnect {
s.natsConnListener.OnNatsConnected() s.natsConnListener.OnNatsConnected()
}else{ } else {
s.natsConnListener.OnNatsDisconnect() s.natsConnListener.OnNatsDisconnect()
} }
} }
func (s *Service) OnDiscoverServiceEvent(ev event.IEvent){ func (s *Service) OnDiscoverServiceEvent(ev event.IEvent) {
event := ev.(*DiscoveryServiceEvent) de := ev.(*DiscoveryServiceEvent)
if event.IsDiscovery { if de.IsDiscovery {
s.discoveryServiceLister.OnDiscoveryService(event.NodeId,event.ServiceName) s.discoveryServiceLister.OnDiscoveryService(de.NodeId, de.ServiceName)
}else{ } else {
s.discoveryServiceLister.OnUnDiscoveryService(event.NodeId,event.ServiceName) s.discoveryServiceLister.OnUnDiscoveryService(de.NodeId, de.ServiceName)
} }
} }
func (s *Service) RegNodeConnListener(nodeConnListener rpc.INodeConnListener) { func (s *Service) RegNodeConnListener(nodeConnListener rpc.INodeConnListener) {
s.nodeConnLister = nodeConnListener s.nodeConnLister = nodeConnListener
s.RegEventReceiverFunc(event.Sys_Event_Node_Conn_Event,s.GetEventHandler(),s.OnNodeConnEvent) s.RegEventReceiverFunc(event.Sys_Event_Node_Conn_Event, s.GetEventHandler(), s.OnNodeConnEvent)
RegRpcEventFun(s.GetName()) RegRpcEventFun(s.GetName())
} }
func (s *Service) UnRegNodeConnListener() { func (s *Service) UnRegNodeConnListener() {
s.UnRegEventReceiverFunc(event.Sys_Event_Node_Conn_Event,s.GetEventHandler()) s.UnRegEventReceiverFunc(event.Sys_Event_Node_Conn_Event, s.GetEventHandler())
UnRegRpcEventFun(s.GetName()) UnRegRpcEventFun(s.GetName())
} }
func (s *Service) RegNatsConnListener(natsConnListener rpc.INatsConnListener) { func (s *Service) RegNatsConnListener(natsConnListener rpc.INatsConnListener) {
s.natsConnListener = natsConnListener s.natsConnListener = natsConnListener
s.RegEventReceiverFunc(event.Sys_Event_Nats_Conn_Event,s.GetEventHandler(),s.OnNatsConnEvent) s.RegEventReceiverFunc(event.Sys_Event_Nats_Conn_Event, s.GetEventHandler(), s.OnNatsConnEvent)
RegRpcEventFun(s.GetName()) RegRpcEventFun(s.GetName())
} }
func (s *Service) UnRegNatsConnListener() { func (s *Service) UnRegNatsConnListener() {
s.UnRegEventReceiverFunc(event.Sys_Event_Nats_Conn_Event,s.GetEventHandler()) s.UnRegEventReceiverFunc(event.Sys_Event_Nats_Conn_Event, s.GetEventHandler())
UnRegRpcEventFun(s.GetName()) UnRegRpcEventFun(s.GetName())
} }
func (s *Service) RegDiscoverListener(discoveryServiceListener rpc.IDiscoveryServiceListener) { func (s *Service) RegDiscoverListener(discoveryServiceListener rpc.IDiscoveryServiceListener) {
s.discoveryServiceLister = discoveryServiceListener s.discoveryServiceLister = discoveryServiceListener
s.RegEventReceiverFunc(event.Sys_Event_DiscoverService,s.GetEventHandler(),s.OnDiscoverServiceEvent) s.RegEventReceiverFunc(event.Sys_Event_DiscoverService, s.GetEventHandler(), s.OnDiscoverServiceEvent)
RegRpcEventFun(s.GetName()) RegRpcEventFun(s.GetName())
} }
func (s *Service) UnRegDiscoverListener() { func (s *Service) UnRegDiscoverListener() {
s.UnRegEventReceiverFunc(event.Sys_Event_DiscoverService,s.GetEventHandler()) s.UnRegEventReceiverFunc(event.Sys_Event_DiscoverService, s.GetEventHandler())
UnRegRpcEventFun(s.GetName()) UnRegRpcEventFun(s.GetName())
} }
func (s *Service) PushRpcRequest(rpcRequest *rpc.RpcRequest) error{ func (s *Service) PushRpcRequest(rpcRequest *rpc.RpcRequest) error {
ev := event.NewEvent() ev := event.NewEvent()
ev.Type = event.ServiceRpcRequestEvent ev.Type = event.ServiceRpcRequestEvent
ev.Data = rpcRequest ev.Data = rpcRequest
@@ -384,7 +395,7 @@ func (s *Service) PushRpcRequest(rpcRequest *rpc.RpcRequest) error{
return s.pushEvent(ev) return s.pushEvent(ev)
} }
func (s *Service) PushRpcResponse(call *rpc.Call) error{ func (s *Service) PushRpcResponse(call *rpc.Call) error {
ev := event.NewEvent() ev := event.NewEvent()
ev.Type = event.ServiceRpcResponseEvent ev.Type = event.ServiceRpcResponseEvent
ev.Data = call ev.Data = call
@@ -392,13 +403,13 @@ func (s *Service) PushRpcResponse(call *rpc.Call) error{
return s.pushEvent(ev) return s.pushEvent(ev)
} }
func (s *Service) PushEvent(ev event.IEvent) error{ func (s *Service) PushEvent(ev event.IEvent) error {
return s.pushEvent(ev) return s.pushEvent(ev)
} }
func (s *Service) pushEvent(ev event.IEvent) error{ func (s *Service) pushEvent(ev event.IEvent) error {
if len(s.chanEvent) >= maxServiceEventChannelNum { if len(s.chanEvent) >= maxServiceEventChannelNum {
err := errors.New("The event channel in the service is full") err := errors.New("the event channel in the service is full")
log.Error(err.Error()) log.Error(err.Error())
return err return err
} }
@@ -407,25 +418,26 @@ func (s *Service) pushEvent(ev event.IEvent) error{
return nil return nil
} }
func (s *Service) GetServiceEventChannelNum() int{ func (s *Service) GetServiceEventChannelNum() int {
return len(s.chanEvent) return len(s.chanEvent)
} }
func (s *Service) GetServiceTimerChannelNum() int{ func (s *Service) GetServiceTimerChannelNum() int {
return len(s.dispatcher.ChanTimer) return len(s.dispatcher.ChanTimer)
} }
func (s *Service) SetEventChannelNum(num int){ func (s *Service) SetEventChannelNum(num int) {
if s.chanEvent == nil { if s.chanEvent == nil {
s.chanEvent = make(chan event.IEvent,num) s.chanEvent = make(chan event.IEvent, num)
}else { } else {
panic("this stage cannot be set") panic("this stage cannot be set")
} }
} }
// Deprecated: replace it with the OpenConcurrent function
func (s *Service) SetGoRoutineNum(goroutineNum int32) bool { func (s *Service) SetGoRoutineNum(goroutineNum int32) bool {
//已经开始状态不允许修改协程数量,打开性能分析器不允许开多线程 //已经开始状态不允许修改协程数量,打开性能分析器不允许开多线程
if s.startStatus == true || s.profiler!=nil { if s.startStatus == true || s.profiler != nil {
log.Error("open profiler mode is not allowed to set Multi-coroutine.") log.Error("open profiler mode is not allowed to set Multi-coroutine.")
return false return false
} }
@@ -434,5 +446,5 @@ func (s *Service) SetGoRoutineNum(goroutineNum int32) bool {
return true return true
} }
func (s *Service) OnRetire(){ func (s *Service) OnRetire() {
} }

View File

@@ -23,7 +23,7 @@ func Init() {
for _,s := range setupServiceList { for _,s := range setupServiceList {
err := s.OnInit() err := s.OnInit()
if err != nil { if err != nil {
log.SError("Failed to initialize "+s.GetName()+" service:"+err.Error()) log.Error("Failed to initialize "+s.GetName()+" service",log.ErrorField("err",err))
os.Exit(1) os.Exit(1)
} }
} }

View File

@@ -0,0 +1,203 @@
package frametimer
import (
"container/heap"
"context"
"errors"
"github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log"
"time"
)
type TimerCB func(context.Context, FrameTimerID)
type _timerHeap struct {
timers []*timerData
}
func (h *_timerHeap) Len() int {
return len(h.timers)
}
func (h *_timerHeap) Less(i, j int) bool {
return h.timers[i].frameNum < h.timers[j].frameNum
}
func (h *_timerHeap) Swap(i, j int) {
h.timers[i], h.timers[j] = h.timers[j], h.timers[i]
h.timers[i].idx = i
h.timers[j].idx = j
}
func (h *_timerHeap) Push(x interface{}) {
td := x.(*timerData)
h.timers = append(h.timers, td)
td.idx = len(h.timers) - 1
}
func (h *_timerHeap) Pop() (ret interface{}) {
l := len(h.timers)
h.timers, ret = h.timers[:l-1], h.timers[l-1]
return
}
type FrameGroup struct {
groupID FrameGroupID
timerHeap _timerHeap
ft *FrameTimer
preTickGlobalFrameNum FrameNumber // 上次tick全局帧
preGlobalFrameNum FrameNumber // 上次设置的全局帧,用于更新FrameTimer.mapFrameGroup关系
frameNum FrameNumber // 当前帧
pause bool // 暂停状态
multiple uint8 // 位数默认1倍只允许1-5倍数
}
func (fg *FrameGroup) init() {
fg.timerHeap.timers = make([]*timerData, 0, 512)
fg.groupID = fg.ft.genGroupID()
fg.multiple = 1
heap.Init(&fg.timerHeap)
}
func (fg *FrameGroup) convertGlobalFrameNum(frameNum FrameNumber) FrameNumber {
return fg.ft.getGlobalFrameNumber() + (frameNum-fg.frameNum)/FrameNumber(fg.multiple)
}
func (fg *FrameGroup) refreshMinFrame() {
if fg.timerHeap.Len() == 0 || fg.pause {
return
}
globalFrameNum := fg.convertGlobalFrameNum(fg.timerHeap.timers[0].frameNum)
fg.ft.refreshGroupMinFrame(fg.groupID, fg.preGlobalFrameNum, globalFrameNum)
fg.preGlobalFrameNum = globalFrameNum
}
func (fg *FrameGroup) tick(globalFrame FrameNumber) {
fg.frameNum = fg.frameNum + (globalFrame-fg.preTickGlobalFrameNum)*FrameNumber(fg.multiple)
fg.preTickGlobalFrameNum = globalFrame
fg.onceTick()
fg.refreshMinFrame()
}
func (fg *FrameGroup) onceTick() {
for fg.timerHeap.Len() > 0 {
if fg.timerHeap.timers[0].frameNum > fg.frameNum {
break
}
t := heap.Pop(&fg.timerHeap).(*timerData)
ev := event.NewEvent()
ev.Type = event.Sys_Event_FrameTick
ev.Data = t
fg.ft.NotifyEvent(ev)
fg.ft.removeTimerData(t.timerID)
if t.tickerFrameNum != 0 {
fg.addTicker(t.timerID, t.tickerFrameNum, t.ctx, t.cb)
}
}
}
func (fg *FrameGroup) addTimer(timerID FrameTimerID, frame FrameNumber, ctx context.Context, cb TimerCB) {
nextFrame := fg.frameNum + frame
td := fg.ft.addTimerData(timerID, nextFrame, 0, ctx, cb)
heap.Push(&fg.timerHeap, td)
}
func (fg *FrameGroup) addTicker(timerID FrameTimerID, frame FrameNumber, ctx context.Context, cb TimerCB) {
nextFrame := fg.frameNum + frame
td := fg.ft.addTimerData(timerID, nextFrame, frame, ctx, cb)
heap.Push(&fg.timerHeap, td)
}
// SetMultiple 设置倍数允许倍数范围1-5
func (fg *FrameGroup) SetMultiple(multiple uint8) error {
if fg.multiple == multiple {
return nil
}
if multiple < 0 || multiple > maxMultiple {
return errors.New("invalid multiplier")
}
fg.multiple = multiple
fg.refreshMinFrame()
return nil
}
// FrameAfterFunc 创建After定时器
func (fg *FrameGroup) FrameAfterFunc(timerID *FrameTimerID, d time.Duration, ctx context.Context, cb TimerCB) {
fg.ft.locker.Lock()
defer fg.ft.locker.Unlock()
frame := FrameNumber(d / fg.ft.oneFrameTime)
newTimerID := fg.ft.genTimerID()
fg.addTimer(newTimerID, frame, ctx, cb)
*timerID = newTimerID
fg.refreshMinFrame()
}
// FrameNewTicker 创建Ticker定时器
func (fg *FrameGroup) FrameNewTicker(timerID *FrameTimerID, d time.Duration, ctx context.Context, cb TimerCB) {
fg.ft.locker.Lock()
defer fg.ft.locker.Unlock()
frame := FrameNumber(d / fg.ft.oneFrameTime)
newTimerID := fg.ft.genTimerID()
fg.addTicker(newTimerID, frame, ctx, cb)
*timerID = newTimerID
fg.refreshMinFrame()
}
// Pause 暂停定时器组
func (fg *FrameGroup) Pause() {
fg.ft.locker.Lock()
defer fg.ft.locker.Unlock()
fg.pause = true
fg.ft.removeGroup(fg.groupID, fg.preGlobalFrameNum)
fg.preGlobalFrameNum = 0
}
// Resume 唤醒定时器组
func (fg *FrameGroup) Resume() {
fg.ft.locker.Lock()
defer fg.ft.locker.Unlock()
fg.pause = false
fg.refreshMinFrame()
fg.preTickGlobalFrameNum = fg.ft.globalFrameNum
}
// CancelTimer 关闭定时器
func (fg *FrameGroup) CancelTimer(timerID FrameTimerID) {
fg.ft.locker.Lock()
defer fg.ft.locker.Unlock()
td := fg.ft.getTimerData(timerID)
if td == nil {
log.Error("cannot find timer", log.Uint64("timerID", uint64(timerID)))
return
}
heap.Remove(&fg.timerHeap, td.idx)
fg.ft.removeGroup(fg.groupID, fg.preGlobalFrameNum)
fg.preGlobalFrameNum = 0
fg.refreshMinFrame()
}
func (fg *FrameGroup) Close(){
fg.ft.removeGroup(fg.groupID, fg.preGlobalFrameNum)
delete(fg.ft.mapGroup,fg.groupID)
}

View File

@@ -0,0 +1,199 @@
package frametimer
import (
"context"
"github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/service"
"sync"
"time"
)
const defaultFps = 50
const defaultSleepInterval = time.Millisecond * 3
const maxFps = 1000
const maxMultiple = 5
type FrameGroupID uint64
type FrameTimerID uint64
type FrameNumber uint64
type timerData struct {
frameNum FrameNumber
timerID FrameTimerID
idx int
cb TimerCB
tickerFrameNum FrameNumber
ctx context.Context
}
type FrameTimer struct {
service.Module
fps uint32
oneFrameTime time.Duration
ticker *time.Ticker
mapFrameGroup map[FrameNumber]map[FrameGroupID]struct{}
mapGroup map[FrameGroupID]*FrameGroup
globalFrameNum FrameNumber // 当前帧
maxTimerID FrameTimerID
maxGroupID FrameGroupID
mapTimer map[FrameTimerID]*timerData
timerDataPool *sync.Pool
locker sync.Mutex
sleepInterval time.Duration
}
func (ft *FrameTimer) getTimerData(timerID FrameTimerID) *timerData {
return ft.mapTimer[timerID]
}
func (ft *FrameTimer) addTimerData(timerID FrameTimerID, frameNum FrameNumber, tickerFrameNum FrameNumber, ctx context.Context, cb TimerCB) *timerData {
td := ft.timerDataPool.Get().(*timerData)
td.timerID = timerID
td.frameNum = frameNum
td.cb = cb
td.idx = -1
td.tickerFrameNum = tickerFrameNum
td.ctx = ctx
ft.mapTimer[timerID] = td
return td
}
func (ft *FrameTimer) removeTimerData(timerID FrameTimerID) {
td := ft.mapTimer[timerID]
if td == nil {
return
}
ft.timerDataPool.Put(td)
}
func (ft *FrameTimer) genGroupID() FrameGroupID {
ft.maxGroupID++
return ft.maxGroupID
}
func (ft *FrameTimer) genTimerID() FrameTimerID {
ft.maxTimerID++
return ft.maxTimerID
}
func (ft *FrameTimer) getGlobalFrameNumber() FrameNumber {
return ft.globalFrameNum
}
func (ft *FrameTimer) frameTick() {
preFrameNum := ft.globalFrameNum
ft.globalFrameNum++
ft.locker.Lock()
defer ft.locker.Unlock()
for i := preFrameNum; i <= ft.globalFrameNum; i++ {
mapGroup := ft.mapFrameGroup[i]
delete(ft.mapFrameGroup, i)
for groupID := range mapGroup {
group := ft.mapGroup[groupID]
if group == nil {
continue
}
group.tick(ft.globalFrameNum)
}
}
}
func (ft *FrameTimer) removeGroup(groupID FrameGroupID, frameNum FrameNumber) {
delete(ft.mapFrameGroup[frameNum], groupID)
}
func (ft *FrameTimer) refreshGroupMinFrame(groupID FrameGroupID, preFrameNum FrameNumber, newFrameNum FrameNumber) {
ft.removeGroup(groupID, preFrameNum)
mapGroup := ft.mapFrameGroup[newFrameNum]
if mapGroup == nil {
mapGroup = make(map[FrameGroupID]struct{}, 6)
ft.mapFrameGroup[newFrameNum] = mapGroup
}
mapGroup[groupID] = struct{}{}
}
func (ft *FrameTimer) OnInit() error {
ft.mapFrameGroup = make(map[FrameNumber]map[FrameGroupID]struct{}, 1024)
ft.mapGroup = make(map[FrameGroupID]*FrameGroup, 1024)
ft.mapTimer = make(map[FrameTimerID]*timerData, 2048)
ft.timerDataPool = &sync.Pool{
New: func() any {
return &timerData{}
},
}
if ft.fps == 0 {
ft.fps = defaultFps
}
ft.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_FrameTick, ft.GetEventHandler(), func(e event.IEvent) {
ev := e.(*event.Event)
td, ok := ev.Data.(*timerData)
if !ok {
log.Error("convert *timerData error")
return
}
td.cb(td.ctx, td.timerID)
event.DeleteEvent(e)
})
ft.oneFrameTime = time.Second / time.Duration(ft.fps)
ft.ticker = time.NewTicker(ft.oneFrameTime)
if ft.sleepInterval == 0 {
ft.sleepInterval = defaultSleepInterval
}
go func() {
preTime := time.Now()
var preFrame FrameNumber
for {
time.Sleep(ft.sleepInterval)
frameMax := FrameNumber(time.Now().Sub(preTime) / ft.oneFrameTime)
for i := preFrame + 1; i <= frameMax; i++ {
ft.frameTick()
}
preFrame = frameMax
}
}()
return nil
}
// SetFps 设置帧率越大误差越低。如果有倍数加速需求可以适当加大fps以减少误差。默认50fps
func (ft *FrameTimer) SetFps(fps uint32) {
if fps > maxFps {
fps = maxFps
}
ft.fps = fps
}
// SetAccuracyInterval 设置时间间隔精度在循环中sleep该时间进行判断。实际上因为sleep有误差所以暂时不使用fps得出。默认为3ms
func (ft *FrameTimer) SetAccuracyInterval(interval time.Duration) {
ft.sleepInterval = interval
}
// NewGroup 创建定时器组
func (ft *FrameTimer) NewGroup() *FrameGroup {
var group FrameGroup
group.ft = ft
group.init()
ft.locker.Lock()
defer ft.locker.Unlock()
ft.mapGroup[group.groupID] = &group
return &group
}

View File

@@ -1,189 +0,0 @@
package ginmodule
import (
"context"
"datacenter/common/processor"
"github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/service"
"github.com/gin-gonic/gin"
"log/slog"
"net/http"
"strings"
)
type GinModule struct {
service.Module
*GinConf
*gin.Engine
srv *http.Server
processor []processor.IGinProcessor
}
type GinConf struct {
Addr string
}
const Sys_Event_Gin_Event event.EventType = -11
func (gm *GinModule) Init(conf *GinConf, engine *gin.Engine) {
gm.GinConf = conf
gm.Engine = engine
}
func (gm *GinModule) SetupDataProcessor(processor ...processor.IGinProcessor) {
gm.processor = processor
}
func (gm *GinModule) AppendDataProcessor(processor ...processor.IGinProcessor) {
gm.processor = append(gm.processor, processor...)
}
func (gm *GinModule) OnInit() error {
if gm.Engine == nil {
gm.Engine = gin.Default()
}
gm.srv = &http.Server{
Addr: gm.Addr,
Handler: gm.Engine,
}
gm.Engine.Use(Logger())
gm.Engine.Use(gin.Recovery())
gm.GetEventProcessor().RegEventReceiverFunc(Sys_Event_Gin_Event, gm.GetEventHandler(), gm.eventHandler)
return nil
}
func (gm *GinModule) eventHandler(ev event.IEvent) {
ginEvent := ev.(*GinEvent)
for _, handler := range ginEvent.handlersChain {
handler(ginEvent.c)
}
ginEvent.chanWait <- struct{}{}
}
func (gm *GinModule) Start() {
log.Info("http start listen", slog.Any("addr", gm.Addr))
go func() {
err := gm.srv.ListenAndServe()
if err != nil {
log.Error("ListenAndServe error", slog.Any("error", err.Error()))
}
}()
}
func (gm *GinModule) StartTLS(certFile, keyFile string) {
log.Info("http start listen", slog.Any("addr", gm.Addr))
go func() {
err := gm.srv.ListenAndServeTLS(certFile, keyFile)
if err != nil {
log.Fatal("ListenAndServeTLS error", slog.Any("error", err.Error()))
}
}()
}
func (gm *GinModule) Stop(ctx context.Context) {
if err := gm.srv.Shutdown(ctx); err != nil {
log.SError("Server Shutdown", slog.Any("error", err))
}
}
type GinEvent struct {
handlersChain gin.HandlersChain
chanWait chan struct{}
c *gin.Context
}
func (ge *GinEvent) GetEventType() event.EventType {
return Sys_Event_Gin_Event
}
func (gm *GinModule) handleMethod(httpMethod, relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
return gm.Engine.Handle(httpMethod, relativePath, func(c *gin.Context) {
for _, p := range gm.processor {
_, err := p.Process(c)
if err != nil {
return
}
}
var ev GinEvent
chanWait := make(chan struct{})
ev.chanWait = chanWait
ev.handlersChain = handlers
ev.c = c
gm.NotifyEvent(&ev)
<-chanWait
})
}
func (gm *GinModule) SafeGET(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
return gm.handleMethod(http.MethodGet, relativePath, handlers...)
}
func (gm *GinModule) SafePOST(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
return gm.handleMethod(http.MethodPost, relativePath, handlers...)
}
func (gm *GinModule) SafeDELETE(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
return gm.handleMethod(http.MethodDelete, relativePath, handlers...)
}
func (gm *GinModule) SafePATCH(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
return gm.handleMethod(http.MethodPatch, relativePath, handlers...)
}
func (gm *GinModule) SafePut(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
return gm.handleMethod(http.MethodPut, relativePath, handlers...)
}
func GetIPWithProxyHeaders(c *gin.Context) string {
// 尝试从 X-Real-IP 头部获取真实 IP
ip := c.GetHeader("X-Real-IP")
// 如果 X-Real-IP 头部不存在,则尝试从 X-Forwarded-For 头部获取
if ip == "" {
ip = c.GetHeader("X-Forwarded-For")
}
// 如果两者都不存在,则使用默认的 ClientIP 方法获取 IP
if ip == "" {
ip = c.ClientIP()
}
return ip
}
func GetIPWithValidatedProxyHeaders(c *gin.Context) string {
// 获取代理头部
proxyHeaders := c.Request.Header.Get("X-Real-IP,X-Forwarded-For")
// 分割代理头部,取第一个 IP 作为真实 IP
ips := strings.Split(proxyHeaders, ",")
ip := strings.TrimSpace(ips[0])
// 如果 IP 格式合法,则使用获取到的 IP否则使用默认的 ClientIP 方法获取
if isValidIP(ip) {
return ip
} else {
ip = c.ClientIP()
return ip
}
}
// isValidIP 判断 IP 格式是否合法
func isValidIP(ip string) bool {
// 此处添加自定义的 IP 格式验证逻辑
// 例如,使用正则表达式验证 IP 格式
// ...
if ip == "" {
return false
}
return true
}

View File

@@ -39,19 +39,19 @@ func (slf *SyncHttpResponse) Get(timeoutMs int) HttpResponse {
return rsp return rsp
} }
return HttpResponse{ return HttpResponse{
Err: fmt.Errorf("Getting the return result timeout [%d]ms", timeoutMs), Err: fmt.Errorf("getting the return result timeout [%d]ms", timeoutMs),
} }
} }
func (m *HttpClientModule) InitHttpClient(transport http.RoundTripper,timeout time.Duration,checkRedirect func(req *http.Request, via []*http.Request) error){ func (m *HttpClientModule) InitHttpClient(transport http.RoundTripper, timeout time.Duration, checkRedirect func(req *http.Request, via []*http.Request) error) {
m.client = &http.Client{ m.client = &http.Client{
Transport: transport, Transport: transport,
Timeout: timeout, Timeout: timeout,
CheckRedirect: checkRedirect, CheckRedirect: checkRedirect,
} }
} }
func (m *HttpClientModule) Init(proxyUrl string, maxpool int, dialTimeout time.Duration,dialKeepAlive time.Duration,idleConnTimeout time.Duration,timeout time.Duration) { func (m *HttpClientModule) Init(proxyUrl string, maxPool int, dialTimeout time.Duration, dialKeepAlive time.Duration, idleConnTimeout time.Duration, timeout time.Duration) {
type ProxyFun func(_ *http.Request) (*url.URL, error) type ProxyFun func(_ *http.Request) (*url.URL, error)
var proxyFun ProxyFun var proxyFun ProxyFun
if proxyUrl != "" { if proxyUrl != "" {
@@ -66,8 +66,8 @@ func (m *HttpClientModule) Init(proxyUrl string, maxpool int, dialTimeout time.D
Timeout: dialTimeout, Timeout: dialTimeout,
KeepAlive: dialKeepAlive, KeepAlive: dialKeepAlive,
}).DialContext, }).DialContext,
MaxIdleConns: maxpool, MaxIdleConns: maxPool,
MaxIdleConnsPerHost: maxpool, MaxIdleConnsPerHost: maxPool,
IdleConnTimeout: idleConnTimeout, IdleConnTimeout: idleConnTimeout,
Proxy: proxyFun, Proxy: proxyFun,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, TLSClientConfig: &tls.Config{InsecureSkipVerify: true},

View File

@@ -248,7 +248,7 @@ func (ch *ConsumerGroupHandler) ConsumeClaim(session sarama.ConsumerGroupSession
select { select {
case msg := <-claim.Messages(): case msg := <-claim.Messages():
if msg == nil { if msg == nil {
log.SWarning("claim will exit", log.Any("topic", claim.Topic()), log.Any("Partition", claim.Partition())) log.SWarn("claim will exit", log.Any("topic", claim.Topic()), log.Any("Partition", claim.Partition()))
return nil return nil
} }
ch.AppendMsg(session, msg) ch.AppendMsg(session, msg)

View File

@@ -86,7 +86,7 @@ func (p *Producer) asyncRun() {
asyncReturn := sm.Metadata.(*AsyncReturn) asyncReturn := sm.Metadata.(*AsyncReturn)
asyncReturn.chanReturn <- asyncReturn asyncReturn.chanReturn <- asyncReturn
case em := <-p.Errors(): case em := <-p.Errors():
log.Error("async kafkamodule error", log.ErrorAttr("err", em.Err)) log.Error("async kafkamodule error", log.ErrorField("err", em.Err))
if em.Msg.Metadata == nil { if em.Msg.Metadata == nil {
break break
} }

View File

@@ -5,7 +5,6 @@ import (
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/x/bsonx"
"time" "time"
) )
@@ -48,6 +47,10 @@ func (mm *MongoModule) Start() error {
return nil return nil
} }
func (mm *MongoModule) Stop() error {
return mm.client.Disconnect(context.Background())
}
func (mm *MongoModule) TakeSession() Session { func (mm *MongoModule) TakeSession() Session {
return Session{Client: mm.client, maxOperatorTimeOut: mm.maxOperatorTimeOut} return Session{Client: mm.client, maxOperatorTimeOut: mm.maxOperatorTimeOut}
} }
@@ -72,12 +75,12 @@ func (s *Session) NextSeq(db string, collection string, id interface{}) (int, er
return res.Seq, err return res.Seq, err
} }
// indexKeys[索引][每个索引key字段] // EnsureIndex indexKeys[索引][每个索引key字段]
func (s *Session) EnsureIndex(db string, collection string, indexKeys [][]string, bBackground bool, sparse bool, asc bool) error { func (s *Session) EnsureIndex(db string, collection string, indexKeys [][]string, bBackground bool, sparse bool, asc bool) error {
return s.ensureIndex(db, collection, indexKeys, bBackground, false, sparse, asc) return s.ensureIndex(db, collection, indexKeys, bBackground, false, sparse, asc)
} }
// indexKeys[索引][每个索引key字段] // EnsureUniqueIndex indexKeys[索引][每个索引key字段]
func (s *Session) EnsureUniqueIndex(db string, collection string, indexKeys [][]string, bBackground bool, sparse bool, asc bool) error { func (s *Session) EnsureUniqueIndex(db string, collection string, indexKeys [][]string, bBackground bool, sparse bool, asc bool) error {
return s.ensureIndex(db, collection, indexKeys, bBackground, true, sparse, asc) return s.ensureIndex(db, collection, indexKeys, bBackground, true, sparse, asc)
} }
@@ -86,12 +89,12 @@ func (s *Session) EnsureUniqueIndex(db string, collection string, indexKeys [][]
func (s *Session) ensureIndex(db string, collection string, indexKeys [][]string, bBackground bool, unique bool, sparse bool, asc bool) error { func (s *Session) ensureIndex(db string, collection string, indexKeys [][]string, bBackground bool, unique bool, sparse bool, asc bool) error {
var indexes []mongo.IndexModel var indexes []mongo.IndexModel
for _, keys := range indexKeys { for _, keys := range indexKeys {
keysDoc := bsonx.Doc{} keysDoc := bson.D{}
for _, key := range keys { for _, key := range keys {
if asc { if asc {
keysDoc = keysDoc.Append(key, bsonx.Int32(1)) keysDoc = append(keysDoc, bson.E{Key: key, Value: 1})
} else { } else {
keysDoc = keysDoc.Append(key, bsonx.Int32(-1)) keysDoc = append(keysDoc, bson.E{Key: key, Value: -1})
} }
} }

View File

@@ -19,8 +19,8 @@ import (
type SyncFun func() type SyncFun func()
type DBExecute struct { type DBExecute struct {
syncExecuteFun chan SyncFun syncExecuteFun chan SyncFun
syncExecuteExit chan bool syncExecuteExit chan bool
} }
type PingExecute struct { type PingExecute struct {
@@ -28,22 +28,21 @@ type PingExecute struct {
pintExit chan bool pintExit chan bool
} }
// DBModule ...
type MySQLModule struct { type MySQLModule struct {
service.Module service.Module
db *sql.DB db *sql.DB
url string url string
username string username string
password string password string
dbname string dbname string
slowDuration time.Duration slowDuration time.Duration
pingCoroutine PingExecute pingCoroutine PingExecute
waitGroup sync.WaitGroup waitGroup sync.WaitGroup
} }
// Tx ... // Tx ...
type Tx struct { type Tx struct {
tx *sql.Tx tx *sql.Tx
slowDuration time.Duration slowDuration time.Duration
} }
@@ -53,7 +52,7 @@ type DBResult struct {
RowsAffected int64 RowsAffected int64
rowNum int rowNum int
RowInfo map[string][]interface{} //map[fieldname][row]sql.NullString RowInfo map[string][]interface{} //map[fieldName][row]sql.NullString
} }
type DataSetList struct { type DataSetList struct {
@@ -63,19 +62,17 @@ type DataSetList struct {
blur bool blur bool
} }
type dbControl interface { type dbControl interface {
Exec(query string, args ...interface{}) (sql.Result, error) Exec(query string, args ...interface{}) (sql.Result, error)
Query(query string, args ...interface{}) (*sql.Rows, error) Query(query string, args ...interface{}) (*sql.Rows, error)
} }
func (m *MySQLModule) Init(url string, userName string, password string, dbname string, maxConn int) error {
func (m *MySQLModule) Init( url string, userName string, password string, dbname string,maxConn int) error {
m.url = url m.url = url
m.username = userName m.username = userName
m.password = password m.password = password
m.dbname = dbname m.dbname = dbname
m.pingCoroutine = PingExecute{tickerPing : time.NewTicker(5*time.Second), pintExit : make(chan bool, 1)} m.pingCoroutine = PingExecute{tickerPing: time.NewTicker(5 * time.Second), pintExit: make(chan bool, 1)}
return m.connect(maxConn) return m.connect(maxConn)
} }
@@ -85,12 +82,12 @@ func (m *MySQLModule) SetQuerySlowTime(slowDuration time.Duration) {
} }
func (m *MySQLModule) Query(strQuery string, args ...interface{}) (*DataSetList, error) { func (m *MySQLModule) Query(strQuery string, args ...interface{}) (*DataSetList, error) {
return query(m.slowDuration, m.db,strQuery,args...) return query(m.slowDuration, m.db, strQuery, args...)
} }
// Exec ... // Exec ...
func (m *MySQLModule) Exec(strSql string, args ...interface{}) (*DBResult, error) { func (m *MySQLModule) Exec(strSql string, args ...interface{}) (*DBResult, error) {
return exec(m.slowDuration, m.db,strSql,args...) return exec(m.slowDuration, m.db, strSql, args...)
} }
// Begin starts a transaction. // Begin starts a transaction.
@@ -98,7 +95,7 @@ func (m *MySQLModule) Begin() (*Tx, error) {
var txDBModule Tx var txDBModule Tx
txDb, err := m.db.Begin() txDb, err := m.db.Begin()
if err != nil { if err != nil {
log.Error("Begin error:%s", err.Error()) log.Error("Begin error", log.ErrorField("err",err))
return &txDBModule, err return &txDBModule, err
} }
txDBModule.slowDuration = m.slowDuration txDBModule.slowDuration = m.slowDuration
@@ -116,14 +113,14 @@ func (slf *Tx) Commit() error {
return slf.tx.Commit() return slf.tx.Commit()
} }
// QueryEx executes a query that return rows. // Query executes a query that return rows.
func (slf *Tx) Query(strQuery string, args ...interface{}) (*DataSetList, error) { func (slf *Tx) Query(strQuery string, args ...interface{}) (*DataSetList, error) {
return query(slf.slowDuration,slf.tx,strQuery,args...) return query(slf.slowDuration, slf.tx, strQuery, args...)
} }
// Exec executes a query that doesn't return rows. // Exec executes a query that doesn't return rows.
func (slf *Tx) Exec(strSql string, args ...interface{}) (*DBResult, error) { func (slf *Tx) Exec(strSql string, args ...interface{}) (*DBResult, error) {
return exec(slf.slowDuration,slf.tx,strSql,args...) return exec(slf.slowDuration, slf.tx, strSql, args...)
} }
// Connect ... // Connect ...
@@ -158,7 +155,7 @@ func (m *MySQLModule) runPing() {
for { for {
select { select {
case <-m.pingCoroutine.pintExit: case <-m.pingCoroutine.pintExit:
log.Error("RunPing stopping %s...", fmt.Sprintf("%T", m)) log.Error("RunPing stopping",log.String("url", m.url),log.String("dbname", m.dbname))
return return
case <-m.pingCoroutine.tickerPing.C: case <-m.pingCoroutine.tickerPing.C:
if m.db != nil { if m.db != nil {
@@ -168,7 +165,7 @@ func (m *MySQLModule) runPing() {
} }
} }
func checkArgs(args ...interface{}) error { func checkArgs(args ...interface{}) error {
for _, val := range args { for _, val := range args {
if reflect.TypeOf(val).Kind() == reflect.String { if reflect.TypeOf(val).Kind() == reflect.String {
retVal := val.(string) retVal := val.(string)
@@ -211,37 +208,37 @@ func checkArgs(args ...interface{}) error {
return nil return nil
} }
func checkSlow(slowDuration time.Duration,Time time.Duration) bool { func checkSlow(slowDuration time.Duration, Time time.Duration) bool {
if slowDuration != 0 && Time >=slowDuration { if slowDuration != 0 && Time >= slowDuration {
return true return true
} }
return false return false
} }
func query(slowDuration time.Duration,db dbControl,strQuery string, args ...interface{}) (*DataSetList, error) { func query(slowDuration time.Duration, db dbControl, strQuery string, args ...interface{}) (*DataSetList, error) {
datasetList := DataSetList{} datasetList := DataSetList{}
datasetList.tag = "json" datasetList.tag = "json"
datasetList.blur = true datasetList.blur = true
if checkArgs(args) != nil { if checkArgs(args) != nil {
log.Error("CheckArgs is error :%s", strQuery) log.Error("CheckArgs is error",log.String("sql",strQuery))
return &datasetList, fmt.Errorf("CheckArgs is error!") return &datasetList, fmt.Errorf("checkArgs is error")
} }
if db == nil { if db == nil {
log.Error("cannot connect database:%s", strQuery) log.Error("cannot connect database",log.String("sql", strQuery))
return &datasetList, fmt.Errorf("cannot connect database!") return &datasetList, fmt.Errorf("cannot connect database")
} }
TimeFuncStart := time.Now() TimeFuncStart := time.Now()
rows, err := db.Query(strQuery, args...) rows, err := db.Query(strQuery, args...)
timeFuncPass := time.Since(TimeFuncStart) timeFuncPass := time.Since(TimeFuncStart)
if checkSlow(slowDuration,timeFuncPass) { if checkSlow(slowDuration, timeFuncPass) {
log.Error("DBModule QueryEx Time %s , Query :%s , args :%+v", timeFuncPass, strQuery, args) log.Error("Query slow",log.Int64("time_ms",timeFuncPass.Milliseconds()),log.String("sql", strQuery), log.Any("args",args))
} }
if err != nil { if err != nil {
log.Error("Query:%s(%v)", strQuery, err) log.Error("Query error", log.String("sql",strQuery),log.ErrorField("err",err))
if rows != nil { if rows != nil {
rows.Close() rows.Close()
} }
@@ -256,7 +253,7 @@ func query(slowDuration time.Duration,db dbControl,strQuery string, args ...inte
if dbResult.RowInfo == nil { if dbResult.RowInfo == nil {
dbResult.RowInfo = make(map[string][]interface{}) dbResult.RowInfo = make(map[string][]interface{})
} }
//RowInfo map[string][][]sql.NullString //map[fieldname][row][column]sql.NullString
colField, err := rows.Columns() colField, err := rows.Columns()
if err != nil { if err != nil {
return &datasetList, err return &datasetList, err
@@ -268,10 +265,10 @@ func query(slowDuration time.Duration,db dbControl,strQuery string, args ...inte
} }
rows.Scan(valuePtrs...) rows.Scan(valuePtrs...)
for idx, fieldname := range colField { for idx, fieldName := range colField {
fieldRowData := dbResult.RowInfo[strings.ToLower(fieldname)] fieldRowData := dbResult.RowInfo[strings.ToLower(fieldName)]
fieldRowData = append(fieldRowData, valuePtrs[idx]) fieldRowData = append(fieldRowData, valuePtrs[idx])
dbResult.RowInfo[strings.ToLower(fieldname)] = fieldRowData dbResult.RowInfo[strings.ToLower(fieldName)] = fieldRowData
} }
dbResult.rowNum += 1 dbResult.rowNum += 1
} }
@@ -281,8 +278,8 @@ func query(slowDuration time.Duration,db dbControl,strQuery string, args ...inte
hasRet := rows.NextResultSet() hasRet := rows.NextResultSet()
if hasRet == false { if hasRet == false {
if rows.Err() != nil { if rowErr :=rows.Err();rowErr != nil {
log.Error( "Query:%s(%+v)", strQuery, rows) log.Error("NextResultSet error", log.String("sql",strQuery), log.ErrorField("err",rowErr))
} }
break break
} }
@@ -291,26 +288,26 @@ func query(slowDuration time.Duration,db dbControl,strQuery string, args ...inte
return &datasetList, nil return &datasetList, nil
} }
func exec(slowDuration time.Duration,db dbControl,strSql string, args ...interface{}) (*DBResult, error) { func exec(slowDuration time.Duration, db dbControl, strSql string, args ...interface{}) (*DBResult, error) {
ret := &DBResult{} ret := &DBResult{}
if db == nil { if db == nil {
log.Error("cannot connect database:%s", strSql) log.Error("cannot connect database", log.String("sql",strSql))
return ret, fmt.Errorf("cannot connect database!") return ret, fmt.Errorf("cannot connect database")
} }
if checkArgs(args) != nil { if checkArgs(args) != nil {
log.Error("CheckArgs is error :%s", strSql) log.Error("CheckArgs is error", log.String("sql",strSql))
return ret, fmt.Errorf("CheckArgs is error!") return ret, fmt.Errorf("checkArgs is error")
} }
TimeFuncStart := time.Now() TimeFuncStart := time.Now()
res, err := db.Exec(strSql, args...) res, err := db.Exec(strSql, args...)
timeFuncPass := time.Since(TimeFuncStart) timeFuncPass := time.Since(TimeFuncStart)
if checkSlow(slowDuration,timeFuncPass) { if checkSlow(slowDuration, timeFuncPass) {
log.Error("DBModule QueryEx Time %s , Query :%s , args :%+v", timeFuncPass, strSql, args) log.Error("Exec slow",log.Int64("time_ms",timeFuncPass.Milliseconds()),log.String("sql",strSql),log.Any("args",args) )
} }
if err != nil { if err != nil {
log.Error("Exec:%s(%v)", strSql, err) log.Error("Exec error",log.String("sql",strSql),log.ErrorField("err", err))
return nil, err return nil, err
} }
@@ -361,21 +358,21 @@ func (ds *DataSetList) slice2interface(in interface{}) error {
} }
v := reflect.ValueOf(in).Elem() v := reflect.ValueOf(in).Elem()
newv := reflect.MakeSlice(v.Type(), 0, length) newV := reflect.MakeSlice(v.Type(), 0, length)
v.Set(newv) v.Set(newV)
v.SetLen(length) v.SetLen(length)
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
idxv := v.Index(i) idxV := v.Index(i)
if idxv.Kind() == reflect.Ptr { if idxV.Kind() == reflect.Ptr {
newObj := reflect.New(idxv.Type().Elem()) newObj := reflect.New(idxV.Type().Elem())
v.Index(i).Set(newObj) v.Index(i).Set(newObj)
idxv = newObj idxV = newObj
} else { } else {
idxv = idxv.Addr() idxV = idxV.Addr()
} }
err := ds.rowData2interface(i, ds.dataSetList[ds.currentDataSetIdx].RowInfo, idxv) err := ds.rowData2interface(i, ds.dataSetList[ds.currentDataSetIdx].RowInfo, idxV)
if err != nil { if err != nil {
return err return err
} }
@@ -390,7 +387,7 @@ func (ds *DataSetList) rowData2interface(rowIdx int, m map[string][]interface{},
typ := t.Elem() typ := t.Elem()
if !val.IsValid() { if !val.IsValid() {
return errors.New("Incorrect data type!") return errors.New("incorrect data type")
} }
for i := 0; i < val.NumField(); i++ { for i := 0; i < val.NumField(); i++ {
@@ -402,11 +399,11 @@ func (ds *DataSetList) rowData2interface(rowIdx int, m map[string][]interface{},
} }
if tag != "" && tag != "-" { if tag != "" && tag != "-" {
vtag := strings.ToLower(tag) vTag := strings.ToLower(tag)
columnData, ok := m[vtag] columnData, ok := m[vTag]
if ok == false { if ok == false {
if !ds.blur { if !ds.blur {
return fmt.Errorf("Cannot find filed name %s!", vtag) return fmt.Errorf("cannot find filed name %s", vTag)
} }
continue continue
} }
@@ -416,12 +413,12 @@ func (ds *DataSetList) rowData2interface(rowIdx int, m map[string][]interface{},
meta := columnData[rowIdx].(*sql.NullString) meta := columnData[rowIdx].(*sql.NullString)
if !ok { if !ok {
if !ds.blur { if !ds.blur {
return fmt.Errorf("No corresponding field was found in the result set %s!", tag) return fmt.Errorf("no corresponding field was found in the result set %s", tag)
} }
continue continue
} }
if !value.CanSet() { if !value.CanSet() {
return errors.New("Struct fields do not have read or write permissions!") return errors.New("struct fields do not have read or write permissions")
} }
if meta.Valid == false { if meta.Valid == false {
@@ -460,7 +457,7 @@ func (ds *DataSetList) rowData2interface(rowIdx int, m map[string][]interface{},
} }
value.SetBool(b) value.SetBool(b)
default: default:
return errors.New("The database map has unrecognized data types!") return errors.New("the database map has unrecognized data types")
} }
} }
} }

View File

@@ -0,0 +1,313 @@
package ginmodule
import (
"context"
"github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/service"
"github.com/gin-gonic/gin"
"io"
"net/http"
"strings"
"time"
)
type IGinProcessor interface {
Process(data *gin.Context) (*gin.Context, error)
}
type GinModule struct {
service.Module
*gin.Engine
srv *http.Server
listenAddr string
handleTimeout time.Duration
processor []IGinProcessor
}
func (gm *GinModule) Init(addr string, handleTimeout time.Duration, engine *gin.Engine) {
gm.listenAddr = addr
gm.handleTimeout = handleTimeout
gm.Engine = engine
}
func (gm *GinModule) SetupDataProcessor(processor ...IGinProcessor) {
gm.processor = processor
}
func (gm *GinModule) AppendDataProcessor(processor ...IGinProcessor) {
gm.processor = append(gm.processor, processor...)
}
func (gm *GinModule) OnInit() error {
if gm.Engine == nil {
gm.Engine = gin.Default()
}
gm.srv = &http.Server{
Addr: gm.listenAddr,
Handler: gm.Engine,
}
gm.Engine.Use(Logger())
gm.Engine.Use(gin.Recovery())
gm.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_Gin_Event, gm.GetEventHandler(), gm.eventHandler)
return nil
}
func (gm *GinModule) eventHandler(ev event.IEvent) {
ginEvent := ev.(*GinEvent)
for _, handler := range ginEvent.handlersChain {
handler(&ginEvent.c)
}
//ginEvent.chanWait <- struct{}{}
}
func (gm *GinModule) Start() {
gm.srv.Addr = gm.listenAddr
log.Info("http start listen", log.Any("addr", gm.listenAddr))
go func() {
err := gm.srv.ListenAndServe()
if err != nil {
log.Error("ListenAndServe error", log.Any("error", err.Error()))
}
}()
}
func (gm *GinModule) StartTLS(certFile, keyFile string) {
log.Info("http start listen", log.Any("addr", gm.listenAddr))
go func() {
err := gm.srv.ListenAndServeTLS(certFile, keyFile)
if err != nil {
log.Fatal("ListenAndServeTLS error", log.Any("error", err.Error()))
}
}()
}
func (gm *GinModule) Stop(ctx context.Context) {
if err := gm.srv.Shutdown(ctx); err != nil {
log.Error("Server Shutdown", log.Any("error", err))
}
}
type SafeContext struct {
*gin.Context
chanWait chan struct{}
}
func (c *SafeContext) JSONAndDone(code int, obj any) {
c.Context.JSON(code, obj)
c.Done()
}
func (c *SafeContext) AsciiJSONAndDone(code int, obj any) {
c.Context.AsciiJSON(code, obj)
c.Done()
}
func (c *SafeContext) PureJSONAndDone(code int, obj any) {
c.Context.PureJSON(code, obj)
c.Done()
}
func (c *SafeContext) XMLAndDone(code int, obj any) {
c.Context.XML(code, obj)
c.Done()
}
func (c *SafeContext) YAMLAndDone(code int, obj any) {
c.Context.YAML(code, obj)
c.Done()
}
func (c *SafeContext) TOMLAndDone(code int, obj any) {
c.Context.TOML(code, obj)
c.Done()
}
func (c *SafeContext) ProtoBufAndDone(code int, obj any) {
c.Context.ProtoBuf(code, obj)
c.Done()
}
func (c *SafeContext) StringAndDone(code int, format string, values ...any) {
c.Context.String(code, format, values...)
c.Done()
}
func (c *SafeContext) RedirectAndDone(code int, location string) {
c.Context.Redirect(code, location)
c.Done()
}
func (c *SafeContext) DataAndDone(code int, contentType string, data []byte) {
c.Context.Data(code, contentType, data)
c.Done()
}
func (c *SafeContext) DataFromReaderAndDone(code int, contentLength int64, contentType string, reader io.Reader, extraHeaders map[string]string) {
c.DataFromReader(code, contentLength, contentType, reader, extraHeaders)
c.Done()
}
func (c *SafeContext) HTMLAndDone(code int, name string, obj any) {
c.Context.HTML(code, name, obj)
c.Done()
}
func (c *SafeContext) IndentedJSONAndDone(code int, obj any) {
c.Context.IndentedJSON(code, obj)
c.Done()
}
func (c *SafeContext) SecureJSONAndDone(code int, obj any) {
c.Context.SecureJSON(code, obj)
c.Done()
}
func (c *SafeContext) JSONPAndDone(code int, obj any) {
c.Context.JSONP(code, obj)
c.Done()
}
func (c *SafeContext) Done() {
c.chanWait <- struct{}{}
}
type GinEvent struct {
handlersChain []SafeHandlerFunc
c SafeContext
}
type SafeHandlerFunc func(*SafeContext)
func (ge *GinEvent) GetEventType() event.EventType {
return event.Sys_Event_Gin_Event
}
func (gm *GinModule) handleMethod(httpMethod, relativePath string, handlers ...SafeHandlerFunc) gin.IRoutes {
return gm.Engine.Handle(httpMethod, relativePath, func(c *gin.Context) {
for _, p := range gm.processor {
_, err := p.Process(c)
if err != nil {
return
}
}
var ev GinEvent
chanWait := make(chan struct{}, 2)
ev.c.chanWait = chanWait
ev.handlersChain = handlers
ev.c.Context = c
gm.NotifyEvent(&ev)
ctx, cancel := context.WithTimeout(context.Background(), gm.handleTimeout)
defer cancel()
select {
case <-ctx.Done():
log.Error("GinModule process timeout", log.Any("path", c.Request.URL.Path))
c.AbortWithStatus(http.StatusRequestTimeout)
case <-chanWait:
}
})
}
// GET 回调处理是在gin协程中
func (gm *GinModule) GET(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
return gm.Engine.GET(relativePath, handlers...)
}
// POST 回调处理是在gin协程中
func (gm *GinModule) POST(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
return gm.Engine.POST(relativePath, handlers...)
}
// DELETE 回调处理是在gin协程中
func (gm *GinModule) DELETE(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
return gm.Engine.DELETE(relativePath, handlers...)
}
// PATCH 回调处理是在gin协程中
func (gm *GinModule) PATCH(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
return gm.Engine.PATCH(relativePath, handlers...)
}
// Put 回调处理是在gin协程中
func (gm *GinModule) Put(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
return gm.Engine.PUT(relativePath, handlers...)
}
// SafeGET 回调处理是在service协程中
func (gm *GinModule) SafeGET(relativePath string, handlers ...SafeHandlerFunc) gin.IRoutes {
return gm.handleMethod(http.MethodGet, relativePath, handlers...)
}
// SafePOST 回调处理是在service协程中
func (gm *GinModule) SafePOST(relativePath string, handlers ...SafeHandlerFunc) gin.IRoutes {
return gm.handleMethod(http.MethodPost, relativePath, handlers...)
}
// SafeDELETE 回调处理是在service协程中
func (gm *GinModule) SafeDELETE(relativePath string, handlers ...SafeHandlerFunc) gin.IRoutes {
return gm.handleMethod(http.MethodDelete, relativePath, handlers...)
}
// SafePATCH 回调处理是在service协程中
func (gm *GinModule) SafePATCH(relativePath string, handlers ...SafeHandlerFunc) gin.IRoutes {
return gm.handleMethod(http.MethodPatch, relativePath, handlers...)
}
// SafePut 回调处理是在service协程中
func (gm *GinModule) SafePut(relativePath string, handlers ...SafeHandlerFunc) gin.IRoutes {
return gm.handleMethod(http.MethodPut, relativePath, handlers...)
}
func GetIPWithProxyHeaders(c *gin.Context) string {
// 尝试从 X-Real-IP 头部获取真实 IP
ip := c.GetHeader("X-Real-IP")
// 如果 X-Real-IP 头部不存在,则尝试从 X-Forwarded-For 头部获取
if ip == "" {
ip = c.GetHeader("X-Forwarded-For")
}
// 如果两者都不存在,则使用默认的 ClientIP 方法获取 IP
if ip == "" {
ip = c.ClientIP()
}
return ip
}
func GetIPWithValidatedProxyHeaders(c *gin.Context) string {
// 获取代理头部
proxyHeaders := c.Request.Header.Get("X-Real-IP,X-Forwarded-For")
// 分割代理头部,取第一个 IP 作为真实 IP
ips := strings.Split(proxyHeaders, ",")
ip := strings.TrimSpace(ips[0])
// 如果 IP 格式合法,则使用获取到的 IP否则使用默认的 ClientIP 方法获取
if isValidIP(ip) {
return ip
} else {
ip = c.ClientIP()
return ip
}
}
// isValidIP 判断 IP 格式是否合法
func isValidIP(ip string) bool {
// 此处添加自定义的 IP 格式验证逻辑
// 例如,使用正则表达式验证 IP 格式
// ...
if ip == "" {
return false
}
return true
}

View File

@@ -2,7 +2,7 @@ package ginmodule
import ( import (
"fmt" "fmt"
"github.com/duanhf2012/origin/log" "github.com/duanhf2012/origin/v2/log"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"time" "time"
) )
@@ -44,7 +44,7 @@ func Logger() gin.HandlerFunc {
// 响应状态码 // 响应状态码
statusCode := c.Writer.Status() statusCode := c.Writer.Status()
log.SDebug(fmt.Sprintf( log.Debug(fmt.Sprintf(
"%s | %3d | %s %10s | \033[44;37m%-6s\033[0m %s %s | %10v | \"%s\" \"%s\"", "%s | %3d | %s %10s | \033[44;37m%-6s\033[0m %s %s | %10v | \"%s\" \"%s\"",
colorForStatus(statusCode), colorForStatus(statusCode),
statusCode, statusCode,

View File

@@ -0,0 +1,210 @@
package kcpmodule
import (
"fmt"
"github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/network"
"github.com/duanhf2012/origin/v2/network/processor"
"github.com/duanhf2012/origin/v2/service"
"github.com/xtaci/kcp-go/v5"
"go.mongodb.org/mongo-driver/bson/primitive"
"sync"
)
type KcpModule struct {
service.Module
blockCrypt kcp.BlockCrypt
mapClientLocker sync.RWMutex
mapClient map[string]*Client
process processor.IRawProcessor
kcpServer network.KCPServer
kcpCfg *network.KcpCfg
}
type Client struct {
id string
kcpConn *network.NetConn
kcpModule *KcpModule
}
type KcpPackType int8
const (
KPTConnected KcpPackType = 0
KPTDisConnected KcpPackType = 1
KPTPack KcpPackType = 2
KPTUnknownPack KcpPackType = 3
)
type KcpPack struct {
Type KcpPackType //0表示连接 1表示断开 2表示数据
ClientId string
Data interface{}
RecyclerReaderBytes func(data []byte)
}
func (km *KcpModule) OnInit() error {
if km.kcpCfg == nil || km.process == nil {
return fmt.Errorf("please call the Init function correctly")
}
km.mapClient = make(map[string]*Client, km.kcpCfg.MaxConnNum)
km.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_Kcp, km.GetEventHandler(), km.kcpEventHandler)
km.process.SetByteOrder(km.kcpCfg.LittleEndian)
km.kcpServer.Init(km.kcpCfg)
km.kcpServer.NewAgent = km.NewAgent
return nil
}
func (km *KcpModule) Init(kcpCfg *network.KcpCfg, process processor.IRawProcessor) {
km.kcpCfg = kcpCfg
km.process = process
}
func (km *KcpModule) Start() error {
return km.kcpServer.Start()
}
func (km *KcpModule) kcpEventHandler(ev event.IEvent) {
e := ev.(*event.Event)
switch KcpPackType(e.IntExt[0]) {
case KPTConnected:
km.process.ConnectedRoute(e.StringExt[0])
case KPTDisConnected:
km.process.DisConnectedRoute(e.StringExt[0])
case KPTUnknownPack:
km.process.UnknownMsgRoute(e.StringExt[0], e.Data, e.AnyExt[0].(func(data []byte)))
case KPTPack:
km.process.MsgRoute(e.StringExt[0], e.Data, e.AnyExt[0].(func(data []byte)))
}
event.DeleteEvent(ev)
}
func (km *KcpModule) SetBlob(blockCrypt kcp.BlockCrypt) {
km.blockCrypt = blockCrypt
}
func (km *KcpModule) OnConnected(c *Client) {
ev := event.NewEvent()
ev.Type = event.Sys_Event_Kcp
ev.IntExt[0] = int64(KPTConnected)
ev.StringExt[0] = c.id
km.NotifyEvent(ev)
}
func (km *KcpModule) OnClose(c *Client) {
ev := event.NewEvent()
ev.Type = event.Sys_Event_Kcp
ev.IntExt[0] = int64(KPTDisConnected)
ev.StringExt[0] = c.id
km.NotifyEvent(ev)
}
func (km *KcpModule) newClient(conn network.Conn) *Client {
km.mapClientLocker.Lock()
defer km.mapClientLocker.Unlock()
pClient := &Client{kcpConn: conn.(*network.NetConn), id: primitive.NewObjectID().Hex()}
pClient.kcpModule = km
km.mapClient[pClient.id] = pClient
return pClient
}
func (km *KcpModule) GetProcessor() processor.IRawProcessor {
return km.process
}
func (km *KcpModule) SendRawMsg(clientId string, data []byte) error {
km.mapClientLocker.Lock()
client, ok := km.mapClient[clientId]
if ok == false {
km.mapClientLocker.Unlock()
return fmt.Errorf("client %s is disconnect", clientId)
}
km.mapClientLocker.Unlock()
return client.kcpConn.WriteMsg(data)
}
func (km *KcpModule) Close(clientId string) {
km.mapClientLocker.Lock()
client, ok := km.mapClient[clientId]
if ok == false {
km.mapClientLocker.Unlock()
return
}
km.mapClientLocker.Unlock()
client.kcpConn.Close()
}
func (km *KcpModule) GetClientIp(clientId string) string {
km.mapClientLocker.Lock()
defer km.mapClientLocker.Unlock()
client, ok := km.mapClient[clientId]
if ok == false {
return ""
}
removeAddr := client.kcpConn.RemoteAddr()
if removeAddr != nil {
return removeAddr.String()
}
return ""
}
func (km *KcpModule) NewAgent(conn network.Conn) network.Agent {
c := km.newClient(conn)
return c
}
func (c *Client) Run() {
defer func() {
if r := recover(); r != nil {
log.StackError(fmt.Sprint(r))
}
}()
c.kcpModule.OnConnected(c)
for c.kcpConn != nil {
c.kcpConn.SetReadDeadline(*c.kcpModule.kcpCfg.ReadDeadlineMill)
msgBuff, err := c.kcpConn.ReadMsg()
if err != nil {
log.Debug("read client failed", log.ErrorField("error", err), log.String("clientId", c.id))
break
}
data, err := c.kcpModule.process.Unmarshal(c.id, msgBuff)
if err != nil {
ev := event.NewEvent()
ev.Type = event.Sys_Event_Kcp
ev.IntExt[0] = int64(KPTUnknownPack)
ev.StringExt[0] = c.id
ev.Data = msgBuff
ev.AnyExt[0] = c.kcpConn.GetRecyclerReaderBytes()
c.kcpModule.NotifyEvent(ev)
continue
}
ev := event.NewEvent()
ev.Type = event.Sys_Event_Kcp
ev.IntExt[0] = int64(KPTPack)
ev.StringExt[0] = c.id
ev.Data = data
ev.AnyExt[0] = c.kcpConn.GetRecyclerReaderBytes()
c.kcpModule.NotifyEvent(ev)
}
}
func (c *Client) OnClose() {
c.kcpModule.OnClose(c)
c.kcpModule.mapClientLocker.Lock()
delete(c.kcpModule.mapClient, c.id)
c.kcpModule.mapClientLocker.Unlock()
}

View File

@@ -0,0 +1,219 @@
package tcpmodule
import (
"fmt"
"github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/network"
"github.com/duanhf2012/origin/v2/network/processor"
"github.com/duanhf2012/origin/v2/service"
"go.mongodb.org/mongo-driver/bson/primitive"
"sync"
"time"
)
type TcpModule struct {
tcpServer network.TCPServer
service.Module
mapClientLocker sync.RWMutex
mapClient map[string]*Client
process processor.IRawProcessor
tcpCfg *TcpCfg
}
type TcpPackType int8
const (
TPTConnected TcpPackType = 0
TPTDisConnected TcpPackType = 1
TPTPack TcpPackType = 2
TPTUnknownPack TcpPackType = 3
)
type TcpPack struct {
Type TcpPackType //0表示连接 1表示断开 2表示数据
ClientId string
Data interface{}
RecyclerReaderBytes func(data []byte)
}
type Client struct {
id string
tcpConn *network.NetConn
tcpModule *TcpModule
}
type TcpCfg struct {
ListenAddr string //监听地址
MaxConnNum int //最大连接数
PendingWriteNum int //写channel最大消息数量
LittleEndian bool //是否小端序
LenMsgLen int //消息头占用byte数量只能是1byte,2byte,4byte。如果是4byte意味着消息最大可以是math.MaxUint32(4GB)
MinMsgLen uint32 //最小消息长度
MaxMsgLen uint32 //最大消息长度,超过判定不合法,断开连接
ReadDeadlineSecond time.Duration //读超时
WriteDeadlineSecond time.Duration //写超时
}
func (tm *TcpModule) OnInit() error {
if tm.tcpCfg == nil || tm.process == nil {
return fmt.Errorf("please call the Init function correctly")
}
//2.初始化网络模块
tm.tcpServer.Addr = tm.tcpCfg.ListenAddr
tm.tcpServer.MaxConnNum = tm.tcpCfg.MaxConnNum
tm.tcpServer.PendingWriteNum = tm.tcpCfg.PendingWriteNum
tm.tcpServer.LittleEndian = tm.tcpCfg.LittleEndian
tm.tcpServer.LenMsgLen = tm.tcpCfg.LenMsgLen
tm.tcpServer.MinMsgLen = tm.tcpCfg.MinMsgLen
tm.tcpServer.MaxMsgLen = tm.tcpCfg.MaxMsgLen
tm.tcpServer.ReadDeadline = tm.tcpCfg.ReadDeadlineSecond * time.Second
tm.tcpServer.WriteDeadline = tm.tcpCfg.WriteDeadlineSecond * time.Second
tm.mapClient = make(map[string]*Client, tm.tcpServer.MaxConnNum)
tm.tcpServer.NewAgent = tm.NewClient
//3.设置解析处理器
tm.process.SetByteOrder(tm.tcpCfg.LittleEndian)
//4.设置网络事件处理
tm.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_Tcp, tm.GetEventHandler(), tm.tcpEventHandler)
return nil
}
func (tm *TcpModule) Init(tcpCfg *TcpCfg, process processor.IRawProcessor) {
tm.tcpCfg = tcpCfg
tm.process = process
}
func (tm *TcpModule) Start() error {
return tm.tcpServer.Start()
}
func (tm *TcpModule) tcpEventHandler(ev event.IEvent) {
pack := ev.(*event.Event).Data.(TcpPack)
switch pack.Type {
case TPTConnected:
tm.process.ConnectedRoute(pack.ClientId)
case TPTDisConnected:
tm.process.DisConnectedRoute(pack.ClientId)
case TPTUnknownPack:
tm.process.UnknownMsgRoute(pack.ClientId, pack.Data, pack.RecyclerReaderBytes)
case TPTPack:
tm.process.MsgRoute(pack.ClientId, pack.Data, pack.RecyclerReaderBytes)
}
}
func (tm *TcpModule) NewClient(conn network.Conn) network.Agent {
tm.mapClientLocker.Lock()
defer tm.mapClientLocker.Unlock()
clientId := primitive.NewObjectID().Hex()
pClient := &Client{tcpConn: conn.(*network.NetConn), id: clientId}
pClient.tcpModule = tm
tm.mapClient[clientId] = pClient
return pClient
}
func (slf *Client) GetId() string {
return slf.id
}
func (slf *Client) Run() {
defer func() {
if r := recover(); r != nil {
log.StackError(fmt.Sprint(r))
}
}()
slf.tcpModule.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPTConnected}})
for slf.tcpConn != nil {
slf.tcpConn.SetReadDeadline(slf.tcpModule.tcpServer.ReadDeadline)
bytes, err := slf.tcpConn.ReadMsg()
if err != nil {
log.Debug("read client failed", log.ErrorField("error", err), log.String("clientId", slf.id))
break
}
data, err := slf.tcpModule.process.Unmarshal(slf.id, bytes)
if err != nil {
slf.tcpModule.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPTUnknownPack, Data: bytes, RecyclerReaderBytes: slf.tcpConn.GetRecyclerReaderBytes()}})
continue
}
slf.tcpModule.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPTPack, Data: data, RecyclerReaderBytes: slf.tcpConn.GetRecyclerReaderBytes()}})
}
}
func (slf *Client) OnClose() {
slf.tcpModule.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPTDisConnected}})
slf.tcpModule.mapClientLocker.Lock()
defer slf.tcpModule.mapClientLocker.Unlock()
delete(slf.tcpModule.mapClient, slf.GetId())
}
func (tm *TcpModule) SendMsg(clientId string, msg interface{}) error {
tm.mapClientLocker.Lock()
client, ok := tm.mapClient[clientId]
if ok == false {
tm.mapClientLocker.Unlock()
return fmt.Errorf("client %s is disconnect", clientId)
}
tm.mapClientLocker.Unlock()
bytes, err := tm.process.Marshal(clientId, msg)
if err != nil {
return err
}
return client.tcpConn.WriteMsg(bytes)
}
func (tm *TcpModule) Close(clientId string) {
tm.mapClientLocker.Lock()
defer tm.mapClientLocker.Unlock()
client, ok := tm.mapClient[clientId]
if ok == false {
return
}
if client.tcpConn != nil {
client.tcpConn.Close()
}
log.SWarn("close client:", clientId)
return
}
func (tm *TcpModule) GetClientIp(clientId string) string {
tm.mapClientLocker.Lock()
defer tm.mapClientLocker.Unlock()
pClient, ok := tm.mapClient[clientId]
if ok == false {
return ""
}
return pClient.tcpConn.GetRemoteIp()
}
func (tm *TcpModule) SendRawMsg(clientId string, msg []byte) error {
tm.mapClientLocker.Lock()
client, ok := tm.mapClient[clientId]
if ok == false {
tm.mapClientLocker.Unlock()
return fmt.Errorf("client %s is disconnect", clientId)
}
tm.mapClientLocker.Unlock()
return client.tcpConn.WriteMsg(msg)
}
func (tm *TcpModule) GetConnNum() int {
tm.mapClientLocker.Lock()
connNum := len(tm.mapClient)
tm.mapClientLocker.Unlock()
return connNum
}
func (tm *TcpModule) GetProcessor() processor.IRawProcessor {
return tm.process
}

View File

@@ -0,0 +1,210 @@
package wsmodule
import (
"fmt"
"github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/network"
"github.com/duanhf2012/origin/v2/network/processor"
"github.com/duanhf2012/origin/v2/service"
"go.mongodb.org/mongo-driver/bson/primitive"
"sync"
)
type WSModule struct {
service.Module
WSServer network.WSServer
mapClientLocker sync.RWMutex
mapClient map[string]*WSClient
process processor.IRawProcessor
wsCfg *WSCfg
}
type WSClient struct {
id string
wsConn *network.WSConn
wsModule *WSModule
}
type WSCfg struct {
ListenAddr string
MaxConnNum int
PendingWriteNum int
MaxMsgLen uint32
LittleEndian bool //是否小端序
KeyFile string
CertFile string
}
type WSPackType int8
const (
WPTConnected WSPackType = 0
WPTDisConnected WSPackType = 1
WPTPack WSPackType = 2
WPTUnknownPack WSPackType = 3
)
type WSPack struct {
Type WSPackType //0表示连接 1表示断开 2表示数据
MsgProcessor processor.IRawProcessor
ClientId string
Data any
}
func (ws *WSModule) OnInit() error {
if ws.wsCfg == nil || ws.process == nil {
return fmt.Errorf("please call the Init function correctly")
}
ws.WSServer.MaxConnNum = ws.wsCfg.MaxConnNum
ws.WSServer.PendingWriteNum = ws.wsCfg.PendingWriteNum
ws.WSServer.MaxMsgLen = ws.wsCfg.MaxMsgLen
ws.WSServer.Addr = ws.wsCfg.ListenAddr
if ws.wsCfg.KeyFile != "" && ws.wsCfg.CertFile != "" {
ws.WSServer.KeyFile = ws.wsCfg.KeyFile
ws.WSServer.CertFile = ws.wsCfg.CertFile
}
// 设置解析处理器
ws.process.SetByteOrder(ws.wsCfg.LittleEndian)
ws.mapClient = make(map[string]*WSClient, ws.WSServer.MaxConnNum)
ws.WSServer.NewAgent = ws.NewWSClient
// 设置网络事件处理
ws.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_WebSocket, ws.GetEventHandler(), ws.wsEventHandler)
return nil
}
func (ws *WSModule) Init(wsCfg *WSCfg, process processor.IRawProcessor) {
ws.wsCfg = wsCfg
ws.process = process
}
func (ws *WSModule) Start() error {
return ws.WSServer.Start()
}
func (ws *WSModule) wsEventHandler(ev event.IEvent) {
pack := ev.(*event.Event).Data.(*WSPack)
switch pack.Type {
case WPTConnected:
ws.process.ConnectedRoute(pack.ClientId)
case WPTDisConnected:
ws.process.DisConnectedRoute(pack.ClientId)
case WPTUnknownPack:
ws.process.UnknownMsgRoute(pack.ClientId, pack.Data, ws.recyclerReaderBytes)
case WPTPack:
ws.process.MsgRoute(pack.ClientId, pack.Data, ws.recyclerReaderBytes)
}
}
func (ws *WSModule) recyclerReaderBytes([]byte) {
}
func (ws *WSModule) NewWSClient(conn *network.WSConn) network.Agent {
ws.mapClientLocker.Lock()
defer ws.mapClientLocker.Unlock()
pClient := &WSClient{wsConn: conn, id: primitive.NewObjectID().Hex()}
pClient.wsModule = ws
ws.mapClient[pClient.id] = pClient
return pClient
}
func (wc *WSClient) GetId() string {
return wc.id
}
func (wc *WSClient) Run() {
wc.wsModule.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: wc.id, Type: WPTConnected}})
for {
bytes, err := wc.wsConn.ReadMsg()
if err != nil {
log.Debug("read client is error", log.String("clientId", wc.id), log.ErrorField("err", err))
break
}
data, err := wc.wsModule.process.Unmarshal(wc.id, bytes)
if err != nil {
wc.wsModule.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: wc.id, Type: WPTUnknownPack, Data: bytes}})
continue
}
wc.wsModule.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: wc.id, Type: WPTPack, Data: data}})
}
}
func (wc *WSClient) OnClose() {
wc.wsModule.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: wc.id, Type: WPTDisConnected}})
wc.wsModule.mapClientLocker.Lock()
defer wc.wsModule.mapClientLocker.Unlock()
delete(wc.wsModule.mapClient, wc.GetId())
}
func (ws *WSModule) GetProcessor() processor.IRawProcessor {
return ws.process
}
func (ws *WSModule) GetClientIp(clientId string) string {
ws.mapClientLocker.Lock()
defer ws.mapClientLocker.Unlock()
pClient, ok := ws.mapClient[clientId]
if ok == false {
return ""
}
return pClient.wsConn.RemoteAddr().String()
}
func (ws *WSModule) Close(clientId string) {
ws.mapClientLocker.Lock()
defer ws.mapClientLocker.Unlock()
client, ok := ws.mapClient[clientId]
if ok == false {
return
}
if client.wsConn != nil {
client.wsConn.Close()
}
return
}
func (ws *WSModule) SendMsg(clientId string, msg interface{}) error {
ws.mapClientLocker.Lock()
client, ok := ws.mapClient[clientId]
if ok == false {
ws.mapClientLocker.Unlock()
return fmt.Errorf("client %s is disconnect", clientId)
}
ws.mapClientLocker.Unlock()
bytes, err := ws.process.Marshal(clientId, msg)
if err != nil {
return err
}
return client.wsConn.WriteMsg(bytes)
}
func (ws *WSModule) SendRawMsg(clientId string, msg []byte) error {
ws.mapClientLocker.Lock()
client, ok := ws.mapClient[clientId]
if ok == false {
ws.mapClientLocker.Unlock()
return fmt.Errorf("client %s is disconnect", clientId)
}
ws.mapClientLocker.Unlock()
return client.wsConn.WriteMsg(msg)
}
func (ws *WSModule) SetMessageType(messageType int) {
ws.WSServer.SetMessageType(messageType)
}

View File

@@ -66,7 +66,7 @@ func (m *RedisModule) Init(redisCfg *ConfigRedis) {
} }
c, err := redis.Dial("tcp", redisServer, opt...) c, err := redis.Dial("tcp", redisServer, opt...)
if err != nil { if err != nil {
log.Error("Connect redis fail reason:%v", err) log.Error("Connect redis fail", log.ErrorField("err",err))
return nil, err return nil, err
} }
@@ -79,7 +79,7 @@ func (m *RedisModule) Init(redisCfg *ConfigRedis) {
} }
_, err := c.Do("PING") _, err := c.Do("PING")
if err != nil { if err != nil {
log.Error("Do PING fail reason:%v", err) log.Error("Do PING fail reason", log.ErrorField("err",err))
return err return err
} }
return err return err
@@ -90,18 +90,18 @@ func (m *RedisModule) Init(redisCfg *ConfigRedis) {
func (m *RedisModule) getConn() (redis.Conn, error) { func (m *RedisModule) getConn() (redis.Conn, error) {
if m.redisPool == nil { if m.redisPool == nil {
log.Error("Not Init RedisModule") log.Error("Not Init RedisModule")
return nil, fmt.Errorf("Not Init RedisModule") return nil, fmt.Errorf("not Init RedisModule")
} }
conn := m.redisPool.Get() conn := m.redisPool.Get()
if conn == nil { if conn == nil {
log.Error("Cannot get connection") log.Error("Cannot get connection")
return nil, fmt.Errorf("Cannot get connection") return nil, fmt.Errorf("cannot get connection")
} }
if conn.Err() != nil { if conn.Err() != nil {
err := conn.Err() err := conn.Err()
if err != nil { if err != nil {
log.Error("Get Conn have error,reason:%v", err) log.Error("get Conn have error", log.ErrorField("err",err))
} }
conn.Close() conn.Close()
return nil, err return nil, err
@@ -118,7 +118,7 @@ func (m *RedisModule) TestPingRedis() error {
err = m.redisPool.TestOnBorrow(conn, time.Now()) err = m.redisPool.TestOnBorrow(conn, time.Now())
if err != nil { if err != nil {
log.Error("TestOnBorrow fail,reason:%v", err) log.Error("TestOnBorrow fail", log.ErrorField("err",err))
return err return err
} }
@@ -153,7 +153,7 @@ func (m *RedisModule) SetStringJSONExpire(key interface{}, val interface{}, expi
func (m *RedisModule) setStringByExpire(key, value, expire interface{}) error { func (m *RedisModule) setStringByExpire(key, value, expire interface{}) error {
if key == "" { if key == "" {
return errors.New("Key Is Empty") return errors.New("key is empty")
} }
conn, err := m.getConn() conn, err := m.getConn()
@@ -171,7 +171,7 @@ func (m *RedisModule) setStringByExpire(key, value, expire interface{}) error {
} }
if retErr != nil { if retErr != nil {
log.Error("setStringByExpire fail,reason:%v", retErr) log.Error("setStringByExpire fail", log.ErrorField("err",retErr))
return retErr return retErr
} }
@@ -254,7 +254,7 @@ func (m *RedisModule) setMuchStringByExpire(mapInfo map[interface{}]interface{},
} }
if serr != nil { if serr != nil {
log.Error("setMuchStringByExpire fail,reason:%v", serr) log.Error("setMuchStringByExpire fail",log.ErrorField("err",serr))
conn.Do("DISCARD") conn.Do("DISCARD")
return serr return serr
} else { } else {
@@ -262,7 +262,7 @@ func (m *RedisModule) setMuchStringByExpire(mapInfo map[interface{}]interface{},
} }
if err != nil { if err != nil {
log.Error("setMuchStringByExpire fail,reason:%v", err) log.Error("setMuchStringByExpire fail", log.ErrorField("err",err))
} }
return err return err
@@ -277,7 +277,7 @@ func (m *RedisModule) GetString(key interface{}) (string, error) {
ret, err := conn.Do("GET", key) ret, err := conn.Do("GET", key)
if err != nil { if err != nil {
log.Error("GetString fail,reason:%v", err) log.Error("GetString fail", log.ErrorField("err",err))
return "", err return "", err
} }
@@ -298,7 +298,7 @@ func (m *RedisModule) GetStringJSON(key string, st interface{}) error {
ret, err := conn.Do("GET", key) ret, err := conn.Do("GET", key)
if err != nil { if err != nil {
log.Error("GetStringJSON fail,reason:%v", err) log.Error("GetStringJSON fail", log.ErrorField("err",err))
return err return err
} }
@@ -315,7 +315,7 @@ func (m *RedisModule) GetStringJSON(key string, st interface{}) error {
} }
if err = json.Unmarshal(str, st); err != nil { if err = json.Unmarshal(str, st); err != nil {
log.Error("GetStringJSON fail json.Unmarshal is error:%s,%s,reason:%v", key, string(str), err) log.Errorf("GetStringJSON fail json.Unmarshal is error:%s,%s,reason:%v", key, string(str), err)
return err return err
} }
@@ -336,13 +336,13 @@ func (m *RedisModule) GetStringMap(keys []string) (retMap map[string]string, err
// 开始Send数据 // 开始Send数据
err = conn.Send("MULTI") err = conn.Send("MULTI")
if err != nil { if err != nil {
log.Error("GetMuchString fail %v", err) log.Errorf("GetMuchString fail %v", err)
return nil, err return nil, err
} }
for _, val := range keys { for _, val := range keys {
err = conn.Send("GET", val) err = conn.Send("GET", val)
if err != nil { if err != nil {
log.Error("GetMuchString fail,reason:%v", err) log.Errorf("GetMuchString fail,reason:%v", err)
conn.Do("DISCARD") conn.Do("DISCARD")
return nil, err return nil, err
} }
@@ -351,7 +351,7 @@ func (m *RedisModule) GetStringMap(keys []string) (retMap map[string]string, err
// 执行命令 // 执行命令
ret, err := conn.Do("EXEC") ret, err := conn.Do("EXEC")
if err != nil { if err != nil {
log.Error("GetMuchString fail %v", err) log.Errorf("GetMuchString fail %v", err)
return return
} }
@@ -383,7 +383,7 @@ func (m *RedisModule) ExistsKey(key interface{}) (bool, error) {
ret, err := conn.Do("EXISTS", key) ret, err := conn.Do("EXISTS", key)
if err != nil { if err != nil {
log.Error("ExistsKey fail, reason:%v", err) log.Errorf("ExistsKey fail, reason:%v", err)
return false, err return false, err
} }
retValue, ok := ret.(int64) retValue, ok := ret.(int64)
@@ -404,7 +404,7 @@ func (m *RedisModule) DelString(key interface{}) error {
ret, err := conn.Do("DEL", key) ret, err := conn.Do("DEL", key)
if err != nil { if err != nil {
log.Error("DelString fail, reason:%v", err) log.Errorf("DelString fail, reason:%v", err)
return err return err
} }
@@ -439,7 +439,7 @@ func (m *RedisModule) DelStringKeyList(keys []interface{}) (map[interface{}]bool
for _, val := range keys { for _, val := range keys {
err = conn.Send("DEL", val) err = conn.Send("DEL", val)
if err != nil { if err != nil {
log.Error("DelMuchString fail,reason:%v", err) log.Errorf("DelMuchString fail,reason:%v", err)
conn.Do("DISCARD") conn.Do("DISCARD")
return nil, err return nil, err
} }
@@ -448,7 +448,7 @@ func (m *RedisModule) DelStringKeyList(keys []interface{}) (map[interface{}]bool
ret, err := conn.Do("EXEC") ret, err := conn.Do("EXEC")
if err != nil { if err != nil {
log.Error("DelMuchString fail,reason:%v", err) log.Errorf("DelMuchString fail,reason:%v", err)
return nil, err return nil, err
} }
@@ -474,7 +474,7 @@ func (m *RedisModule) DelStringKeyList(keys []interface{}) (map[interface{}]bool
func (m *RedisModule) SetHash(redisKey, hashKey, value interface{}) error { func (m *RedisModule) SetHash(redisKey, hashKey, value interface{}) error {
if redisKey == "" || hashKey == "" { if redisKey == "" || hashKey == "" {
return errors.New("Key Is Empty") return errors.New("key is empty")
} }
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -484,16 +484,15 @@ func (m *RedisModule) SetHash(redisKey, hashKey, value interface{}) error {
_, retErr := conn.Do("HSET", redisKey, hashKey, value) _, retErr := conn.Do("HSET", redisKey, hashKey, value)
if retErr != nil { if retErr != nil {
log.Error("SetHash fail,reason:%v", retErr) log.Errorf("SetHash fail,reason:%v", retErr)
} }
return retErr return retErr
} }
// GetRedisAllHashJSON ...
func (m *RedisModule) GetAllHashJSON(redisKey string) (map[string]string, error) { func (m *RedisModule) GetAllHashJSON(redisKey string) (map[string]string, error) {
if redisKey == "" { if redisKey == "" {
return nil, errors.New("Key Is Empty") return nil, errors.New("key is empty")
} }
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -503,7 +502,7 @@ func (m *RedisModule) GetAllHashJSON(redisKey string) (map[string]string, error)
value, err := conn.Do("HGETALL", redisKey) value, err := conn.Do("HGETALL", redisKey)
if err != nil { if err != nil {
log.Error("GetAllHashJSON fail,reason:%v", err) log.Errorf("GetAllHashJSON fail,reason:%v", err)
return nil, err return nil, err
} }
@@ -513,7 +512,7 @@ func (m *RedisModule) GetAllHashJSON(redisKey string) (map[string]string, error)
func (m *RedisModule) GetHash(redisKey interface{}, fieldKey interface{}) (string, error) { func (m *RedisModule) GetHash(redisKey interface{}, fieldKey interface{}) (string, error) {
if redisKey == "" || fieldKey == "" { if redisKey == "" || fieldKey == "" {
log.Error("GetHashValueByKey key is empty!") log.Error("GetHashValueByKey key is empty!")
return "", errors.New("Key Is Empty") return "", errors.New("key is empty")
} }
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -523,11 +522,11 @@ func (m *RedisModule) GetHash(redisKey interface{}, fieldKey interface{}) (strin
value, err := conn.Do("HGET", redisKey, fieldKey) value, err := conn.Do("HGET", redisKey, fieldKey)
if err != nil { if err != nil {
log.Error("GetHashValueByKey fail,reason:%v", err) log.Errorf("GetHashValueByKey fail,reason:%v", err)
return "", err return "", err
} }
if value == nil { if value == nil {
return "", errors.New("Reids Get Hash nil") return "", errors.New("redis get hash nil")
} }
return redis.String(value, nil) return redis.String(value, nil)
@@ -536,7 +535,7 @@ func (m *RedisModule) GetHash(redisKey interface{}, fieldKey interface{}) (strin
func (m *RedisModule) GetMuchHash(args ...interface{}) ([]string, error) { func (m *RedisModule) GetMuchHash(args ...interface{}) ([]string, error) {
if len(args) < 2 { if len(args) < 2 {
log.Error("GetHashValueByHashKeyList key len less than two!") log.Error("GetHashValueByHashKeyList key len less than two!")
return nil, errors.New("Key Is Empty") return nil, errors.New("key is empty")
} }
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -546,15 +545,15 @@ func (m *RedisModule) GetMuchHash(args ...interface{}) ([]string, error) {
value, err := conn.Do("HMGET", args...) value, err := conn.Do("HMGET", args...)
if err != nil { if err != nil {
log.Error("GetHashValueByKey fail,reason:%v", err) log.Errorf("GetHashValueByKey fail,reason:%v", err)
return nil, err return nil, err
} }
if value == nil { if value == nil {
return nil, errors.New("Reids Get Hash nil") return nil, errors.New("redis get hash nil")
} }
valueList := value.([]interface{}) valueList := value.([]interface{})
retList := []string{} var retList []string
for _, valueItem := range valueList { for _, valueItem := range valueList {
valueByte, ok := valueItem.([]byte) valueByte, ok := valueItem.([]byte)
if !ok { if !ok {
@@ -572,7 +571,7 @@ func (m *RedisModule) ScanMatchKeys(cursorValue int, redisKey string, count int)
nextCursorValue := 0 nextCursorValue := 0
if redisKey == "" { if redisKey == "" {
log.Error("ScanMatchKeys key is empty!") log.Error("ScanMatchKeys key is empty!")
return nextCursorValue, nil, errors.New("Key Is Empty") return nextCursorValue, nil, errors.New("key is empty")
} }
conn, err := m.getConn() conn, err := m.getConn()
@@ -583,11 +582,11 @@ func (m *RedisModule) ScanMatchKeys(cursorValue int, redisKey string, count int)
value, err := conn.Do("SCAN", cursorValue, "match", redisKey, "count", count) value, err := conn.Do("SCAN", cursorValue, "match", redisKey, "count", count)
if err != nil { if err != nil {
log.Error("GetHashValueByKey fail,reason:%v", err) log.Errorf("GetHashValueByKey fail,reason:%v", err)
return nextCursorValue, nil, err return nextCursorValue, nil, err
} }
if value == nil { if value == nil {
return nextCursorValue, nil, errors.New("Reids Get Hash nil") return nextCursorValue, nil, errors.New("redis get hash nil")
} }
valueList := value.([]interface{}) valueList := value.([]interface{})
@@ -619,7 +618,7 @@ func (m *RedisModule) SetHashMapJSON(redisKey string, mapFieldValue map[interfac
if err == nil { if err == nil {
_, err = conn.Do("HSET", redisKey, symbol, temp) _, err = conn.Do("HSET", redisKey, symbol, temp)
if err != nil { if err != nil {
log.Error("SetMuchHashJSON fail,reason:%v", err) log.Errorf("SetMuchHashJSON fail,reason:%v", err)
conn.Send("DISCARD") conn.Send("DISCARD")
return err return err
} }
@@ -628,7 +627,7 @@ func (m *RedisModule) SetHashMapJSON(redisKey string, mapFieldValue map[interfac
// 执行命令 // 执行命令
_, err = conn.Do("EXEC") _, err = conn.Do("EXEC")
if err != nil { if err != nil {
log.Error("SetMuchHashJSON fail,reason:%v", err) log.Errorf("SetMuchHashJSON fail,reason:%v", err)
conn.Send("DISCARD") conn.Send("DISCARD")
} }
return err return err
@@ -643,7 +642,7 @@ func (m *RedisModule) DelHash(args ...interface{}) error {
_, retErr := conn.Do("HDEL", args...) _, retErr := conn.Do("HDEL", args...)
if retErr != nil { if retErr != nil {
log.Error("DelMuchHash fail,reason:%v", retErr) log.Errorf("DelMuchHash fail,reason:%v", retErr)
} }
return retErr return retErr
} }
@@ -669,7 +668,7 @@ func (m *RedisModule) RPushListJSON(key interface{}, value ...interface{}) error
// LPUSH和RPUSH // LPUSH和RPUSH
func (m *RedisModule) setListPush(setType string, args ...interface{}) error { func (m *RedisModule) setListPush(setType string, args ...interface{}) error {
if setType != "LPUSH" && setType != "RPUSH" { if setType != "LPUSH" && setType != "RPUSH" {
return errors.New("Redis List Push Type Error,Must Be LPUSH or RPUSH") return errors.New("redis list push type error,must be LPUSH or RPUSH")
} }
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -679,7 +678,7 @@ func (m *RedisModule) setListPush(setType string, args ...interface{}) error {
_, retErr := conn.Do(setType, args...) _, retErr := conn.Do(setType, args...)
if retErr != nil { if retErr != nil {
log.Error("setList fail,reason:%v", retErr) log.Errorf("setList fail,reason:%v", retErr)
} }
return retErr return retErr
} }
@@ -697,7 +696,6 @@ func (m *RedisModule) setListJSONPush(setType string, key interface{}, value ...
return m.setListPush(setType, args...) return m.setListPush(setType, args...)
} }
// Lrange ...
func (m *RedisModule) LRangeList(key string, start, end int) ([]string, error) { func (m *RedisModule) LRangeList(key string, start, end int) ([]string, error) {
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -707,14 +705,14 @@ func (m *RedisModule) LRangeList(key string, start, end int) ([]string, error) {
reply, err := conn.Do("lrange", key, start, end) reply, err := conn.Do("lrange", key, start, end)
if err != nil { if err != nil {
log.Error("SetListJSONRpush fail,reason:%v", err) log.Errorf("SetListJSONRpush fail,reason:%v", err)
return nil, err return nil, err
} }
return redis.Strings(reply, err) return redis.Strings(reply, err)
} }
// 获取List的长度 // GetListLen 获取List的长度
func (m *RedisModule) GetListLen(key string) (int, error) { func (m *RedisModule) GetListLen(key string) (int, error) {
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -724,13 +722,13 @@ func (m *RedisModule) GetListLen(key string) (int, error) {
reply, err := conn.Do("LLEN", key) reply, err := conn.Do("LLEN", key)
if err != nil { if err != nil {
log.Error("GetListLen fail,reason:%v", err) log.Errorf("GetListLen fail,reason:%v", err)
return -1, err return -1, err
} }
return redis.Int(reply, err) return redis.Int(reply, err)
} }
// 弹出List最后条记录 // RPOPListValue 弹出List最后条记录
func (m *RedisModule) RPOPListValue(key string) (string, error) { func (m *RedisModule) RPOPListValue(key string) (string, error) {
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -750,7 +748,7 @@ func (m *RedisModule) LTrimList(key string, start, end int) error {
_, err = conn.Do("LTRIM", key, start, end) _, err = conn.Do("LTRIM", key, start, end)
if err != nil { if err != nil {
log.Error("LtrimListValue fail,reason:%v", err) log.Errorf("LtrimListValue fail,reason:%v", err)
return err return err
} }
return nil return nil
@@ -782,7 +780,7 @@ func (m *RedisModule) LRange(key string, start, stop int) ([]byte, error) {
return makeListJson(reply.([]interface{}), false), nil return makeListJson(reply.([]interface{}), false), nil
} }
// 弹出list(消息队列)数据,数据放入out fromLeft表示是否从左侧弹出 block表示是否阻塞 timeout表示阻塞超时 // ListPopJson 弹出list(消息队列)数据,数据放入out fromLeft表示是否从左侧弹出 block表示是否阻塞 timeout表示阻塞超时
func (m *RedisModule) ListPopJson(key string, fromLeft, block bool, timeout int, out interface{}) error { func (m *RedisModule) ListPopJson(key string, fromLeft, block bool, timeout int, out interface{}) error {
b, err := m.ListPop(key, fromLeft, block, timeout) b, err := m.ListPop(key, fromLeft, block, timeout)
if err != nil { if err != nil {
@@ -795,7 +793,7 @@ func (m *RedisModule) ListPopJson(key string, fromLeft, block bool, timeout int,
return nil return nil
} }
// 弹出list(消息队列)数据 fromLeft表示是否从左侧弹出 block表示是否阻塞 timeout表示阻塞超时 // ListPop 弹出list(消息队列)数据 fromLeft表示是否从左侧弹出 block表示是否阻塞 timeout表示阻塞超时
func (m *RedisModule) ListPop(key string, fromLeft, block bool, timeout int) ([]byte, error) { func (m *RedisModule) ListPop(key string, fromLeft, block bool, timeout int) ([]byte, error) {
cmd := "" cmd := ""
if fromLeft { if fromLeft {
@@ -837,7 +835,7 @@ func (m *RedisModule) ListPop(key string, fromLeft, block bool, timeout int) ([]
return b, nil return b, nil
} }
// 有序集合插入Json // ZADDInsertJson 有序集合插入Json
func (m *RedisModule) ZADDInsertJson(key string, score float64, value interface{}) error { func (m *RedisModule) ZADDInsertJson(key string, score float64, value interface{}) error {
conn, err := m.getConn() conn, err := m.getConn()
@@ -851,13 +849,13 @@ func (m *RedisModule) ZADDInsertJson(key string, score float64, value interface{
} }
_, err = conn.Do("ZADD", key, score, JsonValue) _, err = conn.Do("ZADD", key, score, JsonValue)
if err != nil { if err != nil {
log.Error("ZADDInsertJson fail,reason:%v", err) log.Errorf("ZADDInsertJson fail,reason:%v", err)
return err return err
} }
return nil return nil
} }
// 有序集合插入 // ZADDInsert 有序集合插入
func (m *RedisModule) ZADDInsert(key string, score float64, Data interface{}) error { func (m *RedisModule) ZADDInsert(key string, score float64, Data interface{}) error {
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -867,7 +865,7 @@ func (m *RedisModule) ZADDInsert(key string, score float64, Data interface{}) er
_, err = conn.Do("ZADD", key, score, Data) _, err = conn.Do("ZADD", key, score, Data)
if err != nil { if err != nil {
log.Error("ZADDInsert fail,reason:%v", err) log.Errorf("ZADDInsert fail,reason:%v", err)
return err return err
} }
return nil return nil
@@ -897,7 +895,7 @@ func (m *RedisModule) ZRangeJSON(key string, start, stop int, ascend bool, withS
return nil return nil
} }
// 取有序set指定排名 ascend=true表示按升序遍历 否则按降序遍历 // ZRange 取有序set指定排名 ascend=true表示按升序遍历 否则按降序遍历
func (m *RedisModule) ZRange(key string, start, stop int, ascend bool, withScores bool) ([]byte, error) { func (m *RedisModule) ZRange(key string, start, stop int, ascend bool, withScores bool) ([]byte, error) {
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -921,7 +919,7 @@ func (m *RedisModule) ZRange(key string, start, stop int, ascend bool, withScore
return makeListJson(reply.([]interface{}), withScores), nil return makeListJson(reply.([]interface{}), withScores), nil
} }
// 获取有序集合长度 // Zcard 获取有序集合长度
func (m *RedisModule) Zcard(key string) (int, error) { func (m *RedisModule) Zcard(key string) (int, error) {
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -1005,7 +1003,7 @@ func (m *RedisModule) ZRangeByScore(key string, start, stop float64, ascend bool
return makeListJson(reply.([]interface{}), withScores), nil return makeListJson(reply.([]interface{}), withScores), nil
} }
// 获取指定member的排名 // ZScore 获取指定member的排名
func (m *RedisModule) ZScore(key string, member interface{}) (float64, error) { func (m *RedisModule) ZScore(key string, member interface{}) (float64, error) {
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -1021,7 +1019,7 @@ func (m *RedisModule) ZScore(key string, member interface{}) (float64, error) {
return redis.Float64(reply, err) return redis.Float64(reply, err)
} }
// 获取指定member的排名 // ZRank 获取指定member的排名
func (m *RedisModule) ZRank(key string, member interface{}, ascend bool) (int, error) { func (m *RedisModule) ZRank(key string, member interface{}, ascend bool) (int, error) {
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -1080,7 +1078,7 @@ func (m *RedisModule) ZREMMulti(key string, member ...interface{}) (int, error)
func (m *RedisModule) HincrbyHashInt(redisKey, hashKey string, value int) error { func (m *RedisModule) HincrbyHashInt(redisKey, hashKey string, value int) error {
if redisKey == "" || hashKey == "" { if redisKey == "" || hashKey == "" {
return errors.New("Key Is Empty") return errors.New("key is empty")
} }
conn, err := m.getConn() conn, err := m.getConn()
if err != nil { if err != nil {
@@ -1090,7 +1088,7 @@ func (m *RedisModule) HincrbyHashInt(redisKey, hashKey string, value int) error
_, retErr := conn.Do("HINCRBY", redisKey, hashKey, value) _, retErr := conn.Do("HINCRBY", redisKey, hashKey, value)
if retErr != nil { if retErr != nil {
log.Error("HincrbyHashInt fail,reason:%v", retErr) log.Errorf("HincrbyHashInt fail,reason:%v", retErr)
} }
return retErr return retErr
@@ -1105,7 +1103,7 @@ func (m *RedisModule) EXPlREInsert(key string, TTl int) error {
_, err = conn.Do("expire", key, TTl) _, err = conn.Do("expire", key, TTl)
if err != nil { if err != nil {
log.Error("expire fail,reason:%v", err) log.Errorf("expire fail,reason:%v", err)
return err return err
} }
return nil return nil
@@ -1131,7 +1129,7 @@ func (m *RedisModule) Keys(key string) ([]string, error) {
ret, err := conn.Do("KEYS", key) ret, err := conn.Do("KEYS", key)
if err != nil { if err != nil {
log.Error("KEYS fail, reason:%v", err) log.Errorf("KEYS fail, reason:%v", err)
return nil, err return nil, err
} }
retList, ok := ret.([]interface{}) retList, ok := ret.([]interface{})
@@ -1140,7 +1138,7 @@ func (m *RedisModule) Keys(key string) ([]string, error) {
return nil, err return nil, err
} }
strs := []string{} var strs []string
for _, val := range retList { for _, val := range retList {
strVal, ok := val.([]byte) strVal, ok := val.([]byte)
if !ok { if !ok {

View File

@@ -20,7 +20,6 @@ var DefaultReadTimeout time.Duration = time.Second * 10
var DefaultWriteTimeout time.Duration = time.Second * 10 var DefaultWriteTimeout time.Duration = time.Second * 10
var DefaultProcessTimeout time.Duration = time.Second * 10 var DefaultProcessTimeout time.Duration = time.Second * 10
//http redirect
type HttpRedirectData struct { type HttpRedirectData struct {
Url string Url string
CookieList []*http.Cookie CookieList []*http.Cookie
@@ -53,7 +52,7 @@ type IHttpRouter interface {
POST(url string, handle HttpHandle) bool POST(url string, handle HttpHandle) bool
Router(session *HttpSession) Router(session *HttpSession)
SetServeFile(method HTTP_METHOD, urlpath string, dirname string) error SetServeFile(method HTTP_METHOD, urlPath string, dirname string) error
SetFormFileKey(formFileKey string) SetFormFileKey(formFileKey string)
GetFormFileKey() string GetFormFileKey() string
AddHttpFiltrate(FiltrateFun HttpFiltrate) bool AddHttpFiltrate(FiltrateFun HttpFiltrate) bool
@@ -84,6 +83,7 @@ type HttpSession struct {
sessionDone chan *HttpSession sessionDone chan *HttpSession
} }
// Deprecated: replace it with the GinModule
type HttpService struct { type HttpService struct {
service.Service service.Service
@@ -93,7 +93,7 @@ type HttpService struct {
listenAddr string listenAddr string
corsHeader *CORSHeader corsHeader *CORSHeader
processTimeout time.Duration processTimeout time.Duration
manualStart bool manualStart bool
} }
type HttpFiltrate func(session *HttpSession) bool //true is pass type HttpFiltrate func(session *HttpSession) bool //true is pass
@@ -118,7 +118,7 @@ func NewHttpHttpRouter() IHttpRouter {
return httpRouter return httpRouter
} }
func (slf *HttpSession) GetRawQuery() string{ func (slf *HttpSession) GetRawQuery() string {
return slf.r.URL.RawQuery return slf.r.URL.RawQuery
} }
@@ -215,7 +215,7 @@ func (slf *HttpRouter) analysisRouterUrl(url string) (string, error) {
//替换所有空格 //替换所有空格
url = strings.ReplaceAll(url, " ", "") url = strings.ReplaceAll(url, " ", "")
if len(url) <= 1 || url[0] != '/' { if len(url) <= 1 || url[0] != '/' {
return "", fmt.Errorf("url %s format is error!", url) return "", fmt.Errorf("url %s format is error", url)
} }
//去掉尾部的/ //去掉尾部的/
@@ -300,12 +300,12 @@ func (httpService *HttpService) SetHttpRouter(httpRouter IHttpRouter, eventHandl
httpService.RegEventReceiverFunc(event.Sys_Event_Http_Event, eventHandler, httpService.HttpEventHandler) httpService.RegEventReceiverFunc(event.Sys_Event_Http_Event, eventHandler, httpService.HttpEventHandler)
} }
func (slf *HttpRouter) SetServeFile(method HTTP_METHOD, urlpath string, dirname string) error { func (slf *HttpRouter) SetServeFile(method HTTP_METHOD, urlPath string, dirname string) error {
_, err := os.Stat(dirname) _, err := os.Stat(dirname)
if err != nil { if err != nil {
return err return err
} }
matchURL, aErr := slf.analysisRouterUrl(urlpath) matchURL, aErr := slf.analysisRouterUrl(urlPath)
if aErr != nil { if aErr != nil {
return aErr return aErr
} }
@@ -350,15 +350,15 @@ func (slf *HttpSession) redirects() {
func (httpService *HttpService) OnInit() error { func (httpService *HttpService) OnInit() error {
iConfig := httpService.GetServiceCfg() iConfig := httpService.GetServiceCfg()
if iConfig == nil { if iConfig == nil {
return fmt.Errorf("%s service config is error!", httpService.GetName()) return fmt.Errorf("%s service config is error", httpService.GetName())
} }
httpCfg := iConfig.(map[string]interface{}) httpCfg := iConfig.(map[string]interface{})
addr, ok := httpCfg["ListenAddr"] addr, ok := httpCfg["ListenAddr"]
if ok == false { if ok == false {
return fmt.Errorf("%s service config is error!", httpService.GetName()) return fmt.Errorf("%s service config is error", httpService.GetName())
} }
var readTimeout time.Duration = DefaultReadTimeout var readTimeout = DefaultReadTimeout
var writeTimeout time.Duration = DefaultWriteTimeout var writeTimeout = DefaultWriteTimeout
if cfgRead, ok := httpCfg["ReadTimeout"]; ok == true { if cfgRead, ok := httpCfg["ReadTimeout"]; ok == true {
readTimeout = time.Duration(cfgRead.(float64)) * time.Millisecond readTimeout = time.Duration(cfgRead.(float64)) * time.Millisecond
@@ -370,8 +370,8 @@ func (httpService *HttpService) OnInit() error {
if manualStart, ok := httpCfg["ManualStart"]; ok == true { if manualStart, ok := httpCfg["ManualStart"]; ok == true {
httpService.manualStart = manualStart.(bool) httpService.manualStart = manualStart.(bool)
}else{ } else {
manualStart =false manualStart = false
} }
httpService.processTimeout = DefaultProcessTimeout httpService.processTimeout = DefaultProcessTimeout

View File

@@ -16,7 +16,7 @@ type CustomerSubscriber struct {
rpc.IRpcHandler rpc.IRpcHandler
topic string topic string
subscriber *Subscriber subscriber *Subscriber
fromNodeId int fromNodeId string
callBackRpcMethod string callBackRpcMethod string
serviceName string serviceName string
StartIndex uint64 StartIndex uint64
@@ -24,7 +24,7 @@ type CustomerSubscriber struct {
subscribeMethod SubscribeMethod subscribeMethod SubscribeMethod
customerId string customerId string
isStop int32 //退出标记 isStop int32 //退出标记
topicCache []TopicData // 从消息队列中取出来的消息的缓存 topicCache []TopicData // 从消息队列中取出来的消息的缓存
} }
@@ -37,7 +37,7 @@ const (
MethodLast SubscribeMethod = 1 //Last模式以该消费者上次记录的位置开始订阅 MethodLast SubscribeMethod = 1 //Last模式以该消费者上次记录的位置开始订阅
) )
func (cs *CustomerSubscriber) trySetSubscriberBaseInfo(rpcHandler rpc.IRpcHandler, ss *Subscriber, topic string, subscribeMethod SubscribeMethod, customerId string, fromNodeId int, callBackRpcMethod string, startIndex uint64, oneBatchQuantity int32) error { func (cs *CustomerSubscriber) trySetSubscriberBaseInfo(rpcHandler rpc.IRpcHandler, ss *Subscriber, topic string, subscribeMethod SubscribeMethod, customerId string, fromNodeId string, callBackRpcMethod string, startIndex uint64, oneBatchQuantity int32) error {
cs.subscriber = ss cs.subscriber = ss
cs.fromNodeId = fromNodeId cs.fromNodeId = fromNodeId
cs.callBackRpcMethod = callBackRpcMethod cs.callBackRpcMethod = callBackRpcMethod
@@ -62,13 +62,13 @@ func (cs *CustomerSubscriber) trySetSubscriberBaseInfo(rpcHandler rpc.IRpcHandle
cs.serviceName = strRpcMethod[0] cs.serviceName = strRpcMethod[0]
if cluster.HasService(fromNodeId, cs.serviceName) == false { if cluster.HasService(fromNodeId, cs.serviceName) == false {
err := fmt.Errorf("nodeId %d cannot found %s", fromNodeId, cs.serviceName) err := fmt.Errorf("nodeId %s cannot found %s", fromNodeId, cs.serviceName)
log.SError(err.Error()) log.SError(err.Error())
return err return err
} }
if cluster.GetCluster().IsNodeConnected(fromNodeId) == false { if cluster.GetCluster().IsNodeConnected(fromNodeId) == false {
err := fmt.Errorf("nodeId %d is disconnect", fromNodeId) err := fmt.Errorf("nodeId %s is disconnect", fromNodeId)
log.SError(err.Error()) log.SError(err.Error())
return err return err
} }
@@ -84,8 +84,8 @@ func (cs *CustomerSubscriber) trySetSubscriberBaseInfo(rpcHandler rpc.IRpcHandle
return nil return nil
} }
// 开始订阅 // Subscribe 开始订阅
func (cs *CustomerSubscriber) Subscribe(rpcHandler rpc.IRpcHandler, ss *Subscriber, topic string, subscribeMethod SubscribeMethod, customerId string, fromNodeId int, callBackRpcMethod string, startIndex uint64, oneBatchQuantity int32) error { func (cs *CustomerSubscriber) Subscribe(rpcHandler rpc.IRpcHandler, ss *Subscriber, topic string, subscribeMethod SubscribeMethod, customerId string, fromNodeId string, callBackRpcMethod string, startIndex uint64, oneBatchQuantity int32) error {
err := cs.trySetSubscriberBaseInfo(rpcHandler, ss, topic, subscribeMethod, customerId, fromNodeId, callBackRpcMethod, startIndex, oneBatchQuantity) err := cs.trySetSubscriberBaseInfo(rpcHandler, ss, topic, subscribeMethod, customerId, fromNodeId, callBackRpcMethod, startIndex, oneBatchQuantity)
if err != nil { if err != nil {
return err return err
@@ -96,7 +96,7 @@ func (cs *CustomerSubscriber) Subscribe(rpcHandler rpc.IRpcHandler, ss *Subscrib
return nil return nil
} }
// 取消订阅 // UnSubscribe 取消订阅
func (cs *CustomerSubscriber) UnSubscribe() { func (cs *CustomerSubscriber) UnSubscribe() {
atomic.StoreInt32(&cs.isStop, 1) atomic.StoreInt32(&cs.isStop, 1)
} }
@@ -104,11 +104,11 @@ func (cs *CustomerSubscriber) UnSubscribe() {
func (cs *CustomerSubscriber) LoadLastIndex() { func (cs *CustomerSubscriber) LoadLastIndex() {
for { for {
if atomic.LoadInt32(&cs.isStop) != 0 { if atomic.LoadInt32(&cs.isStop) != 0 {
log.Info("topic ", cs.topic, " out of subscription") log.SInfo("topic ", cs.topic, " out of subscription")
break break
} }
log.Info("customer ", cs.customerId, " start load last index ") log.SInfo("customer ", cs.customerId, " start load last index ")
lastIndex, ret := cs.subscriber.dataPersist.LoadCustomerIndex(cs.topic, cs.customerId) lastIndex, ret := cs.subscriber.dataPersist.LoadCustomerIndex(cs.topic, cs.customerId)
if ret == true { if ret == true {
if lastIndex > 0 { if lastIndex > 0 {
@@ -116,18 +116,18 @@ func (cs *CustomerSubscriber) LoadLastIndex() {
} else { } else {
//否则直接使用客户端发回来的 //否则直接使用客户端发回来的
} }
log.Info("customer ", cs.customerId, " load finish,start index is ", cs.StartIndex) log.SInfo("customer ", cs.customerId, " load finish,start index is ", cs.StartIndex)
break break
} }
log.Info("customer ", cs.customerId, " load last index is fail...") log.SInfo("customer ", cs.customerId, " load last index is fail...")
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
} }
} }
func (cs *CustomerSubscriber) SubscribeRun() { func (cs *CustomerSubscriber) SubscribeRun() {
defer cs.subscriber.queueWait.Done() defer cs.subscriber.queueWait.Done()
log.Info("topic ", cs.topic, " start subscription") log.SInfo("topic ", cs.topic, " start subscription")
//加载之前的位置 //加载之前的位置
if cs.subscribeMethod == MethodLast { if cs.subscribeMethod == MethodLast {
@@ -136,7 +136,7 @@ func (cs *CustomerSubscriber) SubscribeRun() {
for { for {
if atomic.LoadInt32(&cs.isStop) != 0 { if atomic.LoadInt32(&cs.isStop) != 0 {
log.Info("topic ", cs.topic, " out of subscription") log.SInfo("topic ", cs.topic, " out of subscription")
break break
} }
@@ -146,14 +146,14 @@ func (cs *CustomerSubscriber) SubscribeRun() {
//todo 检测退出 //todo 检测退出
if cs.subscribe() == false { if cs.subscribe() == false {
log.Info("topic ", cs.topic, " out of subscription") log.SInfo("topic ", cs.topic, " out of subscription")
break break
} }
} }
//删除订阅关系 //删除订阅关系
cs.subscriber.removeCustomer(cs.customerId, cs) cs.subscriber.removeCustomer(cs.customerId, cs)
log.Info("topic ", cs.topic, " unsubscription") log.SInfo("topic ", cs.topic, " unsubscription")
} }
func (cs *CustomerSubscriber) subscribe() bool { func (cs *CustomerSubscriber) subscribe() bool {
@@ -163,14 +163,14 @@ func (cs *CustomerSubscriber) subscribe() bool {
cs.publishToCustomer(topicData) cs.publishToCustomer(topicData)
return true return true
} }
//从持久化数据中来找 //从持久化数据中来找
topicData = cs.subscriber.dataPersist.FindTopicData(cs.topic, cs.StartIndex, int64(cs.oneBatchQuantity),cs.topicCache[:0]) topicData = cs.subscriber.dataPersist.FindTopicData(cs.topic, cs.StartIndex, int64(cs.oneBatchQuantity), cs.topicCache[:0])
return cs.publishToCustomer(topicData) return cs.publishToCustomer(topicData)
} }
func (cs *CustomerSubscriber) checkCustomerIsValid() bool { func (cs *CustomerSubscriber) checkCustomerIsValid() bool {
//1.检查nodeid是否在线不在线直接取消订阅 //1.检查nodeId是否在线不在线直接取消订阅
if cluster.GetCluster().IsNodeConnected(cs.fromNodeId) == false { if cluster.GetCluster().IsNodeConnected(cs.fromNodeId) == false {
return false return false
} }
@@ -213,7 +213,7 @@ func (cs *CustomerSubscriber) publishToCustomer(topicData []TopicData) bool {
} }
//推送数据 //推送数据
err := cs.CallNodeWithTimeout(4*time.Minute,cs.fromNodeId, cs.callBackRpcMethod, &dbQueuePublishReq, &dbQueuePushRes) err := cs.CallNodeWithTimeout(4*time.Minute, cs.fromNodeId, cs.callBackRpcMethod, &dbQueuePublishReq, &dbQueuePushRes)
if err != nil { if err != nil {
time.Sleep(time.Second * 1) time.Sleep(time.Second * 1)
continue continue

View File

@@ -19,7 +19,7 @@ func (mq *MemoryQueue) Init(cap int32) {
mq.topicQueue = make([]TopicData, cap+1) mq.topicQueue = make([]TopicData, cap+1)
} }
// 从队尾Push数据 // Push 从队尾Push数据
func (mq *MemoryQueue) Push(topicData *TopicData) bool { func (mq *MemoryQueue) Push(topicData *TopicData) bool {
mq.locker.Lock() mq.locker.Lock()
defer mq.locker.Unlock() defer mq.locker.Unlock()
@@ -51,7 +51,7 @@ func (mq *MemoryQueue) findData(startPos int32, startIndex uint64, limit int32)
} else { } else {
findEndPos = int32(len(mq.topicQueue)) findEndPos = int32(len(mq.topicQueue))
} }
if findStartPos >= findEndPos { if findStartPos >= findEndPos {
return nil, false return nil, false
} }
@@ -87,21 +87,21 @@ func (mq *MemoryQueue) FindData(startIndex uint64, limit int32, dataQueue []Topi
return nil, false return nil, false
} else if mq.head < mq.tail { } else if mq.head < mq.tail {
// 队列没有折叠 // 队列没有折叠
datas,ret := mq.findData(mq.head + 1, startIndex, limit) datas, ret := mq.findData(mq.head+1, startIndex, limit)
if ret { if ret {
dataQueue = append(dataQueue, datas...) dataQueue = append(dataQueue, datas...)
} }
return dataQueue, ret return dataQueue, ret
} else { } else {
// 折叠先找后面的部分 // 折叠先找后面的部分
datas,ret := mq.findData(mq.head+1, startIndex, limit) datas, ret := mq.findData(mq.head+1, startIndex, limit)
if ret { if ret {
dataQueue = append(dataQueue, datas...) dataQueue = append(dataQueue, datas...)
return dataQueue, ret return dataQueue, ret
} }
// 后面没找到,从前面开始找 // 后面没找到,从前面开始找
datas,ret = mq.findData(0, startIndex, limit) datas, ret = mq.findData(0, startIndex, limit)
dataQueue = append(dataQueue, datas...) dataQueue = append(dataQueue, datas...)
return dataQueue, ret return dataQueue, ret
} }

View File

@@ -63,7 +63,7 @@ func (ms *MessageQueueService) ReadCfg() error {
maxProcessTopicBacklogNum, ok := mapDBServiceCfg["MaxProcessTopicBacklogNum"] maxProcessTopicBacklogNum, ok := mapDBServiceCfg["MaxProcessTopicBacklogNum"]
if ok == false { if ok == false {
ms.maxProcessTopicBacklogNum = DefaultMaxTopicBacklogNum ms.maxProcessTopicBacklogNum = DefaultMaxTopicBacklogNum
log.Info("MaxProcessTopicBacklogNum config is set to the default value of ", maxProcessTopicBacklogNum) log.SInfo("MaxProcessTopicBacklogNum config is set to the default value of ", maxProcessTopicBacklogNum)
} else { } else {
ms.maxProcessTopicBacklogNum = int32(maxProcessTopicBacklogNum.(float64)) ms.maxProcessTopicBacklogNum = int32(maxProcessTopicBacklogNum.(float64))
} }
@@ -71,7 +71,7 @@ func (ms *MessageQueueService) ReadCfg() error {
memoryQueueLen, ok := mapDBServiceCfg["MemoryQueueLen"] memoryQueueLen, ok := mapDBServiceCfg["MemoryQueueLen"]
if ok == false { if ok == false {
ms.memoryQueueLen = DefaultMemoryQueueLen ms.memoryQueueLen = DefaultMemoryQueueLen
log.Info("MemoryQueueLen config is set to the default value of ", DefaultMemoryQueueLen) log.SInfo("MemoryQueueLen config is set to the default value of ", DefaultMemoryQueueLen)
} else { } else {
ms.memoryQueueLen = int32(memoryQueueLen.(float64)) ms.memoryQueueLen = int32(memoryQueueLen.(float64))
} }
@@ -122,5 +122,5 @@ func (ms *MessageQueueService) RPC_Publish(inParam *rpc.DBQueuePublishReq, outPa
func (ms *MessageQueueService) RPC_Subscribe(req *rpc.DBQueueSubscribeReq, res *rpc.DBQueueSubscribeRes) error { func (ms *MessageQueueService) RPC_Subscribe(req *rpc.DBQueueSubscribeReq, res *rpc.DBQueueSubscribeRes) error {
topicRoom := ms.GetTopicRoom(req.TopicName) topicRoom := ms.GetTopicRoom(req.TopicName)
return topicRoom.TopicSubscribe(ms.GetRpcHandler(), req.SubType, int32(req.Method), int(req.FromNodeId), req.RpcMethod, req.TopicName, req.CustomerId, req.StartIndex, req.OneBatchQuantity) return topicRoom.TopicSubscribe(ms.GetRpcHandler(), req.SubType, int32(req.Method), req.FromNodeId, req.RpcMethod, req.TopicName, req.CustomerId, req.StartIndex, req.OneBatchQuantity)
} }

View File

@@ -77,7 +77,7 @@ func (mp *MongoPersist) OnInit() error {
keys = append(keys, "Customer", "Topic") keys = append(keys, "Customer", "Topic")
IndexKey = append(IndexKey, keys) IndexKey = append(IndexKey, keys)
s := mp.mongo.TakeSession() s := mp.mongo.TakeSession()
if err := s.EnsureUniqueIndex(mp.dbName, CustomerCollectName, IndexKey, true, true,true); err != nil { if err := s.EnsureUniqueIndex(mp.dbName, CustomerCollectName, IndexKey, true, true, true); err != nil {
log.SError("EnsureUniqueIndex is fail ", err.Error()) log.SError("EnsureUniqueIndex is fail ", err.Error())
return err return err
} }
@@ -162,7 +162,7 @@ func (mp *MongoPersist) persistTopicData(collectionName string, topicData []Topi
_, err := s.Collection(mp.dbName, collectionName).InsertMany(ctx, documents) _, err := s.Collection(mp.dbName, collectionName).InsertMany(ctx, documents)
if err != nil { if err != nil {
log.SError("PersistTopicData InsertMany fail,collect name is ", collectionName," error:",err.Error()) log.SError("PersistTopicData InsertMany fail,collect name is ", collectionName, " error:", err.Error())
//失败最大重试数量 //失败最大重试数量
return retryCount >= mp.retryCount return retryCount >= mp.retryCount
@@ -171,16 +171,16 @@ func (mp *MongoPersist) persistTopicData(collectionName string, topicData []Topi
return true return true
} }
func (mp *MongoPersist) IsSameDay(timestamp1 int64,timestamp2 int64) bool{ func (mp *MongoPersist) IsSameDay(timestamp1 int64, timestamp2 int64) bool {
t1 := time.Unix(timestamp1, 0) t1 := time.Unix(timestamp1, 0)
t2 := time.Unix(timestamp2, 0) t2 := time.Unix(timestamp2, 0)
return t1.Year() == t2.Year() && t1.Month() == t2.Month()&&t1.Day() == t2.Day() return t1.Year() == t2.Year() && t1.Month() == t2.Month() && t1.Day() == t2.Day()
} }
// PersistTopicData 持久化数据 // PersistTopicData 持久化数据
func (mp *MongoPersist) PersistTopicData(topic string, topicData []TopicData, retryCount int) ([]TopicData, []TopicData, bool) { func (mp *MongoPersist) PersistTopicData(topic string, topicData []TopicData, retryCount int) ([]TopicData, []TopicData, bool) {
if len(topicData) == 0 { if len(topicData) == 0 {
return nil, nil,true return nil, nil, true
} }
preDate := topicData[0].Seq >> 32 preDate := topicData[0].Seq >> 32
@@ -188,7 +188,7 @@ func (mp *MongoPersist) PersistTopicData(topic string, topicData []TopicData, re
for findPos = 1; findPos < len(topicData); findPos++ { for findPos = 1; findPos < len(topicData); findPos++ {
newDate := topicData[findPos].Seq >> 32 newDate := topicData[findPos].Seq >> 32
//说明换天了 //说明换天了
if mp.IsSameDay(int64(preDate),int64(newDate)) == false { if mp.IsSameDay(int64(preDate), int64(newDate)) == false {
break break
} }
} }
@@ -201,14 +201,13 @@ func (mp *MongoPersist) PersistTopicData(topic string, topicData []TopicData, re
} }
//如果成功 //如果成功
return topicData[findPos:len(topicData)], topicData[0:findPos], true return topicData[findPos:], topicData[0:findPos], true
} }
// FindTopicData 查找数据 // FindTopicData 查找数据
func (mp *MongoPersist) findTopicData(topic string, startIndex uint64, limit int64,topicBuff []TopicData) ([]TopicData, bool) { func (mp *MongoPersist) findTopicData(topic string, startIndex uint64, limit int64, topicBuff []TopicData) ([]TopicData, bool) {
s := mp.mongo.TakeSession() s := mp.mongo.TakeSession()
condition := bson.D{{Key: "_id", Value: bson.D{{Key: "$gt", Value: startIndex}}}} condition := bson.D{{Key: "_id", Value: bson.D{{Key: "$gt", Value: startIndex}}}}
var findOption options.FindOptions var findOption options.FindOptions
@@ -238,11 +237,7 @@ func (mp *MongoPersist) findTopicData(topic string, startIndex uint64, limit int
defer cancelAll() defer cancelAll()
err = cursor.All(ctxAll, &res) err = cursor.All(ctxAll, &res)
if err != nil { if err != nil {
if err != nil { log.Error("find collect name error",log.String("topic",topic) ,log.ErrorField("err",err))
log.SError("find collect name ", topic, " is error:", err.Error())
return nil, false
}
return nil, false return nil, false
} }
@@ -251,7 +246,7 @@ func (mp *MongoPersist) findTopicData(topic string, startIndex uint64, limit int
rawData, errM := bson.Marshal(res[i]) rawData, errM := bson.Marshal(res[i])
if errM != nil { if errM != nil {
if errM != nil { if errM != nil {
log.SError("collect name ", topic, " Marshal is error:", err.Error()) log.Error("Marshal error",log.String("topic",topic) , log.ErrorField("err", err))
return nil, false return nil, false
} }
continue continue
@@ -262,26 +257,26 @@ func (mp *MongoPersist) findTopicData(topic string, startIndex uint64, limit int
return topicBuff, true return topicBuff, true
} }
func (mp *MongoPersist) IsYesterday(startIndex uint64) (bool,string){ func (mp *MongoPersist) IsYesterday(startIndex uint64) (bool, string) {
timeStamp := int64(startIndex>>32) timeStamp := int64(startIndex >> 32)
startTime := time.Unix(timeStamp, 0).AddDate(0,0,1) startTime := time.Unix(timeStamp, 0).AddDate(0, 0, 1)
nowTm := time.Now() nowTm := time.Now()
return startTime.Year() == nowTm.Year() && startTime.Month() == nowTm.Month()&&startTime.Day() == nowTm.Day(),nowTm.Format("20060102") return startTime.Year() == nowTm.Year() && startTime.Month() == nowTm.Month() && startTime.Day() == nowTm.Day(), nowTm.Format("20060102")
} }
func (mp *MongoPersist) getCollectCount(topic string,today string) (int64 ,error){ func (mp *MongoPersist) getCollectCount(topic string, today string) (int64, error) {
s := mp.mongo.TakeSession() s := mp.mongo.TakeSession()
ctx, cancel := s.GetDefaultContext() ctx, cancel := s.GetDefaultContext()
defer cancel() defer cancel()
collectName := fmt.Sprintf("%s_%s", topic, today) collectName := fmt.Sprintf("%s_%s", topic, today)
count, err := s.Collection(mp.dbName, collectName).EstimatedDocumentCount(ctx) count, err := s.Collection(mp.dbName, collectName).EstimatedDocumentCount(ctx)
return count,err return count, err
} }
// FindTopicData 查找数据 // FindTopicData 查找数据
func (mp *MongoPersist) FindTopicData(topic string, startIndex uint64, limit int64,topicBuff []TopicData) []TopicData { func (mp *MongoPersist) FindTopicData(topic string, startIndex uint64, limit int64, topicBuff []TopicData) []TopicData {
//某表找不到,一直往前找,找到当前置为止 //某表找不到,一直往前找,找到当前置为止
for days := 1; days <= MaxDays; days++ { for days := 1; days <= MaxDays; days++ {
//是否可以跳天 //是否可以跳天
@@ -290,12 +285,12 @@ func (mp *MongoPersist) FindTopicData(topic string, startIndex uint64, limit int
IsJumpDays := true IsJumpDays := true
//如果是昨天,先判断当天有没有表数据 //如果是昨天,先判断当天有没有表数据
bYesterday,strToday := mp.IsYesterday(startIndex) bYesterday, strToday := mp.IsYesterday(startIndex)
if bYesterday { if bYesterday {
count,err := mp.getCollectCount(topic,strToday) count, err := mp.getCollectCount(topic, strToday)
if err != nil { if err != nil {
//失败时,重新开始 //失败时,重新开始
log.SError("getCollectCount ",topic,"_",strToday," is fail:",err.Error()) log.SError("getCollectCount ", topic, "_", strToday, " is fail:", err.Error())
return nil return nil
} }
//当天没有记录,则不能跳表,有可能当天还有数据 //当天没有记录,则不能跳表,有可能当天还有数据
@@ -305,9 +300,9 @@ func (mp *MongoPersist) FindTopicData(topic string, startIndex uint64, limit int
} }
//从startIndex开始一直往后查 //从startIndex开始一直往后查
topicData, isSucc := mp.findTopicData(topic, startIndex, limit,topicBuff) topicData, ok := mp.findTopicData(topic, startIndex, limit, topicBuff)
//有数据或者数据库出错时返回,返回后,会进行下一轮的查询遍历 //有数据或者数据库出错时返回,返回后,会进行下一轮的查询遍历
if len(topicData) > 0 || isSucc == false { if len(topicData) > 0 || ok == false {
return topicData return topicData
} }
@@ -396,7 +391,7 @@ func (mp *MongoPersist) GetIndex(topicData *TopicData) uint64 {
if e.Key == "_id" { if e.Key == "_id" {
errC, seq := convertToNumber[uint64](e.Value) errC, seq := convertToNumber[uint64](e.Value)
if errC != nil { if errC != nil {
log.Error("value is error:%s,%+v, ", errC.Error(), e.Value) log.Error("value is error", log.ErrorField("err",errC), log.Any("val",e.Value))
} }
return seq return seq
@@ -411,14 +406,14 @@ func (mp *MongoPersist) PersistIndex(topic string, customerId string, index uint
condition := bson.D{{Key: "Customer", Value: customerId}, {Key: "Topic", Value: topic}} condition := bson.D{{Key: "Customer", Value: customerId}, {Key: "Topic", Value: topic}}
upsert := bson.M{"Customer": customerId, "Topic": topic, "Index": index} upsert := bson.M{"Customer": customerId, "Topic": topic, "Index": index}
updata := bson.M{"$set": upsert} update := bson.M{"$set": upsert}
var UpdateOptionsOpts []*options.UpdateOptions var UpdateOptionsOpts []*options.UpdateOptions
UpdateOptionsOpts = append(UpdateOptionsOpts, options.Update().SetUpsert(true)) UpdateOptionsOpts = append(UpdateOptionsOpts, options.Update().SetUpsert(true))
ctx, cancel := s.GetDefaultContext() ctx, cancel := s.GetDefaultContext()
defer cancel() defer cancel()
_, err := s.Collection(mp.dbName, CustomerCollectName).UpdateOne(ctx, condition, updata, UpdateOptionsOpts...) _, err := s.Collection(mp.dbName, CustomerCollectName).UpdateOne(ctx, condition, update, UpdateOptionsOpts...)
if err != nil { if err != nil {
log.SError("PersistIndex fail :", err.Error()) log.SError("PersistIndex fail :", err.Error())
} }

View File

@@ -7,7 +7,7 @@ import (
"sync" "sync"
) )
// 订阅器 // Subscriber 订阅器
type Subscriber struct { type Subscriber struct {
customerLocker sync.RWMutex customerLocker sync.RWMutex
mapCustomer map[string]*CustomerSubscriber mapCustomer map[string]*CustomerSubscriber
@@ -31,7 +31,7 @@ func (ss *Subscriber) PersistTopicData(topic string, topics []TopicData, retryCo
return ss.dataPersist.PersistTopicData(topic, topics, retryCount) return ss.dataPersist.PersistTopicData(topic, topics, retryCount)
} }
func (ss *Subscriber) TopicSubscribe(rpcHandler rpc.IRpcHandler, subScribeType rpc.SubscribeType, subscribeMethod SubscribeMethod, fromNodeId int, callBackRpcMethod string, topic string, customerId string, StartIndex uint64, oneBatchQuantity int32) error { func (ss *Subscriber) TopicSubscribe(rpcHandler rpc.IRpcHandler, subScribeType rpc.SubscribeType, subscribeMethod SubscribeMethod, fromNodeId string, callBackRpcMethod string, topic string, customerId string, StartIndex uint64, oneBatchQuantity int32) error {
//取消订阅时 //取消订阅时
if subScribeType == rpc.SubscribeType_Unsubscribe { if subScribeType == rpc.SubscribeType_Unsubscribe {
ss.UnSubscribe(customerId) ss.UnSubscribe(customerId)
@@ -56,9 +56,9 @@ func (ss *Subscriber) TopicSubscribe(rpcHandler rpc.IRpcHandler, subScribeType r
} }
if ok == true { if ok == true {
log.Info("repeat subscription for customer ", customerId) log.SInfo("repeat subscription for customer ", customerId)
} else { } else {
log.Info("subscription for customer ", customerId) log.SInfo("subscription for customer ", customerId)
} }
} }
@@ -72,7 +72,7 @@ func (ss *Subscriber) UnSubscribe(customerId string) {
customerSubscriber, ok := ss.mapCustomer[customerId] customerSubscriber, ok := ss.mapCustomer[customerId]
if ok == false { if ok == false {
log.SWarning("failed to unsubscribe customer " + customerId) log.SWarn("failed to unsubscribe customer ", customerId)
return return
} }

View File

@@ -43,7 +43,7 @@ type TopicRoom struct {
isStop int32 isStop int32
} }
// maxProcessTopicBacklogNum:主题最大积压数量 // Init maxProcessTopicBacklogNum:主题最大积压数量
func (tr *TopicRoom) Init(maxTopicBacklogNum int32, memoryQueueLen int32, topic string, queueWait *sync.WaitGroup, dataPersist QueueDataPersist) { func (tr *TopicRoom) Init(maxTopicBacklogNum int32, memoryQueueLen int32, topic string, queueWait *sync.WaitGroup, dataPersist QueueDataPersist) {
if maxTopicBacklogNum == 0 { if maxTopicBacklogNum == 0 {
maxTopicBacklogNum = DefaultMaxTopicBacklogNum maxTopicBacklogNum = DefaultMaxTopicBacklogNum
@@ -93,7 +93,7 @@ func (tr *TopicRoom) Stop() {
func (tr *TopicRoom) topicRoomRun() { func (tr *TopicRoom) topicRoomRun() {
defer tr.queueWait.Done() defer tr.queueWait.Done()
log.Info("topic room ", tr.topic, " is running..") log.SInfo("topic room ", tr.topic, " is running..")
for { for {
if atomic.LoadInt32(&tr.isStop) != 0 { if atomic.LoadInt32(&tr.isStop) != 0 {
break break
@@ -116,18 +116,18 @@ func (tr *TopicRoom) topicRoomRun() {
for retryCount := 0; retryCount < maxTryPersistNum; { for retryCount := 0; retryCount < maxTryPersistNum; {
//持久化处理 //持久化处理
stagingBuff, savedBuff, ret := tr.PersistTopicData(tr.topic, stagingBuff, retryCount+1) stagingBuff, savedBuff, ret := tr.PersistTopicData(tr.topic, stagingBuff, retryCount+1)
if ret == true { if ret == true {
// 1. 把成功存储的数据放入内存中 // 1. 把成功存储的数据放入内存中
if len(savedBuff) > 0 { if len(savedBuff) > 0 {
tr.PushTopicDataToQueue(tr.topic, savedBuff) tr.PushTopicDataToQueue(tr.topic, savedBuff)
} }
// 2. 如果存档成功,并且有后续批次,则继续存档 // 2. 如果存档成功,并且有后续批次,则继续存档
if ret == true && len(stagingBuff) > 0 { if len(stagingBuff) > 0 {
continue continue
} }
// 3. 成功了,跳出 // 3. 成功了,跳出
break break
} else { } else {
@@ -145,5 +145,5 @@ func (tr *TopicRoom) topicRoomRun() {
} }
tr.customerLocker.Unlock() tr.customerLocker.Unlock()
log.Info("topic room ", tr.topic, " is stop") log.SInfo("topic room ", tr.topic, " is stop")
} }

View File

@@ -14,37 +14,37 @@ import (
"time" "time"
) )
const batchRemoveNum = 128 //一切删除的最大数量 const batchRemoveNum = 128 //一切删除的最大数量
// RankDataDB 排行表数据 // RankDataDB 排行表数据
type RankDataDB struct { type RankDataDB struct {
Id uint64 `bson:"_id"` Id uint64 `bson:"_id"`
RefreshTime int64 `bson:"RefreshTime"` RefreshTime int64 `bson:"RefreshTime"`
SortData []int64 `bson:"SortData"` SortData []int64 `bson:"SortData"`
Data []byte `bson:"Data"` Data []byte `bson:"Data"`
ExData []int64 `bson:"ExData"` ExData []int64 `bson:"ExData"`
} }
// MongoPersist持久化Module // MongoPersist 持久化Module
type MongoPersist struct { type MongoPersist struct {
service.Module service.Module
mongo mongodbmodule.MongoModule mongo mongodbmodule.MongoModule
url string //Mongodb连接url url string //Mongodb连接url
dbName string //数据库名称 dbName string //数据库名称
SaveInterval time.Duration //落地数据库时间间隔 SaveInterval time.Duration //落地数据库时间间隔
sync.Mutex sync.Mutex
mapRemoveRankData map[uint64]map[uint64]struct{} //将要删除的排行数据 map[RankId]map[Key]struct{} mapRemoveRankData map[uint64]map[uint64]struct{} //将要删除的排行数据 map[RankId]map[Key]struct{}
mapUpsertRankData map[uint64]map[uint64]RankData //需要upsert的排行数据 map[RankId][key]RankData mapUpsertRankData map[uint64]map[uint64]RankData //需要upsert的排行数据 map[RankId][key]RankData
mapRankSkip map[uint64]IRankSkip //所有的排行榜对象map[RankId]IRankSkip mapRankSkip map[uint64]IRankSkip //所有的排行榜对象map[RankId]IRankSkip
maxRetrySaveCount int //存档重试次数 maxRetrySaveCount int //存档重试次数
retryTimeIntervalMs time.Duration //重试时间间隔 retryTimeIntervalMs time.Duration //重试时间间隔
lastSaveTime time.Time //最后一次存档时间 lastSaveTime time.Time //最后一次存档时间
stop int32 //是否停服 stop int32 //是否停服
waitGroup sync.WaitGroup //等待停服 waitGroup sync.WaitGroup //等待停服
} }
@@ -84,12 +84,12 @@ func (mp *MongoPersist) ReadCfg() error {
} }
//读取数据库配置 //读取数据库配置
saveMongoCfg,ok := mapDBServiceCfg["SaveMongo"] saveMongoCfg, ok := mapDBServiceCfg["SaveMongo"]
if ok == false { if ok == false {
return fmt.Errorf("RankService.SaveMongo config is error") return fmt.Errorf("RankService.SaveMongo config is error")
} }
mongodbCfg,ok := saveMongoCfg.(map[string]interface{}) mongodbCfg, ok := saveMongoCfg.(map[string]interface{})
if ok == false { if ok == false {
return fmt.Errorf("RankService.SaveMongo config is error") return fmt.Errorf("RankService.SaveMongo config is error")
} }
@@ -111,7 +111,7 @@ func (mp *MongoPersist) ReadCfg() error {
return fmt.Errorf("RankService.SaveMongo.SaveIntervalMs config is error") return fmt.Errorf("RankService.SaveMongo.SaveIntervalMs config is error")
} }
mp.SaveInterval = time.Duration(saveInterval.(float64))*time.Millisecond mp.SaveInterval = time.Duration(saveInterval.(float64)) * time.Millisecond
maxRetrySaveCount, ok := mongodbCfg["MaxRetrySaveCount"] maxRetrySaveCount, ok := mongodbCfg["MaxRetrySaveCount"]
if ok == false { if ok == false {
@@ -123,16 +123,16 @@ func (mp *MongoPersist) ReadCfg() error {
if ok == false { if ok == false {
return fmt.Errorf("RankService.SaveMongo.RetryTimeIntervalMs config is error") return fmt.Errorf("RankService.SaveMongo.RetryTimeIntervalMs config is error")
} }
mp.retryTimeIntervalMs = time.Duration(retryTimeIntervalMs.(float64))*time.Millisecond mp.retryTimeIntervalMs = time.Duration(retryTimeIntervalMs.(float64)) * time.Millisecond
return nil return nil
} }
//启服从数据库加载 // OnStart 启服从数据库加载
func (mp *MongoPersist) OnStart() { func (mp *MongoPersist) OnStart() {
} }
func (mp *MongoPersist) OnSetupRank(manual bool,rankSkip *RankSkip) error{ func (mp *MongoPersist) OnSetupRank(manual bool, rankSkip *RankSkip) error {
if mp.mapRankSkip == nil { if mp.mapRankSkip == nil {
mp.mapRankSkip = map[uint64]IRankSkip{} mp.mapRankSkip = map[uint64]IRankSkip{}
} }
@@ -142,17 +142,17 @@ func (mp *MongoPersist) OnSetupRank(manual bool,rankSkip *RankSkip) error{
return nil return nil
} }
log.Info("start load rank ",rankSkip.GetRankName()," from mongodb.") log.SInfo("start load rank ", rankSkip.GetRankName(), " from mongodb.")
err := mp.loadFromDB(rankSkip.GetRankID(),rankSkip.GetRankName()) err := mp.loadFromDB(rankSkip.GetRankID(), rankSkip.GetRankName())
if err != nil { if err != nil {
log.SError("load from db is fail :%s",err.Error()) log.SError("load from db is fail :%s", err.Error())
return err return err
} }
log.Info("finish load rank ",rankSkip.GetRankName()," from mongodb.") log.SInfo("finish load rank ", rankSkip.GetRankName(), " from mongodb.")
return nil return nil
} }
func (mp *MongoPersist) loadFromDB(rankId uint64,rankCollectName string) error{ func (mp *MongoPersist) loadFromDB(rankId uint64, rankCollectName string) error {
s := mp.mongo.TakeSession() s := mp.mongo.TakeSession()
ctx, cancel := s.GetDefaultContext() ctx, cancel := s.GetDefaultContext()
defer cancel() defer cancel()
@@ -164,14 +164,14 @@ func (mp *MongoPersist) loadFromDB(rankId uint64,rankCollectName string) error{
return err return err
} }
if cursor.Err()!=nil { if cursor.Err() != nil {
log.SError("find collect name ", rankCollectName, " is error:", cursor.Err().Error()) log.SError("find collect name ", rankCollectName, " is error:", cursor.Err().Error())
return err return err
} }
rankSkip := mp.mapRankSkip[rankId] rankSkip := mp.mapRankSkip[rankId]
if rankSkip == nil { if rankSkip == nil {
err = fmt.Errorf("rank ", rankCollectName, " is not setup:") err = fmt.Errorf("rank %s is not setup", rankCollectName)
log.SError(err.Error()) log.SError(err.Error())
return err return err
} }
@@ -189,69 +189,68 @@ func (mp *MongoPersist) loadFromDB(rankId uint64,rankCollectName string) error{
rankData.Data = rankDataDB.Data rankData.Data = rankDataDB.Data
rankData.Key = rankDataDB.Id rankData.Key = rankDataDB.Id
rankData.SortData = rankDataDB.SortData rankData.SortData = rankDataDB.SortData
for _,eData := range rankDataDB.ExData{ for _, eData := range rankDataDB.ExData {
rankData.ExData = append(rankData.ExData,&rpc.ExtendIncData{InitValue:eData}) rankData.ExData = append(rankData.ExData, &rpc.ExtendIncData{InitValue: eData})
} }
//更新到排行榜 //更新到排行榜
rankSkip.UpsetRank(&rankData,rankDataDB.RefreshTime,true) rankSkip.UpsetRank(&rankData, rankDataDB.RefreshTime, true)
} }
return nil return nil
} }
func (mp *MongoPersist) lazyInitRemoveMap(rankId uint64){ func (mp *MongoPersist) lazyInitRemoveMap(rankId uint64) {
if mp.mapRemoveRankData[rankId] == nil { if mp.mapRemoveRankData[rankId] == nil {
mp.mapRemoveRankData[rankId] = make(map[uint64]struct{},256) mp.mapRemoveRankData[rankId] = make(map[uint64]struct{}, 256)
} }
} }
func (mp *MongoPersist) lazyInitUpsertMap(rankId uint64){ func (mp *MongoPersist) lazyInitUpsertMap(rankId uint64) {
if mp.mapUpsertRankData[rankId] == nil { if mp.mapUpsertRankData[rankId] == nil {
mp.mapUpsertRankData[rankId] = make(map[uint64]RankData,256) mp.mapUpsertRankData[rankId] = make(map[uint64]RankData, 256)
} }
} }
func (mp *MongoPersist) OnEnterRank(rankSkip IRankSkip, enterData *RankData){ func (mp *MongoPersist) OnEnterRank(rankSkip IRankSkip, enterData *RankData) {
mp.Lock() mp.Lock()
defer mp.Unlock() defer mp.Unlock()
delete(mp.mapRemoveRankData,enterData.Key) delete(mp.mapRemoveRankData, enterData.Key)
mp.lazyInitUpsertMap(rankSkip.GetRankID()) mp.lazyInitUpsertMap(rankSkip.GetRankID())
mp.mapUpsertRankData[rankSkip.GetRankID()][enterData.Key] = *enterData mp.mapUpsertRankData[rankSkip.GetRankID()][enterData.Key] = *enterData
} }
func (mp *MongoPersist) OnLeaveRank(rankSkip IRankSkip, leaveData *RankData) {
func (mp *MongoPersist) OnLeaveRank(rankSkip IRankSkip, leaveData *RankData){
mp.Lock() mp.Lock()
defer mp.Unlock() defer mp.Unlock()
//先删掉更新中的数据 //先删掉更新中的数据
delete(mp.mapUpsertRankData,leaveData.Key) delete(mp.mapUpsertRankData, leaveData.Key)
mp.lazyInitRemoveMap(rankSkip.GetRankID()) mp.lazyInitRemoveMap(rankSkip.GetRankID())
mp.mapRemoveRankData[rankSkip.GetRankID()][leaveData.Key] = struct{}{} mp.mapRemoveRankData[rankSkip.GetRankID()][leaveData.Key] = struct{}{}
} }
func (mp *MongoPersist) OnChangeRankData(rankSkip IRankSkip, changeData *RankData){ func (mp *MongoPersist) OnChangeRankData(rankSkip IRankSkip, changeData *RankData) {
mp.Lock() mp.Lock()
defer mp.Unlock() defer mp.Unlock()
//先删掉要删除的数据 //先删掉要删除的数据
delete(mp.mapRemoveRankData,changeData.Key) delete(mp.mapRemoveRankData, changeData.Key)
//更新数据 //更新数据
mp.lazyInitUpsertMap(rankSkip.GetRankID()) mp.lazyInitUpsertMap(rankSkip.GetRankID())
mp.mapUpsertRankData[rankSkip.GetRankID()][changeData.Key] = *changeData mp.mapUpsertRankData[rankSkip.GetRankID()][changeData.Key] = *changeData
} }
//停存持久化到DB // OnStop 停存持久化到DB
func (mp *MongoPersist) OnStop(mapRankSkip map[uint64]*RankSkip){ func (mp *MongoPersist) OnStop(mapRankSkip map[uint64]*RankSkip) {
atomic.StoreInt32(&mp.stop,1) atomic.StoreInt32(&mp.stop, 1)
mp.waitGroup.Wait() mp.waitGroup.Wait()
} }
func (mp *MongoPersist) JugeTimeoutSave() bool{ func (mp *MongoPersist) JudgeTimeoutSave() bool {
timeout := time.Now() timeout := time.Now()
isTimeOut := timeout.Sub(mp.lastSaveTime) >= mp.SaveInterval isTimeOut := timeout.Sub(mp.lastSaveTime) >= mp.SaveInterval
if isTimeOut == true { if isTimeOut == true {
@@ -261,18 +260,18 @@ func (mp *MongoPersist) JugeTimeoutSave() bool{
return isTimeOut return isTimeOut
} }
func (mp *MongoPersist) persistCoroutine(){ func (mp *MongoPersist) persistCoroutine() {
defer mp.waitGroup.Done() defer mp.waitGroup.Done()
for atomic.LoadInt32(&mp.stop)==0 || mp.hasPersistData(){ for atomic.LoadInt32(&mp.stop) == 0 {
//间隔时间sleep //间隔时间sleep
time.Sleep(time.Second*1) time.Sleep(time.Second * 1)
//没有持久化数据continue //没有持久化数据continue
if mp.hasPersistData() == false { if mp.hasPersistData() == false {
continue continue
} }
if mp.JugeTimeoutSave() == false{ if mp.JudgeTimeoutSave() == false {
continue continue
} }
@@ -284,20 +283,20 @@ func (mp *MongoPersist) persistCoroutine(){
mp.saveToDB() mp.saveToDB()
} }
func (mp *MongoPersist) hasPersistData() bool{ func (mp *MongoPersist) hasPersistData() bool {
mp.Lock() mp.Lock()
defer mp.Unlock() defer mp.Unlock()
return len(mp.mapUpsertRankData)>0 || len(mp.mapRemoveRankData) >0 return len(mp.mapUpsertRankData) > 0 || len(mp.mapRemoveRankData) > 0
} }
func (mp *MongoPersist) saveToDB(){ func (mp *MongoPersist) saveToDB() {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096) buf := make([]byte, 4096)
l := runtime.Stack(buf, false) l := runtime.Stack(buf, false)
errString := fmt.Sprint(r) errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString)) log.StackError(string(buf[:l]), log.String("error", errString))
} }
}() }()
@@ -314,13 +313,13 @@ func (mp *MongoPersist) saveToDB(){
mp.upsertRankDataToDB(mapUpsertRankData) mp.upsertRankDataToDB(mapUpsertRankData)
} }
for len(mapRemoveRankData) >0 { for len(mapRemoveRankData) > 0 {
mp.removeRankDataToDB(mapRemoveRankData) mp.removeRankDataToDB(mapRemoveRankData)
} }
} }
func (mp *MongoPersist) removeToDB(collectName string,keys []uint64) error{ func (mp *MongoPersist) removeToDB(collectName string, keys []uint64) error {
s := mp.mongo.TakeSession() s := mp.mongo.TakeSession()
ctx, cancel := s.GetDefaultContext() ctx, cancel := s.GetDefaultContext()
defer cancel() defer cancel()
@@ -336,16 +335,16 @@ func (mp *MongoPersist) removeToDB(collectName string,keys []uint64) error{
return nil return nil
} }
func (mp *MongoPersist) removeRankData(rankId uint64,keys []uint64) bool { func (mp *MongoPersist) removeRankData(rankId uint64, keys []uint64) bool {
rank := mp.mapRankSkip[rankId] rank := mp.mapRankSkip[rankId]
if rank== nil { if rank == nil {
log.SError("cannot find rankId ",rankId,"config") log.SError("cannot find rankId ", rankId, "config")
return false return false
} }
//不成功则重试maxRetrySaveCount次 //不成功则重试maxRetrySaveCount次
for i:=0;i<mp.maxRetrySaveCount;i++{ for i := 0; i < mp.maxRetrySaveCount; i++ {
if mp.removeToDB(rank.GetRankName(),keys)!= nil { if mp.removeToDB(rank.GetRankName(), keys) != nil {
time.Sleep(mp.retryTimeIntervalMs) time.Sleep(mp.retryTimeIntervalMs)
continue continue
} }
@@ -355,9 +354,9 @@ func (mp *MongoPersist) removeRankData(rankId uint64,keys []uint64) bool {
return true return true
} }
func (mp *MongoPersist) upsertToDB(collectName string,rankData *RankData) error{ func (mp *MongoPersist) upsertToDB(collectName string, rankData *RankData) error {
condition := bson.D{{"_id", rankData.Key}} condition := bson.D{{"_id", rankData.Key}}
upsert := bson.M{"_id":rankData.Key,"RefreshTime": rankData.RefreshTimestamp, "SortData": rankData.SortData, "Data": rankData.Data,"ExData":rankData.ExData} upsert := bson.M{"_id": rankData.Key, "RefreshTime": rankData.RefreshTimestamp, "SortData": rankData.SortData, "Data": rankData.Data, "ExData": rankData.ExData}
update := bson.M{"$set": upsert} update := bson.M{"$set": upsert}
s := mp.mongo.TakeSession() s := mp.mongo.TakeSession()
@@ -365,7 +364,7 @@ func (mp *MongoPersist) upsertToDB(collectName string,rankData *RankData) error{
defer cancel() defer cancel()
updateOpts := options.Update().SetUpsert(true) updateOpts := options.Update().SetUpsert(true)
_, err := s.Collection(mp.dbName, collectName).UpdateOne(ctx, condition,update,updateOpts) _, err := s.Collection(mp.dbName, collectName).UpdateOne(ctx, condition, update, updateOpts)
if err != nil { if err != nil {
log.SError("MongoPersist upsertDB fail,collect name is ", collectName) log.SError("MongoPersist upsertDB fail,collect name is ", collectName)
return err return err
@@ -374,19 +373,19 @@ func (mp *MongoPersist) upsertToDB(collectName string,rankData *RankData) error{
return nil return nil
} }
func (mp *MongoPersist) upsertRankDataToDB(mapUpsertRankData map[uint64]map[uint64]RankData) error{ func (mp *MongoPersist) upsertRankDataToDB(mapUpsertRankData map[uint64]map[uint64]RankData) error {
for rankId,mapRankData := range mapUpsertRankData{ for rankId, mapRankData := range mapUpsertRankData {
rank,ok := mp.mapRankSkip[rankId] rank, ok := mp.mapRankSkip[rankId]
if ok == false { if ok == false {
log.SError("cannot find rankId ",rankId,",config is error") log.SError("cannot find rankId ", rankId, ",config is error")
delete(mapUpsertRankData,rankId) delete(mapUpsertRankData, rankId)
continue continue
} }
for key,rankData := range mapRankData{ for key, rankData := range mapRankData {
//最大重试mp.maxRetrySaveCount次 //最大重试mp.maxRetrySaveCount次
for i:=0;i<mp.maxRetrySaveCount;i++{ for i := 0; i < mp.maxRetrySaveCount; i++ {
err := mp.upsertToDB(rank.GetRankName(),&rankData) err := mp.upsertToDB(rank.GetRankName(), &rankData)
if err != nil { if err != nil {
time.Sleep(mp.retryTimeIntervalMs) time.Sleep(mp.retryTimeIntervalMs)
continue continue
@@ -395,11 +394,11 @@ func (mp *MongoPersist) upsertRankDataToDB(mapUpsertRankData map[uint64]map[uint
} }
//存完删掉指定key //存完删掉指定key
delete(mapRankData,key) delete(mapRankData, key)
} }
if len(mapRankData) == 0 { if len(mapRankData) == 0 {
delete(mapUpsertRankData,rankId) delete(mapUpsertRankData, rankId)
} }
} }
@@ -407,23 +406,22 @@ func (mp *MongoPersist) upsertRankDataToDB(mapUpsertRankData map[uint64]map[uint
} }
func (mp *MongoPersist) removeRankDataToDB(mapRemoveRankData map[uint64]map[uint64]struct{}) { func (mp *MongoPersist) removeRankDataToDB(mapRemoveRankData map[uint64]map[uint64]struct{}) {
for rankId ,mapRemoveKey := range mapRemoveRankData{ for rankId, mapRemoveKey := range mapRemoveRankData {
//每100个一删 //每100个一删
keyList := make([]uint64,0,batchRemoveNum) keyList := make([]uint64, 0, batchRemoveNum)
for key := range mapRemoveKey { for key := range mapRemoveKey {
delete(mapRemoveKey,key) delete(mapRemoveKey, key)
keyList = append(keyList,key) keyList = append(keyList, key)
if len(keyList) >= batchRemoveNum { if len(keyList) >= batchRemoveNum {
break break
} }
} }
mp.removeRankData(rankId,keyList) mp.removeRankData(rankId, keyList)
//如果删完删掉rankid下所有 if len(mapRemoveKey) == 0 {
if len(mapRemoveKey) == 0 { delete(mapRemoveRankData, rankId)
delete(mapRemoveRankData,rankId) }
}
} }
} }

View File

@@ -1,8 +1,8 @@
package rankservice package rankservice
import ( import (
"github.com/duanhf2012/origin/v2/service"
"github.com/duanhf2012/origin/v2/rpc" "github.com/duanhf2012/origin/v2/rpc"
"github.com/duanhf2012/origin/v2/service"
) )
type RankDataChangeType int8 type RankDataChangeType int8
@@ -11,19 +11,18 @@ type IRankSkip interface {
GetRankID() uint64 GetRankID() uint64
GetRankName() string GetRankName() string
GetRankLen() uint64 GetRankLen() uint64
UpsetRank(upsetData *rpc.RankData,refreshTimestamp int64,fromLoad bool) RankDataChangeType UpsetRank(upsetData *rpc.RankData, refreshTimestamp int64, fromLoad bool) RankDataChangeType
} }
type IRankModule interface { type IRankModule interface {
service.IModule service.IModule
OnSetupRank(manual bool, rankSkip *RankSkip) error //当完成安装排行榜对象时
OnSetupRank(manual bool,rankSkip *RankSkip) error //当完成安装排行榜对象时 OnStart() //服务开启时回调
OnStart() //服务开启时回调
OnEnterRank(rankSkip IRankSkip, enterData *RankData) //进入排行 OnEnterRank(rankSkip IRankSkip, enterData *RankData) //进入排行
OnLeaveRank(rankSkip IRankSkip, leaveData *RankData) //离开排行 OnLeaveRank(rankSkip IRankSkip, leaveData *RankData) //离开排行
OnChangeRankData(rankSkip IRankSkip, changeData *RankData) //当排行数据变化时 OnChangeRankData(rankSkip IRankSkip, changeData *RankData) //当排行数据变化时
OnStop(mapRankSkip map[uint64]*RankSkip) //服务结束时回调 OnStop(mapRankSkip map[uint64]*RankSkip) //服务结束时回调
} }
type DefaultRankModule struct { type DefaultRankModule struct {

View File

@@ -45,7 +45,7 @@ func (rs *RankService) OnRelease() {
rs.rankModule.OnStop(rs.mapRankSkip) rs.rankModule.OnStop(rs.mapRankSkip)
} }
// 安装排行模块 // SetupRankModule 安装排行模块
func (rs *RankService) SetupRankModule(rankModule IRankModule) { func (rs *RankService) SetupRankModule(rankModule IRankModule) {
rs.rankModule = rankModule rs.rankModule = rankModule
} }

View File

@@ -342,7 +342,7 @@ func (rs *RankSkip) GetRankNodeData(findKey uint64) (*RankData, uint64) {
return rankNode, index + 1 return rankNode, index + 1
} }
// GetRankNodeDataByPos 获取,返回排名节点与名次 // GetRankNodeDataByRank 获取,返回排名节点与名次
func (rs *RankSkip) GetRankNodeDataByRank(rank uint64) (*RankData, uint64) { func (rs *RankSkip) GetRankNodeDataByRank(rank uint64) (*RankData, uint64) {
rs.pickExpireKey() rs.pickExpireKey()
rankNode := rs.skipList.ByPosition(rank - 1) rankNode := rs.skipList.ByPosition(rank - 1)
@@ -382,7 +382,7 @@ func (rs *RankSkip) GetRankKeyPrevToLimit(findKey, count uint64, result *rpc.Ran
return nil return nil
} }
// GetRankKeyPrevToLimit 获取key前count名的数据 // GetRankKeyNextToLimit 获取key前count名的数据
func (rs *RankSkip) GetRankKeyNextToLimit(findKey, count uint64, result *rpc.RankDataList) error { func (rs *RankSkip) GetRankKeyNextToLimit(findKey, count uint64, result *rpc.RankDataList) error {
if rs.GetRankLen() <= 0 { if rs.GetRankLen() <= 0 {
return fmt.Errorf("rank[%d] no data", rs.rankId) return fmt.Errorf("rank[%d] no data", rs.rankId)
@@ -411,7 +411,7 @@ func (rs *RankSkip) GetRankKeyNextToLimit(findKey, count uint64, result *rpc.Ran
return nil return nil
} }
// GetRankList 获取排行榜数据,startPos开始的count个数据 // GetRankDataFromToLimit 获取排行榜数据,startPos开始的count个数据
func (rs *RankSkip) GetRankDataFromToLimit(startPos, count uint64, result *rpc.RankDataList) error { func (rs *RankSkip) GetRankDataFromToLimit(startPos, count uint64, result *rpc.RankDataList) error {
if rs.GetRankLen() <= 0 { if rs.GetRankLen() <= 0 {
//初始排行榜可能没有数据 //初始排行榜可能没有数据

View File

@@ -8,95 +8,94 @@ import (
"github.com/duanhf2012/origin/v2/network/processor" "github.com/duanhf2012/origin/v2/network/processor"
"github.com/duanhf2012/origin/v2/service" "github.com/duanhf2012/origin/v2/service"
"github.com/duanhf2012/origin/v2/util/bytespool" "github.com/duanhf2012/origin/v2/util/bytespool"
"runtime"
"sync"
"github.com/google/uuid" "github.com/google/uuid"
"time"
"strings" "strings"
"sync"
"time"
) )
// Deprecated: replace it with the TcpModule
type TcpService struct { type TcpService struct {
tcpServer network.TCPServer tcpServer network.TCPServer
service.Service service.Service
mapClientLocker sync.RWMutex mapClientLocker sync.RWMutex
mapClient map[string] *Client mapClient map[string]*Client
process processor.IProcessor process processor.IProcessor
} }
type TcpPackType int8 type TcpPackType int8
const(
TPT_Connected TcpPackType = 0 const (
TPT_Connected TcpPackType = 0
TPT_DisConnected TcpPackType = 1 TPT_DisConnected TcpPackType = 1
TPT_Pack TcpPackType = 2 TPT_Pack TcpPackType = 2
TPT_UnknownPack TcpPackType = 3 TPT_UnknownPack TcpPackType = 3
) )
type TcpPack struct { type TcpPack struct {
Type TcpPackType //0表示连接 1表示断开 2表示数据 Type TcpPackType //0表示连接 1表示断开 2表示数据
ClientId string ClientId string
Data interface{} Data interface{}
} }
type Client struct { type Client struct {
id string id string
tcpConn *network.TCPConn tcpConn *network.NetConn
tcpService *TcpService tcpService *TcpService
} }
func (tcpService *TcpService) OnInit() error{ func (tcpService *TcpService) OnInit() error {
iConfig := tcpService.GetServiceCfg() iConfig := tcpService.GetServiceCfg()
if iConfig == nil { if iConfig == nil {
return fmt.Errorf("%s service config is error!", tcpService.GetName()) return fmt.Errorf("%s service config is error", tcpService.GetName())
} }
tcpCfg := iConfig.(map[string]interface{}) tcpCfg := iConfig.(map[string]interface{})
addr,ok := tcpCfg["ListenAddr"] addr, ok := tcpCfg["ListenAddr"]
if ok == false { if ok == false {
return fmt.Errorf("%s service config is error!", tcpService.GetName()) return fmt.Errorf("%s service config is error", tcpService.GetName())
} }
tcpService.tcpServer.Addr = addr.(string) tcpService.tcpServer.Addr = addr.(string)
MaxConnNum,ok := tcpCfg["MaxConnNum"] MaxConnNum, ok := tcpCfg["MaxConnNum"]
if ok == true { if ok == true {
tcpService.tcpServer.MaxConnNum = int(MaxConnNum.(float64)) tcpService.tcpServer.MaxConnNum = int(MaxConnNum.(float64))
} }
PendingWriteNum,ok := tcpCfg["PendingWriteNum"] PendingWriteNum, ok := tcpCfg["PendingWriteNum"]
if ok == true { if ok == true {
tcpService.tcpServer.PendingWriteNum = int(PendingWriteNum.(float64)) tcpService.tcpServer.PendingWriteNum = int(PendingWriteNum.(float64))
} }
LittleEndian,ok := tcpCfg["LittleEndian"] LittleEndian, ok := tcpCfg["LittleEndian"]
if ok == true { if ok == true {
tcpService.tcpServer.LittleEndian = LittleEndian.(bool) tcpService.tcpServer.LittleEndian = LittleEndian.(bool)
} }
LenMsgLen,ok := tcpCfg["LenMsgLen"] LenMsgLen, ok := tcpCfg["LenMsgLen"]
if ok == true { if ok == true {
tcpService.tcpServer.LenMsgLen = int(LenMsgLen.(float64)) tcpService.tcpServer.LenMsgLen = int(LenMsgLen.(float64))
} }
MinMsgLen,ok := tcpCfg["MinMsgLen"] MinMsgLen, ok := tcpCfg["MinMsgLen"]
if ok == true { if ok == true {
tcpService.tcpServer.MinMsgLen = uint32(MinMsgLen.(float64)) tcpService.tcpServer.MinMsgLen = uint32(MinMsgLen.(float64))
} }
MaxMsgLen,ok := tcpCfg["MaxMsgLen"] MaxMsgLen, ok := tcpCfg["MaxMsgLen"]
if ok == true { if ok == true {
tcpService.tcpServer.MaxMsgLen = uint32(MaxMsgLen.(float64)) tcpService.tcpServer.MaxMsgLen = uint32(MaxMsgLen.(float64))
} }
readDeadline,ok := tcpCfg["ReadDeadline"] readDeadline, ok := tcpCfg["ReadDeadline"]
if ok == true { if ok == true {
tcpService.tcpServer.ReadDeadline = time.Second*time.Duration(readDeadline.(float64)) tcpService.tcpServer.ReadDeadline = time.Second * time.Duration(readDeadline.(float64))
} }
writeDeadline,ok := tcpCfg["WriteDeadline"] writeDeadline, ok := tcpCfg["WriteDeadline"]
if ok == true { if ok == true {
tcpService.tcpServer.WriteDeadline = time.Second*time.Duration(writeDeadline.(float64)) tcpService.tcpServer.WriteDeadline = time.Second * time.Duration(writeDeadline.(float64))
} }
tcpService.mapClient = make( map[string] *Client, tcpService.tcpServer.MaxConnNum) tcpService.mapClient = make(map[string]*Client, tcpService.tcpServer.MaxConnNum)
tcpService.tcpServer.NewAgent = tcpService.NewClient tcpService.tcpServer.NewAgent = tcpService.NewClient
tcpService.tcpServer.Start() return tcpService.tcpServer.Start()
return nil
} }
func (tcpService *TcpService) TcpEventHandler(ev event.IEvent) { func (tcpService *TcpService) TcpEventHandler(ev event.IEvent) {
@@ -107,24 +106,27 @@ func (tcpService *TcpService) TcpEventHandler(ev event.IEvent) {
case TPT_DisConnected: case TPT_DisConnected:
tcpService.process.DisConnectedRoute(pack.ClientId) tcpService.process.DisConnectedRoute(pack.ClientId)
case TPT_UnknownPack: case TPT_UnknownPack:
tcpService.process.UnknownMsgRoute(pack.ClientId,pack.Data) tcpService.process.UnknownMsgRoute(pack.ClientId, pack.Data, tcpService.recyclerReaderBytes)
case TPT_Pack: case TPT_Pack:
tcpService.process.MsgRoute(pack.ClientId,pack.Data) tcpService.process.MsgRoute(pack.ClientId, pack.Data, tcpService.recyclerReaderBytes)
} }
} }
func (tcpService *TcpService) SetProcessor(process processor.IProcessor,handler event.IEventHandler){ func (tcpService *TcpService) recyclerReaderBytes(data []byte) {
tcpService.process = process
tcpService.RegEventReceiverFunc(event.Sys_Event_Tcp,handler, tcpService.TcpEventHandler)
} }
func (tcpService *TcpService) NewClient(conn *network.TCPConn) network.Agent { func (tcpService *TcpService) SetProcessor(process processor.IProcessor, handler event.IEventHandler) {
tcpService.process = process
tcpService.RegEventReceiverFunc(event.Sys_Event_Tcp, handler, tcpService.TcpEventHandler)
}
func (tcpService *TcpService) NewClient(conn network.Conn) network.Agent {
tcpService.mapClientLocker.Lock() tcpService.mapClientLocker.Lock()
defer tcpService.mapClientLocker.Unlock() defer tcpService.mapClientLocker.Unlock()
uuId,_ := uuid.NewUUID() uuId, _ := uuid.NewUUID()
clientId := strings.ReplaceAll(uuId.String(), "-", "") clientId := strings.ReplaceAll(uuId.String(), "-", "")
pClient := &Client{tcpConn: conn, id: clientId} pClient := &Client{tcpConn: conn.(*network.NetConn), id: clientId}
pClient.tcpService = tcpService pClient.tcpService = tcpService
tcpService.mapClient[clientId] = pClient tcpService.mapClient[clientId] = pClient
@@ -138,52 +140,49 @@ func (slf *Client) GetId() string {
func (slf *Client) Run() { func (slf *Client) Run() {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096) log.StackError(fmt.Sprint(r))
l := runtime.Stack(buf, false)
errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString))
} }
}() }()
slf.tcpService.NotifyEvent(&event.Event{Type:event.Sys_Event_Tcp,Data:TcpPack{ClientId:slf.id,Type:TPT_Connected}}) slf.tcpService.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPT_Connected}})
for{ for {
if slf.tcpConn == nil { if slf.tcpConn == nil {
break break
} }
slf.tcpConn.SetReadDeadline(slf.tcpService.tcpServer.ReadDeadline) slf.tcpConn.SetReadDeadline(slf.tcpService.tcpServer.ReadDeadline)
bytes,err := slf.tcpConn.ReadMsg() bytes, err := slf.tcpConn.ReadMsg()
if err != nil { if err != nil {
log.Debug("read client failed",log.ErrorAttr("error",err),log.String("clientId",slf.id)) log.Debug("read client failed", log.ErrorField("error", err), log.String("clientId", slf.id))
break break
} }
data,err:=slf.tcpService.process.Unmarshal(slf.id,bytes) data, err := slf.tcpService.process.Unmarshal(slf.id, bytes)
if err != nil { if err != nil {
slf.tcpService.NotifyEvent(&event.Event{Type:event.Sys_Event_Tcp,Data:TcpPack{ClientId:slf.id,Type:TPT_UnknownPack,Data:bytes}}) slf.tcpService.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPT_UnknownPack, Data: bytes}})
continue continue
} }
slf.tcpService.NotifyEvent(&event.Event{Type:event.Sys_Event_Tcp,Data:TcpPack{ClientId:slf.id,Type:TPT_Pack,Data:data}}) slf.tcpService.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPT_Pack, Data: data}})
} }
} }
func (slf *Client) OnClose(){ func (slf *Client) OnClose() {
slf.tcpService.NotifyEvent(&event.Event{Type:event.Sys_Event_Tcp,Data:TcpPack{ClientId:slf.id,Type:TPT_DisConnected}}) slf.tcpService.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPT_DisConnected}})
slf.tcpService.mapClientLocker.Lock() slf.tcpService.mapClientLocker.Lock()
defer slf.tcpService.mapClientLocker.Unlock() defer slf.tcpService.mapClientLocker.Unlock()
delete (slf.tcpService.mapClient,slf.GetId()) delete(slf.tcpService.mapClient, slf.GetId())
} }
func (tcpService *TcpService) SendMsg(clientId string,msg interface{}) error{ func (tcpService *TcpService) SendMsg(clientId string, msg interface{}) error {
tcpService.mapClientLocker.Lock() tcpService.mapClientLocker.Lock()
client,ok := tcpService.mapClient[clientId] client, ok := tcpService.mapClient[clientId]
if ok == false{ if ok == false {
tcpService.mapClientLocker.Unlock() tcpService.mapClientLocker.Unlock()
return fmt.Errorf("client %d is disconnect!",clientId) return fmt.Errorf("client %s is disconnect", clientId)
} }
tcpService.mapClientLocker.Unlock() tcpService.mapClientLocker.Unlock()
bytes,err := tcpService.process.Marshal(clientId,msg) bytes, err := tcpService.process.Marshal(clientId, msg)
if err != nil { if err != nil {
return err return err
} }
@@ -194,53 +193,51 @@ func (tcpService *TcpService) Close(clientId string) {
tcpService.mapClientLocker.Lock() tcpService.mapClientLocker.Lock()
defer tcpService.mapClientLocker.Unlock() defer tcpService.mapClientLocker.Unlock()
client,ok := tcpService.mapClient[clientId] client, ok := tcpService.mapClient[clientId]
if ok == false{ if ok == false {
return return
} }
if client.tcpConn!=nil { if client.tcpConn != nil {
client.tcpConn.Close() client.tcpConn.Close()
} }
return return
} }
func (tcpService *TcpService) GetClientIp(clientid string) string{ func (tcpService *TcpService) GetClientIp(clientId string) string {
tcpService.mapClientLocker.Lock() tcpService.mapClientLocker.Lock()
defer tcpService.mapClientLocker.Unlock() defer tcpService.mapClientLocker.Unlock()
pClient,ok := tcpService.mapClient[clientid] pClient, ok := tcpService.mapClient[clientId]
if ok == false{ if ok == false {
return "" return ""
} }
return pClient.tcpConn.GetRemoteIp() return pClient.tcpConn.GetRemoteIp()
} }
func (tcpService *TcpService) SendRawMsg(clientId string, msg []byte) error {
func (tcpService *TcpService) SendRawMsg(clientId string,msg []byte) error{
tcpService.mapClientLocker.Lock() tcpService.mapClientLocker.Lock()
client,ok := tcpService.mapClient[clientId] client, ok := tcpService.mapClient[clientId]
if ok == false{ if ok == false {
tcpService.mapClientLocker.Unlock() tcpService.mapClientLocker.Unlock()
return fmt.Errorf("client %d is disconnect!",clientId) return fmt.Errorf("client %s is disconnect", clientId)
} }
tcpService.mapClientLocker.Unlock() tcpService.mapClientLocker.Unlock()
return client.tcpConn.WriteMsg(msg) return client.tcpConn.WriteMsg(msg)
} }
func (tcpService *TcpService) SendRawData(clientId string,data []byte) error{ func (tcpService *TcpService) SendRawData(clientId string, data []byte) error {
tcpService.mapClientLocker.Lock() tcpService.mapClientLocker.Lock()
client,ok := tcpService.mapClient[clientId] client, ok := tcpService.mapClient[clientId]
if ok == false{ if ok == false {
tcpService.mapClientLocker.Unlock() tcpService.mapClientLocker.Unlock()
return fmt.Errorf("client %d is disconnect!",clientId) return fmt.Errorf("client %s is disconnect", clientId)
} }
tcpService.mapClientLocker.Unlock() tcpService.mapClientLocker.Unlock()
return client.tcpConn.WriteRawMsg(data) return client.tcpConn.WriteRawMsg(data)
} }
func (tcpService *TcpService) GetConnNum() int { func (tcpService *TcpService) GetConnNum() int {
tcpService.mapClientLocker.Lock() tcpService.mapClientLocker.Lock()
connNum := len(tcpService.mapClient) connNum := len(tcpService.mapClient)
@@ -248,14 +245,14 @@ func (tcpService *TcpService) GetConnNum() int {
return connNum return connNum
} }
func (server *TcpService) SetNetMempool(mempool bytespool.IBytesMempool){ func (tcpService *TcpService) SetNetMemPool(memPool bytespool.IBytesMemPool) {
server.tcpServer.SetNetMempool(mempool) tcpService.tcpServer.SetNetMemPool(memPool)
} }
func (server *TcpService) GetNetMempool() bytespool.IBytesMempool { func (tcpService *TcpService) GetNetMemPool() bytespool.IBytesMemPool {
return server.tcpServer.GetNetMempool() return tcpService.tcpServer.GetNetMemPool()
} }
func (server *TcpService) ReleaseNetMem(byteBuff []byte) { func (tcpService *TcpService) ReleaseNetMem(byteBuff []byte) {
server.tcpServer.GetNetMempool().ReleaseBytes(byteBuff) tcpService.tcpServer.GetNetMemPool().ReleaseBytes(byteBuff)
} }

View File

@@ -7,26 +7,28 @@ import (
"github.com/duanhf2012/origin/v2/network" "github.com/duanhf2012/origin/v2/network"
"github.com/duanhf2012/origin/v2/network/processor" "github.com/duanhf2012/origin/v2/network/processor"
"github.com/duanhf2012/origin/v2/service" "github.com/duanhf2012/origin/v2/service"
"sync"
"github.com/google/uuid" "github.com/google/uuid"
"strings" "strings"
"sync"
) )
// Deprecated: replace it with the WSModule
type WSService struct { type WSService struct {
service.Service service.Service
wsServer network.WSServer wsServer network.WSServer
mapClientLocker sync.RWMutex mapClientLocker sync.RWMutex
mapClient map[string] *WSClient mapClient map[string]*WSClient
process processor.IProcessor process processor.IProcessor
} }
type WSPackType int8 type WSPackType int8
const(
WPT_Connected WSPackType = 0 const (
WPT_Connected WSPackType = 0
WPT_DisConnected WSPackType = 1 WPT_DisConnected WSPackType = 1
WPT_Pack WSPackType = 2 WPT_Pack WSPackType = 2
WPT_UnknownPack WSPackType = 3 WPT_UnknownPack WSPackType = 3
) )
const Default_WS_MaxConnNum = 3000 const Default_WS_MaxConnNum = 3000
@@ -34,8 +36,8 @@ const Default_WS_PendingWriteNum = 10000
const Default_WS_MaxMsgLen = 65535 const Default_WS_MaxMsgLen = 65535
type WSClient struct { type WSClient struct {
id string id string
wsConn *network.WSConn wsConn *network.WSConn
wsService *WSService wsService *WSService
} }
@@ -46,44 +48,43 @@ type WSPack struct {
Data interface{} Data interface{}
} }
func (ws *WSService) OnInit() error{ func (ws *WSService) OnInit() error {
iConfig := ws.GetServiceCfg() iConfig := ws.GetServiceCfg()
if iConfig == nil { if iConfig == nil {
return fmt.Errorf("%s service config is error!", ws.GetName()) return fmt.Errorf("%s service config is error", ws.GetName())
} }
wsCfg := iConfig.(map[string]interface{}) wsCfg := iConfig.(map[string]interface{})
addr,ok := wsCfg["ListenAddr"] addr, ok := wsCfg["ListenAddr"]
if ok == false { if ok == false {
return fmt.Errorf("%s service config is error!", ws.GetName()) return fmt.Errorf("%s service config is error", ws.GetName())
} }
ws.wsServer.Addr = addr.(string) ws.wsServer.Addr = addr.(string)
ws.wsServer.MaxConnNum = Default_WS_MaxConnNum ws.wsServer.MaxConnNum = Default_WS_MaxConnNum
ws.wsServer.PendingWriteNum = Default_WS_PendingWriteNum ws.wsServer.PendingWriteNum = Default_WS_PendingWriteNum
ws.wsServer.MaxMsgLen = Default_WS_MaxMsgLen ws.wsServer.MaxMsgLen = Default_WS_MaxMsgLen
MaxConnNum,ok := wsCfg["MaxConnNum"] MaxConnNum, ok := wsCfg["MaxConnNum"]
if ok == true { if ok == true {
ws.wsServer.MaxConnNum = int(MaxConnNum.(float64)) ws.wsServer.MaxConnNum = int(MaxConnNum.(float64))
} }
PendingWriteNum,ok := wsCfg["PendingWriteNum"] PendingWriteNum, ok := wsCfg["PendingWriteNum"]
if ok == true { if ok == true {
ws.wsServer.PendingWriteNum = int(PendingWriteNum.(float64)) ws.wsServer.PendingWriteNum = int(PendingWriteNum.(float64))
} }
MaxMsgLen,ok := wsCfg["MaxMsgLen"] MaxMsgLen, ok := wsCfg["MaxMsgLen"]
if ok == true { if ok == true {
ws.wsServer.MaxMsgLen = uint32(MaxMsgLen.(float64)) ws.wsServer.MaxMsgLen = uint32(MaxMsgLen.(float64))
} }
ws.mapClient = make( map[string] *WSClient, ws.wsServer.MaxConnNum) ws.mapClient = make(map[string]*WSClient, ws.wsServer.MaxConnNum)
ws.wsServer.NewAgent = ws.NewWSClient ws.wsServer.NewAgent = ws.NewWSClient
ws.wsServer.Start() return ws.wsServer.Start()
return nil
} }
func (ws *WSService) SetMessageType(messageType int){ func (ws *WSService) SetMessageType(messageType int) {
ws.wsServer.SetMessageType(messageType) ws.wsServer.SetMessageType(messageType)
} }
@@ -95,15 +96,15 @@ func (ws *WSService) WSEventHandler(ev event.IEvent) {
case WPT_DisConnected: case WPT_DisConnected:
pack.MsgProcessor.DisConnectedRoute(pack.ClientId) pack.MsgProcessor.DisConnectedRoute(pack.ClientId)
case WPT_UnknownPack: case WPT_UnknownPack:
pack.MsgProcessor.UnknownMsgRoute(pack.ClientId,pack.Data) pack.MsgProcessor.UnknownMsgRoute(pack.ClientId, pack.Data, ws.recyclerReaderBytes)
case WPT_Pack: case WPT_Pack:
pack.MsgProcessor.MsgRoute(pack.ClientId,pack.Data) pack.MsgProcessor.MsgRoute(pack.ClientId, pack.Data, ws.recyclerReaderBytes)
} }
} }
func (ws *WSService) SetProcessor(process processor.IProcessor,handler event.IEventHandler){ func (ws *WSService) SetProcessor(process processor.IProcessor, handler event.IEventHandler) {
ws.process = process ws.process = process
ws.RegEventReceiverFunc(event.Sys_Event_WebSocket,handler, ws.WSEventHandler) ws.RegEventReceiverFunc(event.Sys_Event_WebSocket, handler, ws.WSEventHandler)
} }
func (ws *WSService) NewWSClient(conn *network.WSConn) network.Agent { func (ws *WSService) NewWSClient(conn *network.WSConn) network.Agent {
@@ -125,58 +126,60 @@ func (slf *WSClient) GetId() string {
} }
func (slf *WSClient) Run() { func (slf *WSClient) Run() {
slf.wsService.NotifyEvent(&event.Event{Type:event.Sys_Event_WebSocket,Data:&WSPack{ClientId:slf.id,Type:WPT_Connected,MsgProcessor:slf.wsService.process}}) slf.wsService.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: slf.id, Type: WPT_Connected, MsgProcessor: slf.wsService.process}})
for{ for {
bytes,err := slf.wsConn.ReadMsg() bytes, err := slf.wsConn.ReadMsg()
if err != nil { if err != nil {
log.Debug("read client id %d is error:%+v",slf.id,err) log.Debugf("read client id %s is error:%+v", slf.id, err)
break break
} }
data,err:=slf.wsService.process.Unmarshal(slf.id,bytes) data, err := slf.wsService.process.Unmarshal(slf.id, bytes)
if err != nil { if err != nil {
slf.wsService.NotifyEvent(&event.Event{Type:event.Sys_Event_WebSocket,Data:&WSPack{ClientId:slf.id,Type:WPT_UnknownPack,Data:bytes,MsgProcessor:slf.wsService.process}}) slf.wsService.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: slf.id, Type: WPT_UnknownPack, Data: bytes, MsgProcessor: slf.wsService.process}})
continue continue
} }
slf.wsService.NotifyEvent(&event.Event{Type:event.Sys_Event_WebSocket,Data:&WSPack{ClientId:slf.id,Type:WPT_Pack,Data:data,MsgProcessor:slf.wsService.process}}) slf.wsService.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: slf.id, Type: WPT_Pack, Data: data, MsgProcessor: slf.wsService.process}})
} }
} }
func (slf *WSClient) OnClose(){ func (slf *WSClient) OnClose() {
slf.wsService.NotifyEvent(&event.Event{Type:event.Sys_Event_WebSocket,Data:&WSPack{ClientId:slf.id,Type:WPT_DisConnected,MsgProcessor:slf.wsService.process}}) slf.wsService.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: slf.id, Type: WPT_DisConnected, MsgProcessor: slf.wsService.process}})
slf.wsService.mapClientLocker.Lock() slf.wsService.mapClientLocker.Lock()
defer slf.wsService.mapClientLocker.Unlock() defer slf.wsService.mapClientLocker.Unlock()
delete (slf.wsService.mapClient,slf.GetId()) delete(slf.wsService.mapClient, slf.GetId())
} }
func (ws *WSService) SendMsg(clientid string,msg interface{}) error{ func (ws *WSService) SendMsg(clientId string, msg interface{}) error {
ws.mapClientLocker.Lock() ws.mapClientLocker.Lock()
client,ok := ws.mapClient[clientid] client, ok := ws.mapClient[clientId]
if ok == false{ if ok == false {
ws.mapClientLocker.Unlock() ws.mapClientLocker.Unlock()
return fmt.Errorf("client %d is disconnect!",clientid) return fmt.Errorf("client %s is disconnect", clientId)
} }
ws.mapClientLocker.Unlock() ws.mapClientLocker.Unlock()
bytes,err := ws.process.Marshal(clientid,msg) bytes, err := ws.process.Marshal(clientId, msg)
if err != nil { if err != nil {
return err return err
} }
return client.wsConn.WriteMsg(bytes) return client.wsConn.WriteMsg(bytes)
} }
func (ws *WSService) Close(clientid string) { func (ws *WSService) Close(clientId string) {
ws.mapClientLocker.Lock() ws.mapClientLocker.Lock()
defer ws.mapClientLocker.Unlock() defer ws.mapClientLocker.Unlock()
client,ok := ws.mapClient[clientid] client, ok := ws.mapClient[clientId]
if ok == false{ if ok == false {
return return
} }
if client.wsConn!=nil { if client.wsConn != nil {
client.wsConn.Close() client.wsConn.Close()
} }
return return
} }
func (ws *WSService) recyclerReaderBytes(data []byte) {
}

View File

@@ -9,7 +9,7 @@ import (
func NewAesEncrypt(key string) (aes *AesEncrypt, err error) { func NewAesEncrypt(key string) (aes *AesEncrypt, err error) {
keyLen := len(key) keyLen := len(key)
if keyLen < 16 { if keyLen < 16 {
err = fmt.Errorf("The length of res key shall not be less than 16") err = fmt.Errorf("the length of res key shall not be less than 16")
return return
} }
aes = &AesEncrypt{ aes = &AesEncrypt{
@@ -22,12 +22,12 @@ type AesEncrypt struct {
StrKey string StrKey string
} }
func (this *AesEncrypt) getKey() []byte { func (ae *AesEncrypt) getKey() []byte {
keyLen := len(this.StrKey) keyLen := len(ae.StrKey)
if keyLen < 16 { if keyLen < 16 {
panic("The length of res key shall not be less than 16") panic("The length of res key shall not be less than 16")
} }
arrKey := []byte(this.StrKey) arrKey := []byte(ae.StrKey)
if keyLen >= 32 { if keyLen >= 32 {
//取前32个字节 //取前32个字节
return arrKey[:32] return arrKey[:32]
@@ -40,37 +40,37 @@ func (this *AesEncrypt) getKey() []byte {
return arrKey[:16] return arrKey[:16]
} }
//加密字符串 // Encrypt 加密字符串
func (this *AesEncrypt) Encrypt(strMesg string) ([]byte, error) { func (ae *AesEncrypt) Encrypt(str string) ([]byte, error) {
key := this.getKey() key := ae.getKey()
var iv = []byte(key)[:aes.BlockSize] var iv = key[:aes.BlockSize]
encrypted := make([]byte, len(strMesg)) encrypted := make([]byte, len(str))
aesBlockEncrypter, err := aes.NewCipher(key) aesBlockEncrypter, err := aes.NewCipher(key)
if err != nil { if err != nil {
return nil, err return nil, err
} }
aesEncrypter := cipher.NewCFBEncrypter(aesBlockEncrypter, iv) aesEncrypter := cipher.NewCFBEncrypter(aesBlockEncrypter, iv)
aesEncrypter.XORKeyStream(encrypted, []byte(strMesg)) aesEncrypter.XORKeyStream(encrypted, []byte(str))
return encrypted, nil return encrypted, nil
} }
//解密字符串 // Decrypt 解密字符串
func (this *AesEncrypt) Decrypt(src []byte) (strDesc string, err error) { func (ae *AesEncrypt) Decrypt(src []byte) (strDesc string, err error) {
defer func() { defer func() {
//错误处理 //错误处理
if e := recover(); e != nil { if e := recover(); e != nil {
err = e.(error) err = e.(error)
} }
}() }()
key := this.getKey() key := ae.getKey()
var iv = []byte(key)[:aes.BlockSize] var iv = key[:aes.BlockSize]
decrypted := make([]byte, len(src)) decrypted := make([]byte, len(src))
var aesBlockDecrypter cipher.Block var aesBlockDecrypter cipher.Block
aesBlockDecrypter, err = aes.NewCipher([]byte(key)) aesBlockDecrypter, err = aes.NewCipher(key)
if err != nil { if err != nil {
return "", err return "", err
} }
aesDecrypter := cipher.NewCFBDecrypter(aesBlockDecrypter, iv) aesDecrypter := cipher.NewCFBDecrypter(aesBlockDecrypter, iv)
aesDecrypter.XORKeyStream(decrypted, src) aesDecrypter.XORKeyStream(decrypted, src)
return string(decrypted), nil return string(decrypted), nil
} }

View File

@@ -42,7 +42,7 @@ func setBitTagByIndex[Number BitNumber, UNumber UnsignedNumber](bitBuff []Number
func GetBitwiseTag[Number BitNumber, UNumber UnsignedNumber](bitBuff []Number, bitPositionIndex UNumber) (bool, error) { func GetBitwiseTag[Number BitNumber, UNumber UnsignedNumber](bitBuff []Number, bitPositionIndex UNumber) (bool, error) {
sliceIndex, sliceBitIndex, ret := getBitTagIndex(bitBuff, bitPositionIndex) sliceIndex, sliceBitIndex, ret := getBitTagIndex(bitBuff, bitPositionIndex)
if ret == false { if ret == false {
return false, errors.New("Invalid parameter") return false, errors.New("invalid parameter")
} }
return (bitBuff[sliceIndex] & (1 << sliceBitIndex)) > 0, nil return (bitBuff[sliceIndex] & (1 << sliceBitIndex)) > 0, nil

View File

@@ -4,7 +4,7 @@ import (
"sync" "sync"
) )
type IBytesMempool interface { type IBytesMemPool interface {
MakeBytes(size int) []byte MakeBytes(size int) []byte
ReleaseBytes(byteBuff []byte) bool ReleaseBytes(byteBuff []byte) bool
} }

View File

@@ -7,18 +7,18 @@ import (
"runtime/debug" "runtime/debug"
) )
func F(callback interface{},recoverNum int, args ...interface{}) { func F(callback interface{}, recoverNum int, args ...interface{}) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
var coreInfo string var coreInfo string
coreInfo = string(debug.Stack()) coreInfo = string(debug.Stack())
coreInfo += "\n" + fmt.Sprintf("Core information is %v\n", r) coreInfo += "\n" + fmt.Sprintf("Core information is %v\n", r)
log.SError(coreInfo) log.SError(coreInfo)
if recoverNum > 0{ if recoverNum > 0 {
recoverNum -= 1 recoverNum -= 1
} }
if recoverNum == -1 || recoverNum > 0 { if recoverNum == -1 || recoverNum > 0 {
go F(callback,recoverNum, args...) go F(callback, recoverNum, args...)
} }
} }
}() }()
@@ -36,10 +36,10 @@ func F(callback interface{},recoverNum int, args ...interface{}) {
} }
func Go(callback interface{}, args ...interface{}) { func Go(callback interface{}, args ...interface{}) {
go F(callback,0, args...) go F(callback, 0, args...)
} }
//-1表示一直恢复 // GoRecover -1表示一直恢复
func GoRecover(callback interface{},recoverNum int, args ...interface{}) { func GoRecover(callback interface{}, recoverNum int, args ...interface{}) {
go F(callback,recoverNum, args...) go F(callback, recoverNum, args...)
} }

View File

@@ -1,129 +0,0 @@
package math
import (
"github.com/duanhf2012/origin/v2/log"
)
type NumberType interface {
int | int8 | int16 | int32 | int64 | float32 | float64 | uint | uint8 | uint16 | uint32 | uint64
}
type SignedNumberType interface {
int | int8 | int16 | int32 | int64 | float32 | float64
}
type FloatType interface {
float32 | float64
}
func Max[NumType NumberType](number1 NumType, number2 NumType) NumType {
if number1 > number2 {
return number1
}
return number2
}
func Min[NumType NumberType](number1 NumType, number2 NumType) NumType {
if number1 < number2 {
return number1
}
return number2
}
func Abs[NumType SignedNumberType](Num NumType) NumType {
if Num < 0 {
return -1 * Num
}
return Num
}
func AddSafe[NumType NumberType](number1 NumType, number2 NumType) (NumType, bool) {
ret := number1 + number2
if number2 > 0 && ret < number1 {
log.Stack("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
return ret, false
} else if number2 < 0 && ret > number1 {
log.Stack("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
return ret, false
}
return ret, true
}
func SubSafe[NumType NumberType](number1 NumType, number2 NumType) (NumType, bool) {
ret := number1 - number2
if number2 > 0 && ret > number1 {
log.Stack("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
return ret, false
} else if number2 < 0 && ret < number1 {
log.Stack("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
return ret, false
}
return ret, true
}
func MulSafe[NumType NumberType](number1 NumType, number2 NumType) (NumType, bool) {
ret := number1 * number2
if number1 == 0 || number2 == 0 {
return ret, true
}
if ret/number2 == number1 {
return ret, true
}
log.Stack("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
return ret, true
}
func Add[NumType NumberType](number1 NumType, number2 NumType) NumType {
ret, _ := AddSafe(number1, number2)
return ret
}
func Sub[NumType NumberType](number1 NumType, number2 NumType) NumType {
ret, _ := SubSafe(number1, number2)
return ret
}
func Mul[NumType NumberType](number1 NumType, number2 NumType) NumType {
ret, _ := MulSafe(number1, number2)
return ret
}
// 安全的求比例
func PercentRateSafe[NumType NumberType, OutNumType NumberType](maxValue int64, rate NumType, numbers ...NumType) (OutNumType, bool) {
// 比例不能为负数
if rate < 0 {
log.Stack("rate must not positive")
return 0, false
}
if rate == 0 {
// 比例为0
return 0, true
}
ret := int64(rate)
for _, number := range numbers {
number64 := int64(number)
result, success := MulSafe(number64, ret)
if !success {
// 基数*比例越界了int64都越界了没办法了
return 0, false
}
ret = result
}
ret = ret / 10000
if ret > maxValue {
return 0, false
}
return OutNumType(ret), true
}

View File

@@ -0,0 +1,173 @@
package pubsub
import (
"container/list"
"sync/atomic"
)
type TopicType int
type Key uint64
type IBaseSubscriber interface {
OnSubscribe(key Key)
GetKey() Key
}
type ISubscriber interface {
IBaseSubscriber
OnEvent(ctx ...any)
}
type IPublisher interface {
Publish(topic TopicType, ctx ...any)
Subscribe(topic TopicType, sub ISubscriber)
UnSubscribe(topic TopicType)
UnSubscribeKey(key Key)
}
var keyID uint64
func genKeyID() Key {
return Key(atomic.AddUint64(&keyID, 1))
}
type KeyData struct {
subscriber ISubscriber
topicType TopicType
keyElement *list.Element
}
type SubscriberSet map[Key]KeyData
type TopicSet map[TopicType]*list.List
type Publisher struct {
subscriberSet SubscriberSet
topicSet TopicSet
}
func (set *SubscriberSet) init() {
*set = make(SubscriberSet, 64)
}
func (set *SubscriberSet) add(keyElement *list.Element, topicType TopicType, subscriber ISubscriber) {
(*set)[keyElement.Value.(Key)] = KeyData{subscriber: subscriber, topicType: topicType, keyElement: keyElement}
}
func (set *SubscriberSet) del(key Key) {
delete(*set, key)
}
func (set *SubscriberSet) get(key Key) (KeyData, bool) {
keyData, ok := (*set)[key]
if !ok {
return keyData, false
}
return keyData, true
}
func (set *TopicSet) init() {
*set = make(TopicSet, 64)
}
func (set *TopicSet) add(topic TopicType, key Key) *list.Element {
keyList := (*set)[topic]
if keyList == nil {
keyList = list.New()
(*set)[topic] = keyList
}
return keyList.PushBack(key)
}
func (set *TopicSet) del(topic TopicType, keyElement *list.Element) {
keyList := (*set)[topic]
if keyList == nil {
return
}
keyList.Remove(keyElement)
}
func (set *TopicSet) foreach(topic TopicType, cb func(key Key)) {
keyList := (*set)[topic]
if keyList == nil {
return
}
for e := keyList.Front(); e != nil; e = e.Next() {
cb(e.Value.(Key))
}
}
type BaseSubscriber struct {
key Key
}
func (bs *BaseSubscriber) OnSubscribe(key Key) {
bs.key = key
}
func (bs *BaseSubscriber) GetKey() Key {
return bs.key
}
func (pub *Publisher) lazyInit() {
if pub.subscriberSet == nil {
pub.subscriberSet.init()
}
if pub.topicSet == nil {
pub.topicSet.init()
}
}
func (pub *Publisher) add(topic TopicType, sub ISubscriber) Key {
key := genKeyID()
ele := pub.topicSet.add(topic, key)
pub.subscriberSet.add(ele, topic, sub)
return key
}
func (pub *Publisher) Publish(topic TopicType, ctx ...any) {
pub.lazyInit()
pub.topicSet.foreach(topic, func(key Key) {
keyData, ok := pub.subscriberSet.get(key)
if ok == false {
return
}
keyData.subscriber.OnEvent(ctx...)
})
}
func (pub *Publisher) Subscribe(topic TopicType, sub ISubscriber) bool {
if topic == 0 {
return false
}
pub.lazyInit()
sub.OnSubscribe(pub.add(topic, sub))
return true
}
func (pub *Publisher) UnSubscribe(topic TopicType) {
keyList := pub.topicSet[topic]
if keyList == nil {
return
}
for e := keyList.Front(); e != nil; e = e.Next() {
pub.subscriberSet.del(e.Value.(Key))
}
delete(pub.topicSet, topic)
}
func (pub *Publisher) UnSubscribeKey(key Key) {
keyData, ok := pub.subscriberSet.get(key)
if ok == false {
return
}
pub.topicSet.del(keyData.topicType, keyData.keyElement)
pub.subscriberSet.del(key)
}

View File

@@ -0,0 +1,54 @@
package pubsub
import (
"testing"
)
const (
Invalid TopicType = iota
Topic1
Topic2
)
var test *testing.T
type Subscriber1 struct {
BaseSubscriber
}
type Subscriber2 struct {
BaseSubscriber
}
func (sub *Subscriber1) OnEvent(ctx ...any) {
test.Log("Subscriber1 OnEvent", " key ", sub.GetKey(), ctx)
}
func (sub *Subscriber2) OnEvent(ctx ...any) {
test.Log("Subscriber2 OnEvent", " key ", sub.GetKey(), ctx)
}
func TestPubSub(t *testing.T) {
test = t
var publisher Publisher
// 创建3个订阅者
var subscriber []ISubscriber
subscriber = append(subscriber, &Subscriber1{}, &Subscriber1{}, &Subscriber2{})
// 分别注册进Publisher中
publisher.Subscribe(Topic1, subscriber[0])
publisher.Subscribe(Topic1, subscriber[1])
publisher.Subscribe(Topic2, subscriber[2])
// 发布订阅,两个Subscriber1都会调用OnEvent
publisher.Publish(Topic1, 1, 2, 3)
// 删除订阅Publish后只有Subscriber1的key2收到
publisher.UnSubscribeKey(subscriber[0].GetKey())
publisher.Publish(Topic1, 1, 2, 3)
// 删除Topic2Publish将收不到
publisher.UnSubscribe(Topic2)
publisher.Publish(Topic2, 1)
}

View File

@@ -1,91 +0,0 @@
package rand
import (
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
func RandGroup(p ...uint32) int {
if p == nil {
panic("args not found")
}
r := make([]uint32, len(p))
for i := 0; i < len(p); i++ {
if i == 0 {
r[0] = p[0]
} else {
r[i] = r[i-1] + p[i]
}
}
rl := r[len(r)-1]
if rl == 0 {
return 0
}
rn := uint32(rand.Int63n(int64(rl)))
for i := 0; i < len(r); i++ {
if rn < r[i] {
return i
}
}
panic("bug")
}
func RandInterval(b1, b2 int32) int32 {
if b1 == b2 {
return b1
}
min, max := int64(b1), int64(b2)
if min > max {
min, max = max, min
}
return int32(rand.Int63n(max-min+1) + min)
}
func RandIntervalN(b1, b2 int32, n uint32) []int32 {
if b1 == b2 {
return []int32{b1}
}
min, max := int64(b1), int64(b2)
if min > max {
min, max = max, min
}
l := max - min + 1
if int64(n) > l {
n = uint32(l)
}
r := make([]int32, n)
m := make(map[int32]int32)
for i := uint32(0); i < n; i++ {
v := int32(rand.Int63n(l) + min)
if mv, ok := m[v]; ok {
r[i] = mv
} else {
r[i] = v
}
lv := int32(l - 1 + min)
if v != lv {
if mv, ok := m[lv]; ok {
m[v] = mv
} else {
m[v] = lv
}
}
l--
}
return r
}

85
util/smath/smath.go Normal file
View File

@@ -0,0 +1,85 @@
package smath
import (
"github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/util/typ"
)
func Max[NumType typ.Number](number1 NumType, number2 NumType) NumType {
if number1 > number2 {
return number1
}
return number2
}
func Min[NumType typ.Number](number1 NumType, number2 NumType) NumType {
if number1 < number2 {
return number1
}
return number2
}
func Abs[NumType typ.Signed | typ.Float](Num NumType) NumType {
if Num < 0 {
return -1 * Num
}
return Num
}
func AddSafe[NumType typ.Number](number1 NumType, number2 NumType) (NumType, bool) {
ret := number1 + number2
if number2 > 0 && ret < number1 {
log.SStackError("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
return ret, false
} else if number2 < 0 && ret > number1 {
log.SStackError("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
return ret, false
}
return ret, true
}
func SubSafe[NumType typ.Number](number1 NumType, number2 NumType) (NumType, bool) {
ret := number1 - number2
if number2 > 0 && ret > number1 {
log.SStackError("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
return ret, false
} else if number2 < 0 && ret < number1 {
log.SStackError("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
return ret, false
}
return ret, true
}
func MulSafe[NumType typ.Number](number1 NumType, number2 NumType) (NumType, bool) {
ret := number1 * number2
if number1 == 0 || number2 == 0 {
return ret, true
}
if ret/number2 == number1 {
return ret, true
}
log.SStackError("Calculation overflow", log.Any("number1", number1), log.Any("number2", number2))
return ret, true
}
func Add[NumType typ.Number](number1 NumType, number2 NumType) NumType {
ret, _ := AddSafe(number1, number2)
return ret
}
func Sub[NumType typ.Number](number1 NumType, number2 NumType) NumType {
ret, _ := SubSafe(number1, number2)
return ret
}
func Mul[NumType typ.Number](number1 NumType, number2 NumType) NumType {
ret, _ := MulSafe(number1, number2)
return ret
}

108
util/srand/slice.go Normal file
View File

@@ -0,0 +1,108 @@
package srand
import (
"github.com/duanhf2012/origin/v2/util/typ"
"math/rand"
"slices"
)
func Sum[E ~[]T, T typ.Number](arr E) T {
var sum T
for i := range arr {
sum += arr[i]
}
return sum
}
func SumFunc[E ~[]V, V any, T typ.Number](arr E, getValue func(i int) T) T {
var sum T
for i := range arr {
sum += getValue(i)
}
return sum
}
func Shuffle[E ~[]T, T any](arr E) {
rand.Shuffle(len(arr), func(i, j int) {
arr[i], arr[j] = arr[j], arr[i]
})
}
func RandOne[E ~[]T, T any](arr E) T {
return arr[rand.Intn(len(arr))]
}
func RandN[E ~[]T, T any](arr E, num int) []T {
index := make([]int, 0, len(arr))
for i := range arr {
index = append(index, i)
}
Shuffle(index)
if len(index) > num {
index = index[:num]
}
ret := make([]T, 0, len(index))
for i := range index {
ret = append(ret, arr[index[i]])
}
return ret
}
func RandWeight[E ~[]T, T typ.Integer](weights E) int {
totalWeight := Sum(weights)
if totalWeight <= 0 {
return -1
}
t := T(rand.Intn(int(totalWeight)))
for i := range weights {
if t < weights[i] {
return i
}
t -= weights[i]
}
return -1
}
func RandWeightFunc[E ~[]U, U any, T typ.Integer](arr E, getWeight func(i int) T) int {
weights := make([]T, 0, len(arr))
for i := range arr {
weights = append(weights, getWeight(i))
}
return RandWeight(weights)
}
func Get[E ~[]T, T any, U typ.Integer](arr E, index U) (ret T, ok bool) {
if index < 0 || int(index) >= len(arr) {
return
}
ret = arr[index]
ok = true
return
}
func GetPointer[E ~[]T, T any, U typ.Integer](arr E, index U) *T {
if index < 0 || int(index) >= len(arr) {
return nil
}
return &arr[index]
}
func GetFunc[E ~[]T, T any](arr E, f func(T) bool) (ret T, ok bool) {
index := slices.IndexFunc(arr, f)
if index < 0 {
return
}
return arr[index], true
}
func GetPointerFunc[E ~[]T, T any](arr E, f func(T) bool) *T {
index := slices.IndexFunc(arr, f)
if index < 0 {
return nil
}
return &arr[index]
}

View File

@@ -5,34 +5,32 @@ import (
) )
type Pool struct { type Pool struct {
C chan interface{} //最大缓存的数量 C chan interface{} //最大缓存的数量
syncPool sysSync.Pool syncPool sysSync.Pool
} }
type IPoolData interface { type IPoolData interface {
Reset() Reset()
IsRef()bool IsRef() bool
Ref() Ref()
UnRef() UnRef()
} }
type PoolEx struct{ type PoolEx struct {
C chan IPoolData //最大缓存的数量 C chan IPoolData //最大缓存的数量
syncPool sysSync.Pool syncPool sysSync.Pool
} }
func (pool *Pool) Get() interface{}{ func (pool *Pool) Get() interface{} {
select { select {
case d := <-pool.C: case d := <-pool.C:
return d return d
default: default:
return pool.syncPool.Get() return pool.syncPool.Get()
} }
return nil
} }
func (pool *Pool) Put(data interface{}){ func (pool *Pool) Put(data interface{}) {
select { select {
case pool.C <- data: case pool.C <- data:
default: default:
@@ -41,14 +39,14 @@ func (pool *Pool) Put(data interface{}){
} }
func NewPool(C chan interface{},New func()interface{}) *Pool{ func NewPool(C chan interface{}, New func() interface{}) *Pool {
var p Pool var p Pool
p.C = C p.C = C
p.syncPool.New = New p.syncPool.New = New
return &p return &p
} }
func NewPoolEx(C chan IPoolData,New func()IPoolData) *PoolEx{ func NewPoolEx(C chan IPoolData, New func() IPoolData) *PoolEx {
var pool PoolEx var pool PoolEx
pool.C = C pool.C = C
pool.syncPool.New = func() interface{} { pool.syncPool.New = func() interface{} {
@@ -57,7 +55,7 @@ func NewPoolEx(C chan IPoolData,New func()IPoolData) *PoolEx{
return &pool return &pool
} }
func (pool *PoolEx) Get() IPoolData{ func (pool *PoolEx) Get() IPoolData {
select { select {
case d := <-pool.C: case d := <-pool.C:
if d.IsRef() { if d.IsRef() {
@@ -79,7 +77,7 @@ func (pool *PoolEx) Get() IPoolData{
return nil return nil
} }
func (pool *PoolEx) Put(data IPoolData){ func (pool *PoolEx) Put(data IPoolData) {
if data.IsRef() == false { if data.IsRef() == false {
panic("Repeatedly freeing memory") panic("Repeatedly freeing memory")
} }
@@ -94,5 +92,3 @@ func (pool *PoolEx) Put(data IPoolData){
pool.syncPool.Put(data) pool.syncPool.Put(data)
} }
} }

View File

@@ -6,11 +6,10 @@ import (
"github.com/duanhf2012/origin/v2/util/sync" "github.com/duanhf2012/origin/v2/util/sync"
"reflect" "reflect"
"runtime" "runtime"
"time"
"sync/atomic" "sync/atomic"
"time"
) )
// ITimer
type ITimer interface { type ITimer interface {
GetId() uint64 GetId() uint64
Cancel() Cancel()
@@ -27,10 +26,9 @@ type ITimer interface {
type OnCloseTimer func(timer ITimer) type OnCloseTimer func(timer ITimer)
type OnAddTimer func(timer ITimer) type OnAddTimer func(timer ITimer)
// Timer
type Timer struct { type Timer struct {
Id uint64 Id uint64
cancelled int32 //是否关闭 cancelled int32 //是否关闭
C chan ITimer //定时器管道 C chan ITimer //定时器管道
interval time.Duration // 时间间隔(用于循环定时器) interval time.Duration // 时间间隔(用于循环定时器)
fireTime time.Time // 触发时间 fireTime time.Time // 触发时间
@@ -46,12 +44,10 @@ type Timer struct {
ref bool ref bool
} }
// Ticker
type Ticker struct { type Ticker struct {
Timer Timer
} }
// Cron
type Cron struct { type Cron struct {
Timer Timer
} }
@@ -101,7 +97,6 @@ func releaseCron(cron *Cron) {
cronPool.Put(cron) cronPool.Put(cron)
} }
// one dispatcher per goroutine (goroutine not safe)
type Dispatcher struct { type Dispatcher struct {
ChanTimer chan ITimer ChanTimer chan ITimer
} }
@@ -129,10 +124,7 @@ func (t *Timer) IsOpen() bool {
func (t *Timer) Do() { func (t *Timer) Do() {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096) log.StackError(fmt.Sprint(r))
l := runtime.Stack(buf, false)
errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString))
} }
}() }()
@@ -172,10 +164,10 @@ func (t *Timer) GetInterval() time.Duration {
} }
func (t *Timer) Cancel() { func (t *Timer) Cancel() {
atomic.StoreInt32(&t.cancelled,1) atomic.StoreInt32(&t.cancelled, 1)
} }
// 判断定时器是否已经取消 // IsActive 判断定时器是否已经取消
func (t *Timer) IsActive() bool { func (t *Timer) IsActive() bool {
return atomic.LoadInt32(&t.cancelled) == 0 return atomic.LoadInt32(&t.cancelled) == 0
} }
@@ -215,10 +207,7 @@ func (c *Cron) Reset() {
func (c *Cron) Do() { func (c *Cron) Do() {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096) log.StackError(fmt.Sprint(r))
l := runtime.Stack(buf, false)
errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString))
} }
}() }()
@@ -271,10 +260,7 @@ func (c *Cron) UnRef() {
func (c *Ticker) Do() { func (c *Ticker) Do() {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
buf := make([]byte, 4096) log.StackError(fmt.Sprint(r))
l := runtime.Stack(buf, false)
errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString))
} }
}() }()

54
util/typ/type.go Normal file
View File

@@ -0,0 +1,54 @@
package typ
import "errors"
type Signed interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
}
type Unsigned interface {
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}
type Float interface {
~float32 | ~float64
}
type Integer interface {
Signed | Unsigned
}
type Number interface {
Signed | Unsigned | Float
}
type Ordered interface {
Number | Float | ~string
}
func ConvertToNumber[DType Number](val interface{}) (DType, error) {
switch val.(type) {
case int64:
return DType(val.(int64)), nil
case int:
return DType(val.(int)), nil
case uint:
return DType(val.(uint)), nil
case uint64:
return DType(val.(uint64)), nil
case float32:
return DType(val.(float32)), nil
case float64:
return DType(val.(float64)), nil
case int32:
return DType(val.(int32)), nil
case uint32:
return DType(val.(uint32)), nil
case int16:
return DType(val.(int16)), nil
case uint16:
return DType(val.(uint16)), nil
}
return 0, errors.New("unsupported type")
}