Compare commits

..

31 Commits

Author SHA1 Message Date
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
83 changed files with 4189 additions and 3127 deletions

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如下
@@ -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 {
} }
``` ```
性能监控功能: 性能监控功能:
------------- -------------
@@ -887,10 +864,11 @@ 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)
@@ -901,6 +879,7 @@ func (slf *TestService7) GoTest(){
``` ```
使用示例如下: 使用示例如下:
``` ```
func (slf *TestService13) testAsyncDo() { func (slf *TestService13) testAsyncDo() {
@@ -954,9 +933,8 @@ func (slf *TestService13) testAsyncDo() {
} }
``` ```
第七章:服务发现 第七章:服务发现
-------------------- ----------------
origin引擎默认使用读取所有结点配置的进行确认结点有哪些Service。引擎也支持动态服务发现的方式支持etcd与origin类型具体请参照【配置说明】部分Node结点可以配置只发现某些服务如下示例 origin引擎默认使用读取所有结点配置的进行确认结点有哪些Service。引擎也支持动态服务发现的方式支持etcd与origin类型具体请参照【配置说明】部分Node结点可以配置只发现某些服务如下示例
@@ -979,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使用
----------------------- -----------------------

View File

@@ -1,15 +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"
"errors"
"reflect"
) )
var configDir = "./config/" var configDir = "./config/"
@@ -113,22 +113,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) {
@@ -230,7 +230,6 @@ func (cls *Cluster) serviceDiscoverySetNodeInfo(nodeInfo *NodeInfo) {
} }
} }
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)
@@ -251,7 +250,7 @@ func (cls *Cluster) Init(localNodeId string, setupServiceFun SetupServiceFun) er
//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
@@ -315,7 +314,6 @@ func GetRpcClient(nodeId string, serviceMethod string,filterRetire bool, clientL
} }
serviceName := serviceMethod[:findIndex] serviceName := serviceMethod[:findIndex]
//1.找到对应的rpcNodeid
return GetCluster().GetNodeIdByService(serviceName, clientList, filterRetire) return GetCluster().GetNodeIdByService(serviceName, clientList, filterRetire)
} }
@@ -340,7 +338,7 @@ 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)
@@ -403,7 +401,7 @@ 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{}{}
} }
@@ -423,7 +421,7 @@ func GetNodeByTemplateServiceName(templateServiceName string) map[string]string
return nil return nil
} }
for nodeId,_ := range mapNode { for nodeId := range mapNode {
mapNodeId[serviceName] = nodeId mapNodeId[serviceName] = nodeId
} }
} }
@@ -435,7 +433,6 @@ func (cls *Cluster) GetGlobalCfg() interface{} {
return cls.globalCfg return cls.globalCfg
} }
func (cls *Cluster) ParseGlobalCfg(cfg interface{}) error { func (cls *Cluster) ParseGlobalCfg(cfg interface{}) error {
if cls.globalCfg == nil { if cls.globalCfg == nil {
return errors.New("no service configuration found") return errors.New("no service configuration found")

View File

@@ -1,6 +1,5 @@
package cluster package cluster
import ( import (
"github.com/duanhf2012/origin/v2/event" "github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
@@ -11,19 +10,18 @@ import (
"go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/client/v3"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
"time" "time"
"context" "context"
"errors" "errors"
"fmt" "fmt"
"go.uber.org/zap"
"path" "path"
"runtime"
"strings" "strings"
"sync/atomic" "sync/atomic"
"io/ioutil"
"crypto/x509"
"crypto/tls"
) )
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
@@ -44,11 +42,16 @@ type EtcdDiscoveryService struct {
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
@@ -91,21 +94,50 @@ func (ed *EtcdDiscoveryService) OnInit() error {
} }
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
var tlsConfig *tls.Config
if etcdDiscoveryCfg.EtcdList[i].Cert != "" {
// load cert
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 := ioutil.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,
}
}
client, err = clientv3.New(clientv3.Config{
Endpoints: etcdDiscoveryCfg.EtcdList[i].Endpoints, Endpoints: etcdDiscoveryCfg.EtcdList[i].Endpoints,
DialTimeout: etcdDiscoveryCfg.DialTimeoutMillisecond, DialTimeout: etcdDiscoveryCfg.DialTimeoutMillisecond,
Logger: zap.NewNop(), Username: etcdDiscoveryCfg.EtcdList[i].UserName,
Password: etcdDiscoveryCfg.EtcdList[i].Password,
Logger: log.GetLogger().Logger,
TLS: tlsConfig,
}) })
if cerr != nil {
log.Error("etcd discovery init fail",log.ErrorAttr("err",cerr)) if err != nil {
return cerr log.Error("etcd discovery init fail", log.ErrorField("err", err))
return err
} }
ctx, _ := context.WithTimeout(context.Background(), time.Second*3) ctx, _ := context.WithTimeout(context.Background(), time.Second*3)
_, err = client.Leases(ctx) _, err = client.Leases(ctx)
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.Any("endpoint", etcdDiscoveryCfg.EtcdList[i].Endpoints), log.ErrorField("err", err))
return err return err
} }
@@ -130,7 +162,7 @@ func (ed *EtcdDiscoveryService) registerServiceByClient(client *clientv3.Client,
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
} }
@@ -140,7 +172,7 @@ func (ed *EtcdDiscoveryService) registerServiceByClient(client *clientv3.Client,
// 注册服务节点到 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
} }
@@ -148,7 +180,7 @@ func (ed *EtcdDiscoveryService) registerServiceByClient(client *clientv3.Client,
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
} }
@@ -168,7 +200,6 @@ 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
@@ -203,7 +234,7 @@ func (ed *EtcdDiscoveryService) retire() error{
// 注册服务节点到 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
} }
} }
@@ -230,10 +261,10 @@ 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)
} }
} }
@@ -288,12 +319,12 @@ func (ed *EtcdDiscoveryService) setNodeInfo(networkName string,nodeInfo *rpc.Nod
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))
} }
} }
} }
@@ -302,7 +333,7 @@ func (ed *EtcdDiscoveryService) getServices(client *clientv3.Client,etcdClient *
// 根据前缀获取现有的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
} }
@@ -325,11 +356,7 @@ func (ed *EtcdDiscoveryService) watchByClient(client *clientv3.Client,etcdClient
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)
errString := fmt.Sprint(r)
log.Dump(string(buf[:l]),log.String("error",errString))
ed.tryWatch(client, etcdClient) ed.tryWatch(client, etcdClient)
} }
}() }()
@@ -358,7 +385,7 @@ func (ed *EtcdDiscoveryService) setNode(netWorkName string,byteNode []byte) stri
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 ""
} }
@@ -497,7 +524,7 @@ func (ed *EtcdDiscoveryService) RPC_ServiceRecord(etcdServiceRecord *service.Etc
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 { if err != nil {
log.Error("etcd record fail,cannot grant lease",log.ErrorAttr("err",err)) log.Error("etcd record fail,cannot grant lease", log.ErrorField("err", err))
return errors.New("cannot grant lease") return errors.New("cannot grant lease")
} }
} }
@@ -506,14 +533,14 @@ func (ed *EtcdDiscoveryService) RPC_ServiceRecord(etcdServiceRecord *service.Etc
ctx, _ := context.WithTimeout(context.Background(), time.Second*3) ctx, _ := context.WithTimeout(context.Background(), time.Second*3)
_, err = client.Put(ctx, path.Join(originDir, etcdServiceRecord.RecordKey), etcdServiceRecord.RecordInfo, clientv3.WithLease(lg.ID)) _, err = client.Put(ctx, path.Join(originDir, etcdServiceRecord.RecordKey), etcdServiceRecord.RecordInfo, clientv3.WithLease(lg.ID))
if err != nil { if err != nil {
log.Error("etcd record fail,cannot put record",log.ErrorAttr("err",err)) log.Error("etcd record fail,cannot put record", log.ErrorField("err", err))
} }
return errors.New("cannot put record") return errors.New("cannot put record")
} }
_, err = client.Put(context.Background(), path.Join(originDir, etcdServiceRecord.RecordKey), etcdServiceRecord.RecordInfo) _, 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 put record", log.ErrorField("err", err))
return errors.New("cannot put record") return errors.New("cannot put record")
} }

View File

@@ -1,8 +1,8 @@
package cluster package cluster
import ( import (
"time"
"container/list" "container/list"
"time"
) )
type nodeTTL struct { type nodeTTL struct {
@@ -46,7 +46,7 @@ func (ns *nodeSetTTL) addAndRefreshNode(nodeId string){
} }
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 {

View File

@@ -14,7 +14,6 @@ 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"
@@ -147,16 +146,16 @@ 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) {
@@ -188,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
} }
@@ -208,7 +207,7 @@ 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)
@@ -259,14 +258,13 @@ 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
@@ -350,7 +348,6 @@ func (dc *OriginDiscoveryClient) ping(){
}) })
} }
func (dc *OriginDiscoveryClient) OnStart() { func (dc *OriginDiscoveryClient) OnStart() {
//2.添加并连接发现主结点 //2.添加并连接发现主结点
dc.addDiscoveryMaster() dc.addDiscoveryMaster()
@@ -381,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)
} }
@@ -391,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 {
@@ -474,7 +471,7 @@ func (dc *OriginDiscoveryClient) OnRelease(){
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))
} }
} }
} }
@@ -496,7 +493,7 @@ func (dc *OriginDiscoveryClient) OnRetire(){
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))
} }
} }
} }
@@ -616,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
} }

View File

@@ -1,22 +1,30 @@
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 {
@@ -44,7 +52,7 @@ 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 {
@@ -55,7 +63,6 @@ type NatsConfig struct {
type RpcMode struct { type RpcMode struct {
Typ string `json:"Type"` Typ string `json:"Type"`
Nats NatsConfig Nats NatsConfig
} }
type NodeInfoList struct { type NodeInfoList struct {
@@ -64,6 +71,38 @@ type NodeInfoList struct {
NodeList []NodeInfo NodeList []NodeInfo
} }
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 { func (d *DiscoveryInfo) getDiscoveryType() DiscoveryType {
return d.discoveryType return d.discoveryType
} }
@@ -89,7 +128,7 @@ func (d *DiscoveryInfo) setEtcd(etcd *EtcdDiscovery) error{
} }
if d.discoveryType != InvalidType { if d.discoveryType != InvalidType {
return fmt.Errorf("Repeat configuration of Discovery") return fmt.Errorf("repeat configuration of Discovery")
} }
//Endpoints不允许重复 //Endpoints不允许重复
@@ -130,7 +169,7 @@ func (d *DiscoveryInfo) setOrigin(originDiscovery *OriginDiscovery) error{
} }
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
} }
@@ -235,30 +274,33 @@ func (cls *Cluster) readLocalClusterConfig(nodeId string) (DiscoveryInfo, []Node
var discoveryInfo DiscoveryInfo var discoveryInfo DiscoveryInfo
var rpcMode RpcMode var rpcMode RpcMode
clusterCfgPath := strings.TrimRight(configDir, "/") + "/cluster" //读取任何文件,只读符合格式的配置,目录下的文件可以自定义分文件
fileInfoList, err := os.ReadDir(clusterCfgPath) err := filepath.Walk(configDir, func(path string, info fs.FileInfo, err error)error {
if err != nil { if info.IsDir() {
return discoveryInfo, nil,rpcMode, fmt.Errorf("Read dir %s is fail :%+v", clusterCfgPath, err) return nil
} }
//读取任何文件,只读符合格式的配置,目录下的文件可以自定义分文件 if err != nil {
for _, f := range fileInfoList { return err
if f.IsDir() == false { }
filePath := strings.TrimRight(strings.TrimRight(clusterCfgPath, "/"), "\\") + "/" + f.Name()
fileNodeInfoList, rerr := cls.ReadClusterConfig(filePath)
if rerr != nil { if !validConfigFile(info.Name()) {
return discoveryInfo, nil,rpcMode, fmt.Errorf("read file path %s is error:%+v", filePath, rerr) return nil
}
fileNodeInfoList, rErr := cls.ReadClusterConfig(path)
if rErr != nil {
return fmt.Errorf("read file path %s is error:%+v", path, rErr)
} }
err = cls.SetRpcMode(&fileNodeInfoList.RpcMode, &rpcMode) err = cls.SetRpcMode(&fileNodeInfoList.RpcMode, &rpcMode)
if err != nil { if err != nil {
return discoveryInfo, nil,rpcMode, err return err
} }
err = discoveryInfo.setDiscovery(&fileNodeInfoList.Discovery) err = discoveryInfo.setDiscovery(&fileNodeInfoList.Discovery)
if err != nil { if err != nil {
return discoveryInfo,nil,rpcMode,err return err
} }
for _, nodeInfo := range fileNodeInfoList.NodeList { for _, nodeInfo := range fileNodeInfoList.NodeList {
@@ -266,14 +308,19 @@ func (cls *Cluster) readLocalClusterConfig(nodeId string) (DiscoveryInfo, []Node
nodeInfoList = append(nodeInfoList, nodeInfo) 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("nodeid %s configuration error in NodeList", 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 {
@@ -288,36 +335,32 @@ func (cls *Cluster) readLocalClusterConfig(nodeId string) (DiscoveryInfo, []Node
} }
func (cls *Cluster) readLocalService(localNodeId string) error { func (cls *Cluster) readLocalService(localNodeId string) error {
clusterCfgPath := strings.TrimRight(configDir, "/") + "/cluster"
fileInfoList, err := os.ReadDir(clusterCfgPath)
if err != nil {
return fmt.Errorf("Read dir %s is fail :%+v", clusterCfgPath, err)
}
var globalCfg interface{} 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
} }
@@ -333,7 +376,7 @@ func (cls *Cluster) readLocalService(localNodeId string) error {
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
} }
@@ -349,12 +392,17 @@ func (cls *Cluster) readLocalService(localNodeId string) error {
} }
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
} }
//组合所有的配置 //组合所有的配置
@@ -384,13 +432,12 @@ 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 _, serviceName := range cls.localNodeInfo.ServiceList {
splitServiceName := strings.Split(serviceName, ":") splitServiceName := strings.Split(serviceName, ":")
if len(splitServiceName) == 2 { if len(splitServiceName) == 2 {
@@ -403,13 +450,17 @@ func (cls *Cluster) parseLocalCfg() {
cls.mapTemplateServiceNode[templateServiceName][serviceName] = struct{}{} cls.mapTemplateServiceNode[templateServiceName][serviceName] = struct{}{}
} }
if _, ok := cls.mapServiceNode[serviceName]; ok == false { if _, ok := cls.mapServiceNode[serviceName]; ok == false {
cls.mapServiceNode[serviceName] = make(map[string]struct{}) 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{}{} cls.mapServiceNode[serviceName][cls.localNodeInfo.NodeId] = struct{}{}
} }
return nil
} }
func (cls *Cluster) IsNatsMode() bool { func (cls *Cluster) IsNatsMode() bool {
@@ -442,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 {
@@ -466,7 +516,7 @@ func (cls *Cluster) GetNodeIdByTemplateService(templateServiceName string, rpcCl
for serviceName := range mapServiceName { for serviceName := range mapServiceName {
mapNodeId, ok := cls.mapServiceNode[serviceName] mapNodeId, ok := cls.mapServiceNode[serviceName]
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
@@ -490,7 +540,7 @@ func (cls *Cluster) GetNodeIdByService(serviceName string, rpcClientList []*rpc.
defer cls.locker.RUnlock() defer cls.locker.RUnlock()
mapNodeId, ok := cls.mapServiceNode[serviceName] mapNodeId, ok := cls.mapServiceNode[serviceName]
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

View File

@@ -26,6 +26,8 @@ type Concurrent struct {
} }
/* /*
OpenConcurrentByNumCPU 函数使用说明
cpuMul 表示cpu的倍数 cpuMul 表示cpu的倍数
建议:(1)cpu密集型 使用1 (2)i/o密集型使用2或者更高 建议:(1)cpu密集型 使用1 (2)i/o密集型使用2或者更高
*/ */
@@ -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
} }

View File

@@ -6,14 +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"
"context"
) )
var idleTimeout = int64(2 * time.Second) var idleTimeout = int64(2 * time.Second)
const maxTaskQueueSessionId = 10000 const maxTaskQueueSessionId = 10000
type dispatch struct { type dispatch struct {
@@ -56,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:
@@ -65,7 +66,7 @@ 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()
case <-d.cancelContext.Done(): case <-d.cancelContext.Done():
@@ -93,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]
@@ -161,20 +162,19 @@ 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() d.cancel()
breakFor: breakFor:
for { for {
select { select {
@@ -192,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,15 +51,13 @@ 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)
} }
}() }()
@@ -67,8 +65,8 @@ func (w *worker) exec(t *task) {
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,8 +8,10 @@ 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 ( const (
boolType valueType = 0 boolType valueType = 0
stringType valueType = 1 stringType valueType = 1
@@ -33,11 +35,9 @@ func (cmd *command) execute() error{
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 {

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{}
IntExt [2]int64
StringExt [2]string
AnyExt [2]any
ref bool ref bool
} }
var emptyEvent Event var emptyEvent Event
func (e *Event) Reset() { func (e *Event) Reset() {
*e = emptyEvent *e = emptyEvent
} }
@@ -134,7 +137,6 @@ func (handler *EventHandler) Init(processor IEventProcessor){
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
} }
@@ -212,10 +214,7 @@ 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))
} }
}() }()
@@ -243,4 +242,3 @@ func (processor *EventProcessor) castEvent(event IEvent){
proc.PushEvent(event) proc.PushEvent(event)
} }
} }

View File

@@ -10,16 +10,14 @@ const (
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_Gin_Event EventType = -13 Sys_Event_FrameTick EventType = -13
Sys_Event_FrameTick EventType = -14
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,161 +0,0 @@
package log
import (
"context"
"io"
"log/slog"
"path/filepath"
"runtime"
"runtime/debug"
"sync"
)
const defaultSkip = 7
type IOriginHandler interface {
slog.Handler
Lock()
UnLock()
SetSkip(skip int)
GetSkip() int
}
type BaseHandler struct {
addSource bool
w io.Writer
locker sync.Mutex
skip int
}
type OriginTextHandler struct {
BaseHandler
*slog.TextHandler
}
type OriginJsonHandler struct {
BaseHandler
*slog.JSONHandler
}
func (bh *BaseHandler) SetSkip(skip int){
bh.skip = skip
}
func (bh *BaseHandler) GetSkip() int{
return bh.skip
}
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,
})
textHandler.skip = defaultSkip
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,
})
jsonHandler.skip = defaultSkip
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(b.skip, pcs[:])
record.PC = pcs[0]
}
}

View File

@@ -1,523 +1,337 @@
package log package log
import ( import (
"context" "go.uber.org/zap"
"fmt" "go.uber.org/zap/zapcore"
"github.com/duanhf2012/origin/v2/util/bytespool" "gopkg.in/natefinch/lumberjack.v2"
jsoniter "github.com/json-iterator/go"
"io"
"log/slog"
"os" "os"
"path"
"path/filepath"
"runtime"
"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()
// levels
const (
LevelTrace = slog.Level(-8)
LevelDebug = slog.LevelDebug
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 OpenConsole *bool
LogPath string
sBuff Buffer FileName string
Skip int
LogLevel zapcore.Level
Encoder zapcore.Encoder
LogConfig *lumberjack.Logger
SugaredLogger *zap.SugaredLogger
CoreList []zapcore.Core
} }
type IoWriter struct { func SetLogger(logger *Logger) {
outFile io.Writer // destination for output if logger != nil {
writeBytes int64
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 GetDefaultHandler() IOriginHandler{
return gLogger.(*Logger).Slogger.Handler().(IOriginHandler)
}
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{ 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.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"))
} }
func Warning(msg string, args ...any){ return zapcore.NewJSONEncoder(encoderConfig)
gLogger.Warning(msg,args...)
} }
func Error(msg string, args ...any){ func GetTxtEncoder() zapcore.Encoder {
gLogger.Error(msg,args...) 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"))
} }
func Stack(msg string, args ...any){ return zapcore.NewConsoleEncoder(encoderConfig)
gLogger.Stack(msg,args...)
} }
func Dump(dump string, args ...any){ func getLogConfig() *lumberjack.Logger {
gLogger.Dump(dump,args...) return &lumberjack.Logger{
Filename: "",
MaxSize: 2048,
MaxBackups: 0,
MaxAge: 0,
Compress: false,
}
} }
func Fatal(msg string, args ...any){ func NewDefaultLogger() *Logger {
gLogger.Fatal(msg,args...) logger := Logger{}
logger.Encoder = GetJsonEncoder()
logger.LogConfig = getLogConfig()
logger.LogConfig.LocalTime = true
logger.Init()
return &logger
} }
func Close() { func (logger *Logger) SetLogLevel(level zapcore.Level) {
gLogger.Close() logger.LogLevel = level
} }
func ErrorAttr(key string,value error) slog.Attr{ func (logger *Logger) Enabled(zapcore.Level) bool {
if value== nil { return logger.stack
return slog.Attr{key, slog.StringValue("nil")}
} }
return slog.Attr{key, slog.StringValue(value.Error())} func (logger *Logger) Init() {
} if isSetLogger {
func String(key, value string) slog.Attr {
return slog.Attr{key, slog.StringValue(value)}
}
func Int(key string, value int) slog.Attr {
return slog.Attr{key, slog.Int64Value(int64(value))}
}
func Int64(key string, value int64) slog.Attr {
return slog.Attr{key, slog.Int64Value(value)}
}
func Int32(key string, value int32) slog.Attr {
return slog.Attr{key, slog.Int64Value(int64(value))}
}
func Int16(key string, value int16) slog.Attr {
return slog.Attr{key, slog.Int64Value(int64(value))}
}
func Int8(key string, value int8) slog.Attr {
return slog.Attr{key, slog.Int64Value(int64(value))}
}
func Uint(key string, value uint) slog.Attr {
return slog.Attr{key, slog.Uint64Value(uint64(value))}
}
func Uint64(key string, v uint64) slog.Attr {
return slog.Attr{key, slog.Uint64Value(v)}
}
func Uint32(key string, value uint32) slog.Attr {
return slog.Attr{key, slog.Uint64Value(uint64(value))}
}
func Uint16(key string, value uint16) slog.Attr {
return slog.Attr{key, slog.Uint64Value(uint64(value))}
}
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 coreList []zapcore.Core
defer logger.Slogger.Handler().(IOriginHandler).UnLock() if logger.OpenConsole == nil || *logger.OpenConsole {
core := zapcore.NewCore(logger.Encoder, zapcore.AddSync(os.Stdout), logger.LogLevel)
logger.sBuff.Reset() coreList = append(coreList, core)
logger.FormatHeader(&logger.sBuff,level,3)
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{}) { if logger.CoreList != nil {
logger.DoSPrintf(LevelTrace,a) coreList = append(coreList, logger.CoreList...)
}else if logger.LogPath != "" {
WriteSyncer := zapcore.AddSync(logger.LogConfig)
core := zapcore.NewCore(logger.Encoder, WriteSyncer, logger.LogLevel)
coreList = append(coreList, core)
} }
func (logger *Logger) SDebug(a ...interface{}) { core := zapcore.NewTee(coreList...)
logger.DoSPrintf(LevelDebug,a) logger.Logger = zap.New(core, zap.AddCaller(), zap.AddStacktrace(logger), zap.AddCallerSkip(1+logger.Skip))
logger.SugaredLogger = logger.Logger.Sugar()
} }
func (logger *Logger) SInfo(a ...interface{}) { func (logger *Logger) Debug(msg string, fields ...zap.Field) {
logger.DoSPrintf(LevelInfo,a) logger.Logger.Debug(msg, fields...)
} }
func (logger *Logger) SWarning(a ...interface{}) { func (logger *Logger) Info(msg string, fields ...zap.Field) {
logger.DoSPrintf(LevelWarning,a) logger.Logger.Info(msg, fields...)
} }
func (logger *Logger) SError(a ...interface{}) { func (logger *Logger) Warn(msg string, fields ...zap.Field) {
logger.DoSPrintf(LevelError,a) logger.Logger.Warn(msg, fields...)
} }
func STrace(a ...interface{}) { func (logger *Logger) Error(msg string, fields ...zap.Field) {
gLogger.DoSPrintf(LevelTrace,a) logger.Logger.Error(msg, fields...)
} }
func SDebug(a ...interface{}) { func (logger *Logger) StackError(msg string, args ...zap.Field) {
gLogger.DoSPrintf(LevelDebug,a) logger.stack = true
logger.Logger.Log(zapcore.ErrorLevel, msg, args...)
logger.stack = false
} }
func SInfo(a ...interface{}) { func (logger *Logger) Fatal(msg string, fields ...zap.Field) {
gLogger.DoSPrintf(LevelInfo,a) gLogger.stack = true
logger.Logger.Fatal(msg, fields...)
gLogger.stack = false
} }
func SWarning(a ...interface{}) { func Debug(msg string, fields ...zap.Field) {
gLogger.DoSPrintf(LevelWarning,a) gLogger.Logger.Debug(msg, fields...)
} }
func SError(a ...interface{}) { func Info(msg string, fields ...zap.Field) {
gLogger.DoSPrintf(LevelError,a) gLogger.Logger.Info(msg, fields...)
} }
func (logger *Logger) FormatHeader(buf *Buffer,level slog.Level,calldepth int) { func Warn(msg string, fields ...zap.Field) {
t := time.Now() gLogger.Logger.Warn(msg, fields...)
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=\"") func Error(msg string, fields ...zap.Field) {
buf.AppendString(t.Format("2006/01/02 15:04:05")) gLogger.Logger.Error(msg, fields...)
buf.AppendString("\"") }
logger.sBuff.AppendString(" level=")
logger.sBuff.AppendString(getStrLevel(level)) func StackError(msg string, fields ...zap.Field) {
logger.sBuff.AppendString(" source=") gLogger.stack = true
gLogger.Logger.Error(msg, fields...)
buf.AppendString(file) gLogger.stack = false
buf.AppendByte(':') }
buf.AppendInt(int64(line))
buf.AppendString(" msg=\"") 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,7 +8,7 @@ import (
"time" "time"
) )
var DefaultMaxHeaderBytes int = 1<<20 var DefaultMaxHeaderBytes = 1 << 20
type CAFile struct { type CAFile struct {
CertFile string CertFile string
@@ -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
@@ -81,7 +81,6 @@ func (slf *HttpServer) startListen() error {
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

@@ -24,7 +24,7 @@ type JsonProcessor struct {
unknownMessageHandler UnknownMessageJsonHandler unknownMessageHandler UnknownMessageJsonHandler
connectHandler ConnectJsonHandler connectHandler ConnectJsonHandler
disconnectHandler ConnectJsonHandler disconnectHandler ConnectJsonHandler
bytespool.IBytesMempool bytespool.IBytesMemPool
} }
type JsonPackInfo struct { type JsonPackInfo struct {
@@ -35,7 +35,7 @@ type JsonPackInfo struct {
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,14 +44,14 @@ 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{}, recyclerReaderBytes func(data []byte)) error { func (jsonProcessor *JsonProcessor) MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error {
pPackInfo := msg.(*JsonPackInfo) pPackInfo := msg.(*JsonPackInfo)
defer recyclerReaderBytes(pPackInfo.rawMsg) defer recyclerReaderBytes(pPackInfo.rawMsg)
v, ok := jsonProcessor.mapMsg[pPackInfo.typ] 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)
@@ -59,7 +59,9 @@ func (jsonProcessor *JsonProcessor ) MsgRoute(clientId string,msg interface{},re
} }
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 {
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
@@ -68,7 +70,7 @@ func (jsonProcessor *JsonProcessor) Unmarshal(clientId string,data []byte) (inte
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()
@@ -89,12 +91,12 @@ func (jsonProcessor *JsonProcessor) Marshal(clientId string,msg interface{}) ([]
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 {

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,26 +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{}, recyclerReaderBytes func(data []byte)) error { func (pbProcessor *PBProcessor) MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error {
pPackInfo := msg.(*PBPackInfo) pPackInfo := msg.(*PBPackInfo)
defer recyclerReaderBytes(pPackInfo.rawMsg) 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) {
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 {
@@ -83,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)
@@ -95,7 +95,7 @@ func (pbProcessor *PBProcessor) UnmarshalWithOutRelease(clientId string, data []
return &PBPackInfo{typ: msgType, msg: protoMsg, rawMsg: data}, 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)
@@ -118,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 {
@@ -139,7 +139,6 @@ func (pbProcessor *PBProcessor) UnknownMsgRoute(clientId string, msg interface{}
recyclerReaderBytes(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

@@ -15,6 +15,7 @@ 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
@@ -37,7 +38,7 @@ 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{}, recyclerReaderBytes func(data []byte)) 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)
@@ -46,7 +47,7 @@ func (pbRawProcessor *PBRawProcessor ) MsgRoute(clientId string, msg interface{}
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 {
@@ -58,7 +59,7 @@ func (pbRawProcessor *PBRawProcessor ) Unmarshal(clientId string,data []byte) (i
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)
@@ -90,7 +91,6 @@ func (pbRawProcessor *PBRawProcessor) UnknownMsgRoute(clientId string,msg interf
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)
} }

View File

@@ -1,18 +1,17 @@
package processor package processor
type IProcessor interface { type IProcessor interface {
// must goroutine safe // MsgRoute must goroutine safe
MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error MsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) error
//must goroutine safe // UnknownMsgRoute must goroutine safe
UnknownMsgRoute(clientId string, msg interface{}, recyclerReaderBytes func(data []byte)) 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)
} }
@@ -26,4 +25,3 @@ type IRawProcessor interface {
SetConnectedHandler(connectHandler RawConnectHandler) SetConnectedHandler(connectHandler RawConnectHandler)
SetDisConnectedHandler(disconnectHandler RawConnectHandler) SetDisConnectedHandler(disconnectHandler RawConnectHandler)
} }

View File

@@ -16,7 +16,7 @@ type TCPClient struct {
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
@@ -74,7 +74,7 @@ func (client *TCPClient) init() {
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))
@@ -82,7 +82,7 @@ func (client *TCPClient) init() {
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 {
@@ -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
} }
@@ -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()
@@ -156,4 +156,3 @@ func (client *TCPClient) Close(waitDone bool) {
client.wg.Wait() client.wg.Wait()
} }
} }

View File

@@ -1,169 +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) GetRecyclerReaderBytes() func (data []byte) {
bytePool := tcpConn.msgParser.IBytesMempool
return func(data []byte) {
bytePool.ReleaseBytes(data)
}
}
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
} }
@@ -76,7 +75,7 @@ func (p *MsgParser) Read(conn *TCPConn) ([]byte, error) {
// 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++ {
@@ -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,13 +1,13 @@
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 (
@@ -15,7 +15,6 @@ const(
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 //最大消息长度
@@ -28,7 +27,7 @@ type TCPServer struct {
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
@@ -43,6 +42,8 @@ func (server *TCPServer) Start() error{
if err != nil { if err != nil {
return err return err
} }
server.wgLn.Add(1)
go server.run() go server.run()
return nil return nil
@@ -51,7 +52,7 @@ func (server *TCPServer) Start() error{
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 {
@@ -74,7 +75,7 @@ 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))
@@ -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)) log.Info("accept fail", log.String("error", err.Error()), log.Duration("sleep time", tempDelay))
tempDelay = min(1*time.Second, 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"
@@ -67,13 +68,15 @@ 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()
wsConn := newWSConn(conn, handler.pendingWriteNum, handler.maxMsgLen, handler.messageType) conn.UnderlyingConn().(*net.TCPConn).SetLinger(0)
conn.UnderlyingConn().(*net.TCPConn).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 +95,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 +119,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)
@@ -155,6 +160,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,17 +9,19 @@ 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"
"os" "os"
"os/signal" "os/signal"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
"syscall" "syscall"
"time" "time"
"github.com/duanhf2012/origin/v2/util/sysprocess"
) )
var sig chan os.Signal var sig chan os.Signal
@@ -27,7 +29,6 @@ var nodeId string
var preSetupService []service.IService //预安装 var preSetupService []service.IService //预安装
var preSetupTemplateService []func() 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 var NodeIsRun = false
@@ -55,14 +56,12 @@ 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", -1, "<-logchannelcap num> Set log channel cap.", setLogChannelCapNum)
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()
} }
@@ -83,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
} }
@@ -110,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)
@@ -158,12 +157,14 @@ 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
} }
@@ -213,22 +214,25 @@ func initNode(id string) {
} }
//3.service初始化 //3.service初始化
log.Info("Start running server.")
service.Init() service.Init()
} }
func initLog() error { func initLog() error {
if log.LogPath == "" { logger := log.GetLogger()
setLogPath("./log") if logger.LogPath == "" {
} err := setLogPath("./log")
localnodeinfo := cluster.GetCluster().GetLocalNodeInfo()
filepre := fmt.Sprintf("%s_", localnodeinfo.NodeId)
logger, err := log.NewTextLogger(log.LogLevel,log.LogPath,filepre,true,log.LogChannelCap)
if err != nil { if err != nil {
fmt.Printf("cannot create log file!\n")
return err return err
} }
log.SetLogger(logger) }
localNodeInfo := cluster.GetCluster().GetLocalNodeInfo()
fileName := fmt.Sprintf("%s.log", localNodeInfo.NodeId)
logger.FileName = fileName
logger.LogConfig.Filename = filepath.Join(logger.LogPath, logger.FileName)
logger.Init()
return nil return nil
} }
@@ -240,7 +244,6 @@ func Start() {
} }
} }
func retireNode(args interface{}) error { func retireNode(args interface{}) error {
//1.解析参数 //1.解析参数
param := args.(string) param := args.(string)
@@ -265,12 +268,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)
@@ -328,34 +329,37 @@ func startNode(args interface{}) error {
myName, mErr := sysprocess.GetMyProcessName() myName, mErr := sysprocess.GetMyProcessName()
//当前进程名获取失败,不应该发生 //当前进程名获取失败,不应该发生
if mErr != nil { if mErr != nil {
log.Info("get my process's name is error",log.ErrorAttr("err", mErr)) 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.Info("repeat runs are not allowed",log.String("nodeId",strNodeId),log.Int("processId",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.监听程序退出信号&性能报告
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)
@@ -378,16 +382,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)
@@ -395,12 +403,19 @@ func Setup(s ...service.IService) {
} }
} }
func SetupTemplate(fs ...func()service.IService){ func SetupTemplateFunc(fs ...func() service.IService) {
for _, f := range fs { for _, f := range fs {
preSetupTemplateService = append(preSetupTemplateService, f) 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)
} }
@@ -424,11 +439,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.GetLogger().OpenConsole = &bOpenConsole
} else if strOpen == "true" { } else if strOpen == "true" {
log.OpenConsole = true bOpenConsole := true
log.GetLogger().OpenConsole = &bOpenConsole
} else { } else {
return errors.New("Parameter console error!") return errors.New("parameter console error")
} }
return nil return nil
} }
@@ -440,20 +457,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.GetLogger().LogLevel = zapcore.DebugLevel
case "info": case "info":
log.LogLevel = log.LevelInfo log.GetLogger().LogLevel = zapcore.InfoLevel
case "warning": case "warn":
log.LogLevel = log.LevelWarning log.GetLogger().LogLevel = zapcore.WarnLevel
case "error": case "error":
log.LogLevel = log.LevelError log.GetLogger().LogLevel = zapcore.ErrorLevel
case "stack": case "stackerror":
log.LogLevel = log.LevelStack log.GetLogger().LogLevel = zapcore.ErrorLevel
case "fatal": case "fatal":
log.LogLevel = log.LevelFatal log.GetLogger().LogLevel = zapcore.FatalLevel
default: default:
return errors.New("unknown level: " + strlogLevel) return errors.New("unknown level: " + strlogLevel)
} }
@@ -464,52 +479,33 @@ func setLogPath(args interface{}) error {
if args == "" { if args == "" {
return nil return nil
} }
logPath := strings.TrimSpace(args.(string))
log.LogPath = strings.TrimSpace(args.(string)) dir, err := os.Stat(logPath)
dir, err := os.Stat(log.LogPath) //这个文件夹不存在
if err == nil && dir.IsDir() == false { if err == nil && dir.IsDir() == false {
return errors.New("Not found dir " + log.LogPath) return errors.New("Not found dir " + 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.GetLogger().LogPath = logPath
return nil return nil
} }
func setLogSize(args interface{}) error { func setLogSize(args interface{}) error {
if args == "" {
return nil
}
logSize, ok := args.(int) logSize, ok := args.(int)
if ok == false { if ok == false {
return errors.New("param logsize is error") return errors.New("param logsize is error")
} }
if logSize == 0 {
log.LogSize = int64(logSize)*1024*1024
return nil return nil
} }
func setLogChannelCapNum(args interface{}) error { log.GetLogger().LogConfig.MaxSize = logSize
if args == "" {
return nil
}
logChannelCap,ok := args.(int)
if ok == false{
return errors.New("param logsize is error")
}
if logChannelCap == -1 {
return nil
}
log.LogChannelCap = logChannelCap
return nil return nil
} }

View File

@@ -2,19 +2,21 @@ 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) type ReportFunType func(name string, callNum int, costTime time.Duration, record *list.List)
var reportFunc ReportFunType = DefaultReportFunction var reportFunc ReportFunType = DefaultReportFunction
type Element struct { type Element struct {
@@ -23,6 +25,7 @@ type Element struct {
} }
type RecordType int type RecordType int
const ( const (
MaxOvertimeType = 1 MaxOvertimeType = 1
OvertimeType = 2 OvertimeType = 2
@@ -196,4 +199,3 @@ func Report() {
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,8 +20,6 @@ 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()
@@ -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,11 +2,11 @@ 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 (
@@ -29,10 +29,10 @@ type IWriter interface {
} }
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
@@ -43,8 +43,6 @@ type IRealClient interface {
Bind(server IServer) Bind(server IServer)
} }
type Client struct { type Client struct {
clientId uint32 clientId uint32
targetNodeId string targetNodeId string
@@ -54,7 +52,7 @@ type Client struct {
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,7 +66,6 @@ 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)
@@ -107,7 +104,7 @@ 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
} }
@@ -119,7 +116,7 @@ func (client *Client) processRpcResponse(responseData []byte) error{
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)
@@ -182,7 +178,7 @@ func (rc *Client) rawGo(nodeId string,w IWriter,timeout time.Duration,rpcHandler
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 {
@@ -198,7 +194,7 @@ func (rc *Client) rawGo(nodeId string,w IWriter,timeout time.Duration,rpcHandler
} }
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)
@@ -206,8 +202,8 @@ func (rc *Client) rawGo(nodeId string,w IWriter,timeout time.Duration,rpcHandler
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,14 +211,14 @@ 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)
@@ -236,7 +232,7 @@ func (rc *Client) asyncCall(nodeId string,w IWriter,timeout time.Duration,rpcHan
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 {
@@ -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} rpcCancel := RpcCancel{CallSeq: seq, Cli: client}
return rpcCancel.CancelRpc, nil return rpcCancel.CancelRpc, nil
} }
return emptyCancelRpc,nil
}

View File

@@ -8,7 +8,7 @@ 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时内部申请
@@ -19,6 +19,7 @@ type ICompressor interface {
} }
var compressor ICompressor var compressor ICompressor
func init() { func init() {
SetCompressor(&Lz4Compressor{}) SetCompressor(&Lz4Compressor{})
} }
@@ -56,7 +57,7 @@ func (lc *Lz4Compressor) CompressBlock(src []byte) (dest []byte, err error) {
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,7 +77,7 @@ 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))

View File

@@ -10,15 +10,15 @@ 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() {
@@ -31,7 +31,7 @@ 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) {
@@ -69,8 +69,7 @@ func (lc *LClient) Go(nodeId string,timeout time.Duration,rpcHandler IRpcHandler
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()()
//服务自我调用 //服务自我调用
@@ -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()()
//判断是否是同一服务 //判断是否是同一服务
@@ -111,21 +109,18 @@ func (lc *LClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpc
} }
//其他的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,14 +1,14 @@
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
@@ -17,13 +17,13 @@ type BaseServer struct {
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))
@@ -33,16 +33,16 @@ func (ls *BaseServer) myselfRpcHandlerGo(client *Client,handlerName string, serv
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)
@@ -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))
} }
} }
} }
@@ -127,7 +127,7 @@ 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!")
@@ -194,7 +194,7 @@ func (server *BaseServer) selfNodeRpcHandlerAsyncGo(timeout time.Duration,client
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 {
@@ -209,7 +209,7 @@ func (bs *BaseServer) processRpcRequest(data []byte,connTag string,wrResponse wr
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
@@ -245,7 +245,7 @@ func (bs *BaseServer) processRpcRequest(data []byte,connTag string,wrResponse wr
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 {
@@ -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 {

View File

@@ -1,13 +1,14 @@
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
@@ -28,7 +29,7 @@ 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) {
@@ -40,30 +41,30 @@ 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)})
} }
@@ -71,7 +72,7 @@ func (rc *NatsClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler I
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...)
@@ -81,10 +82,10 @@ func (rc *NatsClient) WriteMsg (nodeId string,args ...[]byte) error{
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,8 +1,8 @@
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"
) )
@@ -19,6 +19,7 @@ type NatsServer struct {
} }
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
@@ -31,7 +32,6 @@ func (ns *NatsServer) Start() error{
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) {
@@ -48,7 +48,7 @@ func (ns *NatsServer) Start() error{
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
} }
@@ -77,7 +77,7 @@ 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
} }
@@ -86,7 +86,7 @@ func (ns *NatsServer) WriteResponse(processor IRpcProcessor, nodeId string,servi
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) {
@@ -106,7 +106,7 @@ func (ns *NatsServer) WriteResponse(processor IRpcProcessor, nodeId string,servi
} }
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))
} }
} }

View File

@@ -1,9 +1,9 @@
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 {
@@ -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
@@ -56,7 +55,7 @@ func (slf *PBProcessor) MakeRpcRequest(seq uint64,rpcMethodId uint32,serviceMeth
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
} }
@@ -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,7 +35,7 @@ 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()
@@ -49,7 +49,7 @@ func (rc *RClient) Go(nodeId string,timeout time.Duration,rpcHandler IRpcHandler
_, 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
@@ -62,8 +62,8 @@ func (rc *RClient) RawGo(nodeId string,timeout time.Duration,rpcHandler IRpcHand
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)})
} }
@@ -74,10 +74,7 @@ func (rc *RClient) AsyncCall(nodeId string,timeout time.Duration,rpcHandler IRpc
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))
} }
}() }()
@@ -89,7 +86,7 @@ func (rc *RClient) Run() {
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
} }
@@ -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 = 32 const maxClusterNode int = 32
type FuncRpcClient func(nodeId string, serviceMethod string, filterRetire bool, client []*Client) (error, []*Client) 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())
@@ -66,7 +67,7 @@ type RpcHandler struct {
//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,6 +86,7 @@ type IDiscoveryServiceListener interface {
} }
type CancelRpc func() type CancelRpc func()
func emptyCancelRpc() {} func emptyCancelRpc() {}
type IRpcHandler interface { type IRpcHandler interface {
@@ -162,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)
@@ -181,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)
@@ -218,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))
} }
}() }()
@@ -240,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)
@@ -309,15 +310,17 @@ func (handler *RpcHandler) HandlerRpcRequest(request *RpcRequest) {
return return
} }
requestHanle := request.requestHandle requestHandle := request.requestHandle
returnValues := v.method.Func.Call(paramList) returnValues := v.method.Func.Call(paramList)
if len(returnValues) > 0 {
errInter := returnValues[0].Interface() errInter := returnValues[0].Interface()
if errInter != nil { if errInter != nil {
err = errInter.(error) 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))
} }
} }
@@ -347,7 +350,7 @@ 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))
@@ -370,7 +373,7 @@ func (handler *RpcHandler) CallMethod(client *Client,ServiceMethod string, param
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)
} }
@@ -437,7 +440,7 @@ func (handler *RpcHandler) goRpc(processor IRpcProcessor, bCast bool, nodeId str
err, pClientList := handler.funcRpcClient(nodeId, serviceMethod, false, pClientList) err, pClientList := handler.funcRpcClient(nodeId, serviceMethod, false, pClientList)
if len(pClientList) == 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))
} }
@@ -466,7 +469,7 @@ func (handler *RpcHandler) callRpc(timeout time.Duration,nodeId string, serviceM
pClientList := make([]*Client, 0, maxClusterNode) pClientList := make([]*Client, 0, maxClusterNode)
err, pClientList := 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 len(pClientList) <= 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)
@@ -512,9 +515,9 @@ func (handler *RpcHandler) asyncCallRpc(timeout time.Duration,nodeId string, ser
if len(pClientList) == 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)})
@@ -530,8 +533,7 @@ func (handler *RpcHandler) asyncCallRpc(timeout time.Duration,nodeId string, ser
} }
//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 {
@@ -590,7 +592,7 @@ func (handler *RpcHandler) RawGoNode(rpcProcessorType RpcProcessorType, nodeId s
pClientList := make([]*Client, 0, 1) pClientList := make([]*Client, 0, 1)
err, pClientList := handler.funcRpcClient(nodeId, serviceName, false, pClientList) err, pClientList := handler.funcRpcClient(nodeId, serviceName, false, pClientList)
if len(pClientList) == 0 || err != nil { if len(pClientList) == 0 || 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
} }
if len(pClientList) > 1 { if len(pClientList) > 1 {
@@ -635,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,12 +7,13 @@ 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 (
@@ -30,7 +31,7 @@ type IServer interface {
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)
@@ -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 {
@@ -130,7 +130,7 @@ 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
} }
@@ -141,7 +141,7 @@ func (agent *RpcAgent) WriteResponse(processor IRpcProcessor, connTag string, se
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) {
@@ -155,35 +155,34 @@ func (agent *RpcAgent) WriteResponse(processor IRpcProcessor, connTag string, se
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
m.ancestor.getBaseModule().(*Module).descendants[module.GetModuleId()] = module
log.Debug("Add module " + module.GetModuleName() + " completed") 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{}{}
@@ -278,7 +286,7 @@ 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,27 +1,24 @@
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"
"encoding/json"
) )
var timerDispatcherLen = 100000 var timerDispatcherLen = 100000
var maxServiceEventChannelNum = 2000000 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{})
@@ -69,8 +66,6 @@ type Service struct {
closeSig chan struct{} closeSig chan struct{}
} }
// DiscoveryServiceEvent 发现服务结点 // DiscoveryServiceEvent 发现服务结点
type DiscoveryServiceEvent struct { type DiscoveryServiceEvent struct {
IsDiscovery bool IsDiscovery bool
@@ -86,7 +81,6 @@ type EtcdServiceRecordEvent struct {
} }
type Empty struct { type Empty struct {
} }
func SetMaxServiceChannel(maxEventChannel int) { func SetMaxServiceChannel(maxEventChannel int) {
@@ -97,7 +91,6 @@ 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()
@@ -107,7 +100,7 @@ func (s *Service) OnSetup(iService IService){
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.")
} }
} }
@@ -151,7 +144,7 @@ func (s *Service) Start() {
s.startStatus = true s.startStatus = true
atomic.StoreInt32(&s.isRelease, 0) atomic.StoreInt32(&s.isRelease, 0)
var waitRun sync.WaitGroup var waitRun sync.WaitGroup
log.Info(s.GetName()+" service is running",) log.Info(s.GetName() + " service is running")
s.self.(IService).OnStart() s.self.(IService).OnStart()
for i := int32(0); i < s.goroutineNum; i++ { for i := int32(0); i < s.goroutineNum; i++ {
@@ -170,8 +163,8 @@ func (s *Service) run() {
defer s.wg.Done() defer s.wg.Done()
var bStop = false var bStop = false
concurrent := s.IConcurrent.(*concurrent.Concurrent) cr := s.IConcurrent.(*concurrent.Concurrent)
concurrentCBChannel := concurrent.GetCallBackChannel() concurrentCBChannel := cr.GetCallBackChannel()
for { for {
var analyzer *profiler.Analyzer var analyzer *profiler.Analyzer
@@ -179,13 +172,13 @@ func (s *Service) run() {
case <-s.closeSig: case <-s.closeSig:
bStop = true bStop = true
s.Release() s.Release()
concurrent.Close() cr.Close()
case cb := <-concurrentCBChannel: case cb := <-concurrentCBChannel:
concurrent.DoCallback(cb) cr.DoCallback(cb)
case ev := <-s.chanEvent: 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)
@@ -267,17 +260,16 @@ func (s *Service) SetName(serviceName string) {
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))
} }
}() }()
if atomic.AddInt32(&s.isRelease, -1) == -1 { if atomic.AddInt32(&s.isRelease, -1) == -1 {
s.self.OnRelease() 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() {
@@ -336,11 +328,11 @@ func (s *Service) OnStart(){
} }
func (s *Service) OnNodeConnEvent(ev event.IEvent) { func (s *Service) OnNodeConnEvent(ev event.IEvent) {
event := ev.(*rpc.RpcConnEvent) re := ev.(*rpc.RpcConnEvent)
if event.IsConnect { if re.IsConnect {
s.nodeConnLister.OnNodeConnected(event.NodeId) s.nodeConnLister.OnNodeConnected(re.NodeId)
} else { } else {
s.nodeConnLister.OnNodeDisconnect(event.NodeId) s.nodeConnLister.OnNodeDisconnect(re.NodeId)
} }
} }
@@ -354,11 +346,11 @@ func (s *Service) OnNatsConnEvent(ev event.IEvent){
} }
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)
} }
} }
@@ -417,7 +409,7 @@ func (s *Service) PushEvent(ev event.IEvent) error{
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
} }
@@ -442,6 +434,7 @@ func (s *Service) SetEventChannelNum(num int){
} }
} }
// 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 {

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.Error("Failed to initialize "+s.GetName()+" service",log.ErrorAttr("err",err)) log.Error("Failed to initialize "+s.GetName()+" service",log.ErrorField("err",err))
os.Exit(1) os.Exit(1)
} }
} }

View File

@@ -58,7 +58,7 @@ func (ft *FrameTimer) addTimerData(timerID FrameTimerID, frameNum FrameNumber, t
td.cb = cb td.cb = cb
td.idx = -1 td.idx = -1
td.tickerFrameNum = tickerFrameNum td.tickerFrameNum = tickerFrameNum
td.ctx = ctx
ft.mapTimer[timerID] = td ft.mapTimer[timerID] = td
return td return td
} }

View File

@@ -39,7 +39,7 @@ 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),
} }
} }
@@ -51,7 +51,7 @@ func (m *HttpClientModule) InitHttpClient(transport http.RoundTripper,timeout ti
} }
} }
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

@@ -75,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)
} }

View File

@@ -28,7 +28,6 @@ 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
@@ -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,13 +62,11 @@ 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
@@ -116,7 +113,7 @@ 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...)
} }
@@ -225,12 +222,12 @@ func query(slowDuration time.Duration,db dbControl,strQuery string, args ...inte
if checkArgs(args) != nil { if checkArgs(args) != nil {
log.Error("CheckArgs is error :%s", strQuery) log.Error("CheckArgs is error :%s", 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:%s", strQuery)
return &datasetList, fmt.Errorf("cannot connect database!") return &datasetList, fmt.Errorf("cannot connect database")
} }
TimeFuncStart := time.Now() TimeFuncStart := time.Now()
@@ -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
} }
@@ -295,12 +292,12 @@ func exec(slowDuration time.Duration,db dbControl,strSql string, args ...interfa
ret := &DBResult{} ret := &DBResult{}
if db == nil { if db == nil {
log.Error("cannot connect database:%s", strSql) log.Error("cannot connect database:%s", 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 :%s", strSql)
return ret, fmt.Errorf("CheckArgs is error!") return ret, fmt.Errorf("checkArgs is error")
} }
TimeFuncStart := time.Now() TimeFuncStart := time.Now()
@@ -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

@@ -6,11 +6,10 @@ import (
"github.com/duanhf2012/origin/v2/log" "github.com/duanhf2012/origin/v2/log"
"github.com/duanhf2012/origin/v2/service" "github.com/duanhf2012/origin/v2/service"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"log/slog" "io"
"net/http" "net/http"
"strings" "strings"
"time" "time"
"io"
) )
type IGinProcessor interface { type IGinProcessor interface {
@@ -69,28 +68,28 @@ func (gm *GinModule) eventHandler(ev event.IEvent) {
func (gm *GinModule) Start() { func (gm *GinModule) Start() {
gm.srv.Addr = gm.listenAddr gm.srv.Addr = gm.listenAddr
log.Info("http start listen", slog.Any("addr", gm.listenAddr)) log.Info("http start listen", log.Any("addr", gm.listenAddr))
go func() { go func() {
err := gm.srv.ListenAndServe() err := gm.srv.ListenAndServe()
if err != nil { if err != nil {
log.Error("ListenAndServe error", slog.Any("error", err.Error())) log.Error("ListenAndServe error", log.Any("error", err.Error()))
} }
}() }()
} }
func (gm *GinModule) StartTLS(certFile, keyFile string) { func (gm *GinModule) StartTLS(certFile, keyFile string) {
log.Info("http start listen", slog.Any("addr", gm.listenAddr)) log.Info("http start listen", log.Any("addr", gm.listenAddr))
go func() { go func() {
err := gm.srv.ListenAndServeTLS(certFile, keyFile) err := gm.srv.ListenAndServeTLS(certFile, keyFile)
if err != nil { if err != nil {
log.Fatal("ListenAndServeTLS error", slog.Any("error", err.Error())) log.Fatal("ListenAndServeTLS error", log.Any("error", err.Error()))
} }
}() }()
} }
func (gm *GinModule) Stop(ctx context.Context) { func (gm *GinModule) Stop(ctx context.Context) {
if err := gm.srv.Shutdown(ctx); err != nil { if err := gm.srv.Shutdown(ctx); err != nil {
log.Error("Server Shutdown", slog.Any("error", err)) log.Error("Server Shutdown", log.Any("error", err))
} }
} }
@@ -210,7 +209,7 @@ func (gm *GinModule) handleMethod(httpMethod, relativePath string, handlers ...S
select { select {
case <-ctx.Done(): case <-ctx.Done():
log.Error("GinModule process timeout", slog.Any("path", c.Request.URL.Path)) log.Error("GinModule process timeout", log.Any("path", c.Request.URL.Path))
c.AbortWithStatus(http.StatusRequestTimeout) c.AbortWithStatus(http.StatusRequestTimeout)
case <-chanWait: case <-chanWait:
} }

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,203 @@
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 //是否小端序
}
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
//3.设置解析处理器
ws.process.SetByteOrder(ws.wsCfg.LittleEndian)
ws.mapClient = make(map[string]*WSClient, ws.WSServer.MaxConnNum)
ws.WSServer.NewAgent = ws.NewWSClient
//4.设置网络事件处理
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
@@ -215,7 +214,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 +299,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 +349,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

View File

@@ -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,7 +84,7 @@ 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 string, 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 {
@@ -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)
} }
@@ -170,7 +170,7 @@ func (cs *CustomerSubscriber) subscribe() bool {
} }
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
} }

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()

View File

@@ -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 ", topic, " is error", log.ErrorAttr("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("collect name ", topic, " Marshal is error", log.ErrorAttr("err", err))
return nil, false return nil, false
} }
continue continue
@@ -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
} }
@@ -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

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
@@ -124,7 +124,7 @@ func (tr *TopicRoom) topicRoomRun() {
} }
// 2. 如果存档成功,并且有后续批次,则继续存档 // 2. 如果存档成功,并且有后续批次,则继续存档
if ret == true && len(stagingBuff) > 0 { if len(stagingBuff) > 0 {
continue continue
} }

View File

@@ -128,7 +128,7 @@ func (mp *MongoPersist) ReadCfg() error {
return nil return nil
} }
//启服从数据库加载 // OnStart 启服从数据库加载
func (mp *MongoPersist) OnStart() { func (mp *MongoPersist) OnStart() {
} }
@@ -171,7 +171,7 @@ func (mp *MongoPersist) loadFromDB(rankId uint64,rankCollectName string) error{
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
} }
@@ -222,7 +222,6 @@ func (mp *MongoPersist) OnEnterRank(rankSkip IRankSkip, enterData *RankData){
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()
@@ -245,13 +244,13 @@ func (mp *MongoPersist) OnChangeRankData(rankSkip IRankSkip, changeData *RankDat
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 {
@@ -272,7 +271,7 @@ func (mp *MongoPersist) persistCoroutine(){
continue continue
} }
if mp.JugeTimeoutSave() == false{ if mp.JudgeTimeoutSave() == false {
continue continue
} }
@@ -420,7 +419,6 @@ func (mp *MongoPersist) removeRankDataToDB(mapRemoveRankData map[uint64]map[uint
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
@@ -17,7 +17,6 @@ type IRankSkip interface {
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) //进入排行

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,11 +8,10 @@ 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"
) )
type TcpService struct { type TcpService struct {
@@ -25,6 +24,7 @@ type TcpService struct {
} }
type TcpPackType int8 type TcpPackType int8
const ( const (
TPT_Connected TcpPackType = 0 TPT_Connected TcpPackType = 0
TPT_DisConnected TcpPackType = 1 TPT_DisConnected TcpPackType = 1
@@ -40,19 +40,19 @@ type TcpPack struct {
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)
@@ -94,9 +94,7 @@ func (tcpService *TcpService) OnInit() error{
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) {
@@ -116,19 +114,18 @@ func (tcpService *TcpService) TcpEventHandler(ev event.IEvent) {
func (tcpService *TcpService) recyclerReaderBytes(data []byte) { func (tcpService *TcpService) recyclerReaderBytes(data []byte) {
} }
func (tcpService *TcpService) SetProcessor(process processor.IProcessor, handler event.IEventHandler) { func (tcpService *TcpService) SetProcessor(process processor.IProcessor, handler event.IEventHandler) {
tcpService.process = process tcpService.process = process
tcpService.RegEventReceiverFunc(event.Sys_Event_Tcp, handler, tcpService.TcpEventHandler) tcpService.RegEventReceiverFunc(event.Sys_Event_Tcp, handler, tcpService.TcpEventHandler)
} }
func (tcpService *TcpService) NewClient(conn *network.TCPConn) network.Agent { 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
@@ -142,10 +139,7 @@ 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))
} }
}() }()
@@ -158,7 +152,7 @@ func (slf *Client) Run() {
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)
@@ -183,7 +177,7 @@ func (tcpService *TcpService) SendMsg(clientId string,msg interface{}) error{
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()
@@ -210,10 +204,10 @@ func (tcpService *TcpService) Close(clientId string) {
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 ""
} }
@@ -221,13 +215,12 @@ func (tcpService *TcpService) GetClientIp(clientid string) string{
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)
@@ -238,13 +231,12 @@ func (tcpService *TcpService) SendRawData(clientId string,data []byte) error{
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)
@@ -252,14 +244,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,9 +7,9 @@ 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"
) )
type WSService struct { type WSService struct {
@@ -22,6 +22,7 @@ type WSService struct {
} }
type WSPackType int8 type WSPackType int8
const ( const (
WPT_Connected WSPackType = 0 WPT_Connected WSPackType = 0
WPT_DisConnected WSPackType = 1 WPT_DisConnected WSPackType = 1
@@ -50,12 +51,12 @@ 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)
@@ -79,8 +80,7 @@ func (ws *WSService) OnInit() error{
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) {
@@ -129,7 +129,7 @@ func (slf *WSClient) Run() {
for { for {
bytes, err := slf.wsConn.ReadMsg() bytes, err := slf.wsConn.ReadMsg()
if err != nil { if err != nil {
log.Debug("read client id %s 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)
@@ -148,27 +148,27 @@ func (slf *WSClient) OnClose(){
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 %s 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
} }

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,33 +40,33 @@ 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
} }

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

@@ -39,7 +39,7 @@ 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

@@ -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

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

View File

@@ -1,12 +1,12 @@
package srand package srand
import ( import (
"github.com/duanhf2012/origin/v2/util/typedef" "github.com/duanhf2012/origin/v2/util/typ"
"math/rand" "math/rand"
"slices" "slices"
) )
func Sum[E ~[]T, T typedef.Number](arr E) T { func Sum[E ~[]T, T typ.Number](arr E) T {
var sum T var sum T
for i := range arr { for i := range arr {
sum += arr[i] sum += arr[i]
@@ -14,7 +14,7 @@ func Sum[E ~[]T, T typedef.Number](arr E) T {
return sum return sum
} }
func SumFunc[E ~[]V, V any, T typedef.Number](arr E, getValue func(i int) T) T { func SumFunc[E ~[]V, V any, T typ.Number](arr E, getValue func(i int) T) T {
var sum T var sum T
for i := range arr { for i := range arr {
sum += getValue(i) sum += getValue(i)
@@ -39,16 +39,17 @@ func RandN[E ~[]T, T any](arr E, num int) []T {
} }
Shuffle(index) Shuffle(index)
if len(index) > num { if len(index) > num {
index = index index = index[:num]
} }
ret := make([]T, 0, len(index)) ret := make([]T, 0, len(index))
for i := range index { for i := range index {
ret = append(ret, arr[index[i]]) ret = append(ret, arr[index[i]])
} }
return ret return ret
} }
func RandWeight[E ~[]T, T typedef.Integer](weights E) int { func RandWeight[E ~[]T, T typ.Integer](weights E) int {
totalWeight := Sum(weights) totalWeight := Sum(weights)
if totalWeight <= 0 { if totalWeight <= 0 {
return -1 return -1
@@ -64,7 +65,7 @@ func RandWeight[E ~[]T, T typedef.Integer](weights E) int {
return -1 return -1
} }
func RandWeightFunc[E ~[]U, U any, T typedef.Integer](arr E, getWeight func(i int) T) int { func RandWeightFunc[E ~[]U, U any, T typ.Integer](arr E, getWeight func(i int) T) int {
weights := make([]T, 0, len(arr)) weights := make([]T, 0, len(arr))
for i := range arr { for i := range arr {
weights = append(weights, getWeight(i)) weights = append(weights, getWeight(i))
@@ -72,7 +73,7 @@ func RandWeightFunc[E ~[]U, U any, T typedef.Integer](arr E, getWeight func(i in
return RandWeight(weights) return RandWeight(weights)
} }
func Get[E ~[]T, T any, U typedef.Integer](arr E, index U) (ret T, ok bool) { func Get[E ~[]T, T any, U typ.Integer](arr E, index U) (ret T, ok bool) {
if index < 0 || int(index) >= len(arr) { if index < 0 || int(index) >= len(arr) {
return return
} }
@@ -81,7 +82,7 @@ func Get[E ~[]T, T any, U typedef.Integer](arr E, index U) (ret T, ok bool) {
return return
} }
func GetPointer[E ~[]T, T any, U typedef.Integer](arr E, index U) *T { func GetPointer[E ~[]T, T any, U typ.Integer](arr E, index U) *T {
if index < 0 || int(index) >= len(arr) { if index < 0 || int(index) >= len(arr) {
return nil return nil
} }

View File

@@ -28,8 +28,6 @@ func (pool *Pool) Get() interface{}{
default: default:
return pool.syncPool.Get() return pool.syncPool.Get()
} }
return nil
} }
func (pool *Pool) Put(data interface{}) { func (pool *Pool) Put(data interface{}) {
@@ -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,7 +26,6 @@ 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 //是否关闭
@@ -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))
} }
}() }()
@@ -175,7 +167,7 @@ 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")
}

View File

@@ -1,25 +0,0 @@
package typedef
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
}