liangdas / mqant Goto Github PK
View Code? Open in Web Editor NEWmqant是一款基于Golang语言的简洁,高效,高性能的分布式微服务框架
License: Apache License 2.0
mqant是一款基于Golang语言的简洁,高效,高性能的分布式微服务框架
License: Apache License 2.0
gate应该处理(MESSAGE_TYPE_DISCONNECT=14)消息,并且需要区分是客户端正常断开连接还是进程被杀死的情况。
Hi,
不好意思,又是我
目前项目这种包管理的方式不太方便,也容易引起一些问题.Golang自1.5后提供了比较方便的vendor进行项目的包管理,也是类似与将依赖加入到项目目录下,了解一下
另外,官方的包管理工具dep也很好用
[mqant_agent.go:94]Read login pack error%!<EXTRA *errors.errorString=IDentifier Rejected length is:36>
github.com/lingdas/mqant/gate/base/mqant_agent.go 94
github.com/lingdas/mqant/network/tcp_server.go:95
每个客户端连接上来 会开两个协程 去接收客户端信息和 向客户端写入信息,但客户端断开之后 这两个协程不会关闭,造成内存浪费
如标题
能不能和你交流一下?
mqantserver编译成功,但运行出错。是不是配置文件问题?
[-] [-] [] [E] nats agent: nats: no servers available for connection
2019-05-16T16:20:30.229879+08:00 [-] [-] [development] [W] [log.go:79] result chan closed
github.com/liangdas/mqant/log/log.go:79
github.com/liangdas/mqant/selector/cache/cache.go:288
runtime/asm_amd64.s:1337
2019-05-16T16:20:30.230067+08:00 [-] [-] [development] [W] [log.go:79] result chan closed
github.com/liangdas/mqant/log/log.go:79
github.com/liangdas/mqant/selector/cache/cache.go:288
runtime/asm_amd64.s:1337
2019-05-16T16:20:30.230128+08:00 [-] [-] [development] [W] [log.go:79] result chan closed
github.com/liangdas/mqant/log/log.go:79
github.com/liangdas/mqant/selector/cache/cache.go:288
runtime/asm_amd64.s:1337
2019/05/16 16:20:30 [ERR] consul.watch: Watch (type: services) errored: Get http://127.0.0.1:8500/v1/catalog/services: dial tcp 127.0.0.1:8500: connect: connection refused, retry in 5s
2019/05/16 16:20:35 [ERR] consul.watch: Watch (type: services) errored: Get http://127.0.0.1:8500/v1/catalog/services: dial tcp 127.0.0.1:8500: connect: connection refused, retry in 20s
2019/05/16 16:20:55 [ERR] consul.watch: Watch (type: services) errored: Get http://127.0.0.1:8500/v1/catalog/services: dial tcp 127.0.0.1:8500: connect: connection refused, retry in 45s
x
就我所找到的教程包括wiki和example,wiki里的介绍太分散了,没有系统性,就每个小模块可能都说了,但是没有把他们穿起来
然后example虽然有,但一下就那么复杂不理解为何要如此
建议:
写一个入门教程,就一步步怎么把example写出来,每一步用意是什么(不需要现在的example那么复杂的,只需要把各个模块都用一下就好了,实现一个聊天室功能就OK了
rpc/base/redis_server.go#28
call_chan chan mqrpc.CallInfo 为啥没有接收channel的地方,是没实现吗
amqp 也是,没看太懂 😆
找到了 🤣
你好,
我本来是想找个go 的 mqtt server,但是发现很多都是要么不维护,要么很臃肿,我想代码控制,自己来处理这个框架,所以找到这个开源库,但是一直找不到mqtt相关代码,希望可以协助
记录的还是日志文件的名字和行号,而不是记录日志当前的文件名和行号,如下面
I] [log.go:69] This service ProcessID is
基于做游戏的业务需求,PHP 会使用对应的异步协程框架,Nodejs 也是如此。
而在 Swoole 的基础上,IO 层面是可以追赶 Go 的。
希望能更正基准测试,以及更理性的评测:
仅对我熟悉的两个领域做出上述评论。
刚入手此框架,发现框架对应用的入**大
例如,配置文件读取,简单看了下源代码,读取配置时如果没有给定参数,就从AppDir/bin/conf/server.json读取,无法在code时覆盖这个默认路径,就导致要不每次运行都要带上这串参数,要么就用给定的默认config位置,显得有些不灵活了
这几天首次使用MQANT提供的RPC,发现不支持可变长参数。
如果注册的RPC使用了可变长参数,那么调用时可能会出现如下打印
The number of params %s [%d] is not adapted.%s [%d]
检查了代码,在
func (s *RPCServer) runFunc(callInfo mqrpc.CallInfo, callbacks chan<- mqrpc.CallInfo) 函数中有如下判断
if len(params) != f.Type().NumIn() {
//因为在调研的 _func的时候还会额外传递一个回调函数 cb
_errorCallback(callInfo.RpcInfo.Cid, fmt.Sprintf("The number of params %s [%d] is not adapted.%s [%d]", params, len(params), f.String(), f.Type().NumIn()), nil)
return
}
由此可见,可变长参数是不支持的。
我简单修改了一下,
if f.Type().IsVariadic() {
if len(params) < f.Type().NumIn() {
_errorCallback(callInfo.RpcInfo.Cid, fmt.Sprintf("1 The number of params %s [%d] is more than .%s [%d]", params, len(params), f.String(), f.Type().NumIn()), nil)
return
}
} else {
if len(params) != f.Type().NumIn() {
//因为在调研的 _func的时候还会额外传递一个回调函数 cb
_errorCallback(callInfo.RpcInfo.Cid, fmt.Sprintf("The number of params %s [%d] is not adapted.%s [%d]", params, len(params), f.String(), f.Type().NumIn()), nil)
return
}
}
目前这样的修改是能满足我的需求。不知道群主有什么好的建议。
PS:不用可变长参数的话,可以直接使用一个string类型做参数,在调用RPC前后,在程序中通过json编解码要传递的参数,然后再转成string,只是感觉这样有点麻烦
请问两台或者更多不同地域的服务器,然后A服务器分别域名是a.xx.com ,B服务器域名是b.xx.com 。然而怎样通过c.xx.com自动分配连接上a或b的mqtt?
和pomelo ,kbengine, scut相比有什么优点。如果现在没有,将来计划会有什么优点吗?
或者在某些游戏类型上有什么显著优点。或者这个框架更偏向skynet?
请问连上后一直不操作,例如不进行登陆验证。怎样在30或者60秒内踢它下线啊?现在我试到是连上后就算没操作都是一直连着的。
目前使用room.GetUsableTable()來配桌
但是在mqantserver中有說到目前這方法還不智能
若要更改,請問要重哪裡下手呢?
只有中文不大好吧,至少得有个英文版,是吧。
mqant 正常執行一段時間後
會跳出 NatsServer error with 'nats: invalid subscription'
請問為什麼會出現該問題 ?
若將gate網關模塊與其他模塊拆開後
gate重啟後,會出現 [nats_client.go:179] rpc callback no found : [2f54c3de-63da-4b9d-8fdc-7d816d50c151]
的問題造成 無法與其他模塊溝通
這部分需修改那些地方 在重啟時重新註冊RPC
執行robot測試Xaxb時,會出現
[unified_send_message_table.go:187] SendBatch error Gate001 The number of params 76af5dae5d20d45b,d9ea7c0ca55872b9 XaXb/OnStop [{"Coin":100000,"Rid":"","SeatIndex":0,"SitDown":true,"Stake":false,"Target":0,"Weight":0},{"Coin":100000,"Rid":"","SeatIndex":1,"SitDown":true,"Stake":false,"Target":0,"Weight":0}] is not adapted.<func(log.TraceSpan, string, string, []uint8) (int64, string) Value>
請問是哪裡出錯,使用mqantserver檔案,並未修改任何程式
原先是做端游,初入H5游戏开发,发现了这个仓库,很棒!
游戏框架的逻辑我学习了下,有个疑问,当出现负载问题的时候,如何进行动态扩容呢?
我的设想是做一系列的H5游戏,一个游戏启动一个docker,N个游戏N个docker,有一个网关负责分配用户到特定的游戏docker里,当不足的时候进行扩容,然后有一个GM端可以进行管理,但总觉得怪怪的,不知道这个你有什么指导的么?
golang提供的单元测试很强大,也很实用
一方面,修改了代码,可以立刻跑一个单元测试,跑通再提交,以减少bug
另一方面,新手学习的时候test文件也是一个非常好的example
(我刚发现real分支有v2.0.0了,但是,没有文档一脸懵逼。。。如果这个时候有个test文件,就非常舒适了
附上一个简单的在mqant v1.8.0(master分支最新代码)下的一个login module的test片段:
func TestLogin(t *testing.T) {
// 先创建一个服务器
conf.LoadConfig("../bin/conf/server.json")
app := mqant.CreateApp(true, conf.Conf) //只有是在调试模式下才会在控制台打印日志, 非调试模式下只在日志文件中输出日志
app.AddRPCSerialize(common.RPCParamWegateResponseMarshalType, new(common.ResponseSerializer))
//app.Route("Chat",ChatRoute)
go app.Run(
wgate.Module(), //这是默认网关模块,是必须的支持 TCP,websocket,MQTT协议
login.Module(), //这是用户登录验证模块
)
time.Sleep(time.Second) // 小睡1秒等待mqant启动完成
// -------------- 开始测试逻辑 --------------
w := Work{}
opts := w.GetDefaultOptions("tcp://127.0.0.1:3563")
opts.SetConnectionLostHandler(func(client MQTT.Client, err error) {
fmt.Println("ConnectionLost", err.Error())
})
opts.SetOnConnectHandler(func(client MQTT.Client) {
fmt.Println("OnConnectHandler")
})
err := w.Connect(opts)
if err != nil {
panic(err)
}
// 未登陆情况下注销
// 期望:返回RetCodeUnauthorized
resp, err := w.Request("Login/HD_Logout", []byte(`{}`))
if err != nil {
t.Fatalf("Login/HD_Logout error: %+v", err)
}
if resp.Ret != common.RetCodeUnauthorized {
t.Fatalf("not login yet, func(logout) shoud return RetCodeUnauthorized(401), but now is %v with Msg: %s", resp.Ret, resp.Msg)
}
// 用户、密码为nil情况下登陆
// 期望:返回RetCodeBadRequest
resp, err = w.Request("Login/HD_Login", []byte(`{}`))
if err != nil {
t.Fatalf("Login/HD_Login error: %+v", err)
}
if resp.Ret != common.RetCodeBadRequest {
t.Fatalf("login with empty info, shoud return RetCodeBadRequest(400), but now is %v with Msg: %s", resp.Ret, resp.Msg)
}
// 正常登陆
// 期望:返回RetCodeOK
resp, err = w.Request("Login/HD_Login", []byte(`{"username":"abc","password":"test"}`))
if err != nil {
t.Fatalf("Login/HD_Login error: %+v", err)
}
if resp.Ret != common.RetCodeOK {
t.Fatalf("login with empty info, shoud return RetCodeOK(200), but now is %v with Msg: %s", resp.Ret, resp.Msg)
}
// 登陆后再登陆
// 期望:返回RetCodeBadRequest
resp, err = w.Request("Login/HD_Login", []byte(`{"username":"abc","password":"test"}`))
if err != nil {
t.Fatalf("Login/HD_Login error: %+v", err)
}
if resp.Ret != common.RetCodeBadRequest {
t.Fatalf("login with empty info, shoud return RetCodeBadRequest(400), but now is %v with Msg: %s", resp.Ret, resp.Msg)
}
// 正常注销
// 期望:返回RetCodeOK
resp, err = w.Request("Login/HD_Logout", []byte(`{}`))
if err != nil {
t.Fatalf("Login/HD_Logout error: %+v", err)
}
if resp.Ret != common.RetCodeOK {
t.Fatalf("not login yet, func(logout) shoud return RetCodeOK(200), but now is %v with Msg: %s", resp.Ret, resp.Msg)
}
// 已注销的情况下注销
// 期望:返回RetCodeUnauthorized
resp, err = w.Request("Login/HD_Logout", []byte(`{}`))
if err != nil {
t.Fatalf("Login/HD_Logout error: %+v", err)
}
if resp.Ret != common.RetCodeUnauthorized {
t.Fatalf("not login yet, func(logout) shoud return RetCodeUnauthorized(401), but now is %v with Msg: %s", resp.Ret, resp.Msg)
}
}
使用mqant2X库,在mqantserver编译出错
gate/CustomAgent.go:113:26: this.gate.GetMinStorageHeartbeat undefined (type gate.Gate has no field or method GetMinStorageHeartbeat)
gate/CustomAgent.go:116:72: cannot use this.GetSession().GetUserId() (type string) as type gate.Session in argument to this.gate.GetStorageHandler().Heartbeat:
string does not implement gate.Session (missing Bind method)
gate/module.go:53:29: cannot use gate (type *Gate) as type gate.StorageHandler in argument to gate.Gate.SetStorageHandler:
*Gate does not implement gate.StorageHandler (wrong type for Delete method)
have Delete(string) error
want Delete(gate.Session) error
gate/module.go:54:11: gate.Gate.SetTracingHandler undefined (type basegate.Gate has no field or method SetTracingHandler)
當在執行一段時間後,用戶一直掛在伺服器上
心跳一直都有監測到,但突然會出現以下錯誤
[mqtt.go:593] No Find Pack(0) length(0) github.com/liangdas/mqant/gate/base/mqtt/mqtt.go:593 github.com/liangdas/mqant/gate/base/mqtt_agent.go:90 github.com/liangdas/mqant/network/tcp_server.go:95 runtime/asm_amd64.s:1333
請問大神可否幫小弟解惑一下
請問在 配置差异當中有提到現在會自動註冊 module id
若有多組module (ex. XaXb部屬兩個)
想請問現在 client端
連進來後會導向到哪台,要如何指定
還是 v2
並不需要指定,會自動分配loading??
rpc_server里面每一个注册的Go函数都启动一个新的gorountine,为什么不用chan的方式启动固定个数rountine呢?
另外,demo示例中使用的无锁队列有严重bug,当get请求远大于put请求时,容量计算会错误,导致卡死。
看文档里不少地方出现关于2x版本的描述,但是release里并没有2x版本,是因为还没开发好吗?
我觉的2x版本的服务注册和发现才是趋势,现在的1.x方式配置管理复杂,不太友好.
还有文档略零散,想看关于分布式部署还得摸代码。
你好,我想单独使用网关模块,应用在智能家居里面,是否可以指点一二?
现在go都使用go.mod来管理依赖包了,顺便也支持下go.mod呗。
建议更新一下新手聊天室项目
许多依赖都找不到路径,下载不下来,折腾好久太痛苦了
Hi! I encounter a problem these days when I run mqant clients in JS.
in function var ClientImpl = function (uri, host, port, path, clientId)
// "line 746" of mqttws31.js
if (!("localStorage" in global && global["localStorage"] !== null)) {
global.localStorage = util.localStorage;
global.localStorage.init();
//var localStorage = Storage();
//throw new Error(format(ERROR.UNSUPPORTED, ["localStorage"]));
//global.localStorage = new Storage();
}
It throw a error "localStorage is not supported".
So I decide to use a simple map to replace localStorage (including setItem & getItem and so on)
But after successfully send a message to the server, the simulator throws a info and disable the connect.
"Simulator: <no filename="filename">:0:null is not a function"
How should I handle this problem? Or mqtt/mqant for JS just supports web game/app instand of other platform? Thanks in advance.
测试publish稍微大点的数据(字符串过千)的时候,会出现非常长的超时。调试代码发现wc_conn中的read可能有问题,导致chan等待。当然,注释也写了goroutine不安全。哈哈。
// goroutine not safe
func (wsConn *WSConn) Read(p []byte) (n int, err error) {
err = <-wsConn.buf_lock //等待写入数据
if err != nil {
//读取数据出现异常了
return
}
if wsConn.buffer.Len() == 0 {
//再等一次
err = <-wsConn.buf_lock //等待写入数据
if err != nil {
//读取数据出现异常了
return
}
}
return wsConn.buffer.Read(p)
}
依赖的Redigo项目迁移,旧项目已经不再维护
From
https://github.com/garyburd/redigo
to
https://github.com/gomodule/redigo
在編譯mqantserver時,會發生session.GetUserid undefined和session.TracCarrier undefined 等許多錯誤
请问
具体需要修改哪些内容?
src
|-client
|-mqtt_chat_client.py 聊天客户端 Python版本
|-webclient.go
缺少 webclient.go 文件。。。。。
失去响应之后,除非从任务管理器强制关闭,关闭之后,服务器后报一个
[E] [mqtt_agent.go:94] Read login pack error%!<EXTRA *net.OpError=read tcp 127.0.0.1:3563->127.0.0.1:2701: wsarecv: An existing connection was forcibly close by remote host.>
github.com/liangdas/mqant/gate/base/matt_agent.go:94
github.com/liangdas/mqant/network/tcp_server.go:95
runtime/asm_amd64.s:2197
[I] [module.go:62]客户端断开了连接。
这个打印,是在强制关闭Untiy之后才打印的。client.Connect():的话 服务器没有任何打印。
有劳大神解答一下。多谢。
附上部分代码:
public void OnClickLogin()
{
Connect();
}
public void Connect()
{
string qos = "2";
string topic = "MqttConnectServer";
string client_id = "HelloWorld";
int publishCount = 1;
MqttQos Qos = ParseQos(qos);
using (var pers = new InMemoryPersistence())
{
var client = new MqttClient(topic, client_id, Qos, publishCount, pers);
while (!client.Finished)
{
try
{
**client.Run();**
}
catch (Exception ex)
{
Console.WriteLine("{0} : {1}", client_id, ex.ToString());
}
Thread.Sleep(TimeSpan.FromSeconds(1));
}
}
}
==========================
Client.Run的处理
var connArgs = new MqttConnectionArgs()
{
ClientId = this.ClientId,
Hostname = "127.0.0.1",
Port = 3563,
Secure = true,
CleanSession = false
};
using (var conn = new MqttConnection(connArgs, persistence))
{
**conn.Connect(); // 到这一步 Unity就失去响应了,VS也不继续向下运行。**
Console.WriteLine("{0} connected", ClientId);
try
{
BindEvents(conn);
if(!conn.IsSessionPresent)
{
Subscribe(conn);
}
while(conn.Loop(PollLimit) && !Finished)
{
conn.Publish("HD_Login", Encoding.UTF8.GetBytes("Hello world!"));
if (!conn.IsPublishing)
{
PublishNext(conn);
}
}
}
finally
{
UnbindEvents(conn);
}
}
}
執行一段時間後 觸發
[mqtt_agent.go:205] Gate OnRecover error [the work queue is full!]
請問是有哪邊需要調整嗎?
请问 mqant 保证消息的Qos吗
是否 Qos 设为 2 还是会存在丢失消息的可能?
consule已经把 github.com/hashicorp/consul/watch包已到了github.com/hashicorp/consul/api/watch
导致我们变异不过,麻烦更新下
您好,請問mqant有方法可以調用conf/server.json自行設定的數值嗎?
mqant客户端无法集成到cocos creator中,能否提供一个cocos creator版的mqant client
我在啟動mqant後,時常會遇到該問題,請問有可能是什麼問題呢?
Gate rpc func(Push) error reflect: call of reflect.Value.Interface on zero Value
----Stack----
goroutine 184 [running]:
modules/mqant/rpc/base.(*RPCServer).runFunc.func3.1(0xc0003d2300, 0xc0001e42a0, 0xc000278c40, 0xc0001c9e30)
D:/HonorIT/src/shihray/HonorServer/src/modules/mqant/rpc/base/rpc_server.go:282 +0x129
panic(0xa335c0, 0xc000278ee0)
C:/Go/src/runtime/panic.go:513 +0x1c7
reflect.valueInterface(0x0, 0x0, 0x0, 0xa29901, 0xa06d01, 0xc0002a5100)
C:/Go/src/reflect/value.go:983 +0x1a7
reflect.Value.Interface(0x0, 0x0, 0x0, 0xa06d40, 0xc0002a4e10)
C:/Go/src/reflect/value.go:978 +0x4b
github.com/golang/protobuf/proto.makeMapMarshaler.func3(0xc00054c600, 0x183, 0x1f3, 0xc0004c23e0, 0x42, 0x4c7400, 0xc00054c600, 0x6d, 0x1f3, 0x0, ...)
D:/HonorIT/src/github.com/golang/protobuf/proto/table_marshal.go:2340 +0x2dd
github.com/golang/protobuf/proto.(*marshalInfo).marshal(0xc0003e2540, 0xc00054c600, 0x6d, 0x1f3, 0xc0004c2370, 0x4e500, 0x1000000009f5580, 0x0, 0x1f3, 0xc00054c600, ...)
D:/HonorIT/src/github.com/golang/protobuf/proto/table_marshal.go:270 +0x173
github.com/golang/protobuf/proto.(*InternalMes
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.