-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/dynamic bind: 增加DynamicBind工作池模式,类似于Bind工作池模式,每个连接绑定一个worker, 但不像Bind模式那样会闲置很多worker #339
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package main | ||
|
||
import ( | ||
"os" | ||
"os/signal" | ||
"time" | ||
|
||
"github.com/aceld/zinx/ziface" | ||
"github.com/aceld/zinx/zlog" | ||
"github.com/aceld/zinx/znet" | ||
) | ||
|
||
const ( | ||
PingType = 1 | ||
PongType = 2 | ||
) | ||
|
||
// ping response router | ||
type PongRouter struct { | ||
znet.BaseRouter | ||
client string | ||
} | ||
|
||
// Hash 工作模式下,需要等待接受到client1的pong后,才会收到client2和client3的pong | ||
// DynamicBind工作模式下,client2, client3 都会立马收到pong, 但client1的pong会被阻塞十秒后才收到 | ||
func (p *PongRouter) Handle(request ziface.IRequest) { | ||
//read server pong data | ||
zlog.Infof("---------client:%s, recv from server:%s, msgId=%d, data=%s ----------\n", | ||
p.client, request.GetConnection().RemoteAddr(), request.GetMsgID(), string(request.GetData())) | ||
} | ||
|
||
func onClient1Start(conn ziface.IConnection) { | ||
zlog.Infof("client1 connection start, %s->%s\n", conn.LocalAddrString(), conn.RemoteAddrString()) | ||
//send ping | ||
err := conn.SendMsg(PingType, []byte("Ping From Client1")) | ||
if err != nil { | ||
zlog.Error(err) | ||
} | ||
} | ||
|
||
func onClient2Start(conn ziface.IConnection) { | ||
zlog.Infof("client2 connection start, %s->%s\n", conn.LocalAddrString(), conn.RemoteAddrString()) | ||
//send ping | ||
err := conn.SendMsg(PingType, []byte("Ping From Client2")) | ||
if err != nil { | ||
zlog.Error(err) | ||
} | ||
} | ||
|
||
func onClient3Start(conn ziface.IConnection) { | ||
zlog.Infof("client3 connection start, %s->%s\n", conn.LocalAddrString(), conn.RemoteAddrString()) | ||
//send ping | ||
err := conn.SendMsg(PingType, []byte("Ping From Client3")) | ||
if err != nil { | ||
zlog.Error(err) | ||
} | ||
} | ||
|
||
func main() { | ||
//Create a client client | ||
client1 := znet.NewClient("127.0.0.1", 8999) | ||
client1.SetOnConnStart(onClient1Start) | ||
client1.AddRouter(PongType, &PongRouter{client: "client1"}) | ||
client1.Start() | ||
|
||
time.Sleep(time.Second) | ||
|
||
client2 := znet.NewClient("127.0.0.1", 8999) | ||
client2.SetOnConnStart(onClient2Start) | ||
client2.AddRouter(PongType, &PongRouter{client: "client2"}) | ||
client2.Start() | ||
|
||
time.Sleep(time.Second) | ||
|
||
client3 := znet.NewClient("127.0.0.1", 8999) | ||
client3.SetOnConnStart(onClient3Start) | ||
client3.AddRouter(PongType, &PongRouter{client: "client3"}) | ||
client3.Start() | ||
|
||
//Prevent the process from exiting, waiting for an interrupt signal | ||
signalChan := make(chan os.Signal, 1) | ||
signal.Notify(signalChan, os.Interrupt) | ||
<-signalChan | ||
client1.Stop() | ||
client2.Stop() | ||
client3.Stop() | ||
|
||
time.Sleep(time.Second) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"Name":"zinx server DynamicBind Mode Demo", | ||
"Host":"127.0.0.1", | ||
"TCPPort":8999, | ||
"MaxConn":12000, | ||
"WorkerPoolSize":1, | ||
"MaxWorkerTaskLen":50, | ||
"WorkerMode":"DynamicBind" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package main | ||
|
||
import ( | ||
"sync/atomic" | ||
"time" | ||
|
||
"github.com/aceld/zinx/ziface" | ||
"github.com/aceld/zinx/zlog" | ||
"github.com/aceld/zinx/znet" | ||
) | ||
|
||
func OnConnectionAdd(conn ziface.IConnection) { | ||
zlog.Debug("OnConnectionAdd:", conn.GetConnection().RemoteAddr()) | ||
} | ||
|
||
func OnConnectionLost(conn ziface.IConnection) { | ||
zlog.Debug("OnConnectionLost:", conn.GetConnection().RemoteAddr()) | ||
} | ||
|
||
type blockRouter struct { | ||
znet.BaseRouter | ||
} | ||
|
||
var Block = int32(1) | ||
|
||
// 模拟阻塞操作 | ||
func (r *blockRouter) Handle(request ziface.IRequest) { | ||
//read client data | ||
zlog.Infof("recv from client:%s, msgId=%d, data=%s\n", request.GetConnection().RemoteAddr(), request.GetMsgID(), string(request.GetData())) | ||
|
||
// 第一次处理时,模拟任务阻塞操作, Hash 模式下,后面的连接的任务得不到处理 | ||
// DynamicBind 模式下,看后面的连接的任务会得到即使处理,不会因为前面连接的任务阻塞而得不到处理 | ||
// 这里只模拟一次阻塞操作。 | ||
if atomic.CompareAndSwapInt32(&Block, 1, 0) { | ||
zlog.Infof("blockRouter handle start, msgId=%d, remote:%v\n", request.GetMsgID(), request.GetConnection().RemoteAddr()) | ||
time.Sleep(time.Second * 10) | ||
//阻塞操作结束 | ||
zlog.Infof("blockRouter handle end, msgId=%d, remote:%v\n", request.GetMsgID(), request.GetConnection().RemoteAddr()) | ||
} | ||
|
||
err := request.GetConnection().SendMsg(2, []byte("pong from server")) | ||
if err != nil { | ||
zlog.Error(err) | ||
return | ||
} | ||
zlog.Infof("send pong over, client:%s\n", request.GetConnection().RemoteAddr()) | ||
} | ||
|
||
func main() { | ||
s := znet.NewServer() | ||
|
||
s.SetOnConnStart(OnConnectionAdd) | ||
s.SetOnConnStop(OnConnectionLost) | ||
|
||
s.AddRouter(1, &blockRouter{}) | ||
|
||
s.Serve() | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 一旦关闭queue,不管什么模式下,worker都应该退出的,不然一直能从queue读到一个空的request。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
中,
TaskQueue: make([]chan ziface.IRequest, TaskQueueLen),
能否做zconf.GlobalObject.WorkerMode == zconf.WorkerModeDynamicBind
的区分,这样不会影响到之前的WorkerBind模式。There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jursonmo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TaskQueue 的长度 TaskQueueLen 已经有针对DynamicBind 模式的区分