Skip to content

Commit

Permalink
Merge branch 'master' into feature/aceld
Browse files Browse the repository at this point in the history
  • Loading branch information
aceld authored Dec 6, 2024
2 parents 0bcc1e1 + 59e7837 commit d0ac08f
Show file tree
Hide file tree
Showing 12 changed files with 295 additions and 38 deletions.
19 changes: 6 additions & 13 deletions README-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ Zinx 是一个基于Golang的轻量级并发服务器框架
---
## zinx源码地址
### Github
Git: https://github.com/aceld/zinx

### 码云(Gitee)
Git: https://gitee.com/Aceld/zinx
| platform | Entry |
| ---- | ---- |
|Github| https://github.com/aceld/zinx |
|Gitcode|https://gitcode.com/aceld/zinx|
|Gitee|https://gitee.com/Aceld/zinx|

### 官网
http://zinx.me
Expand Down Expand Up @@ -62,19 +62,12 @@ Zinx框架的项目制作采用编码和学习教程同步进行,将开发的

当然,最后希望Zinx会有更多的人加入,给我们提出宝贵的意见,让Zinx成为真正的解决企业的服务器框架!在此感谢您的关注!

### 来自chatGPT(AI)的回复
![什么是zinx](https://user-images.githubusercontent.com/7778936/209745655-7463be0d-1450-4a70-b201-6d9279935aff.jpg)
![zinx和其他库对比](https://user-images.githubusercontent.com/7778936/209745668-e6938534-113d-4465-a949-58328c4dca5c.jpg)

### zinx荣誉
#### 开源中国GVP年度最有价值开源项目
![GVP-zinx](https://s2.ax1x.com/2019/10/13/uvYVBV.jpg)



## 二、初探Zinx架构
![Zinx框架](https://user-images.githubusercontent.com/7778936/220058446-0ad45112-2225-4b71-b0d8-69a7f3cee5ca.jpg)

![1-Zinx框架.png](https://camo.githubusercontent.com/903d1431358fa6f4634ebaae3b49a28d97e23d77/68747470733a2f2f75706c6f61642d696d616765732e6a69616e7368752e696f2f75706c6f61645f696d616765732f31313039333230352d633735666636383232333362323533362e706e673f696d6167654d6f6772322f6175746f2d6f7269656e742f7374726970253743696d61676556696577322f322f772f31323430)
![流程图](https://github.com/wenyoufu/testaaaaaa/blob/abc8a50078a86aed37e8af6082d1d867bc165c32/%E6%9C%AA%E5%91%BD%E5%90%8D%E6%B5%81%E7%A8%8B%E5%9B%BE%20(1).jpg?raw=true)
![zinx-start](https://user-images.githubusercontent.com/7778936/126594039-98dddd10-ec6a-4881-9e06-a09ec34f1af7.gif)

Expand Down
23 changes: 5 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ Zinx is a lightweight concurrent server framework based on Golang.
---
## Source of Zinx
### Github
Git: https://github.com/aceld/zinx

### Gitee(China)
Git: https://gitee.com/Aceld/zinx
| platform | Entry |
| ---- | ---- |
|Github| https://github.com/aceld/zinx |
|Gitcode|https://gitcode.com/aceld/zinx|
|Gitee|https://gitee.com/Aceld/zinx|

### Website
http://zinx.me
Expand Down Expand Up @@ -62,19 +62,6 @@ The tutorials will be iterated version by version, with each version adding smal
Of course, we hope that more people will join Zinx and provide us with valuable feedback, enabling Zinx to become a truly enterprise-level server framework. Thank you for your attention!


### Reply from chatGPT(AI)
![what-is-zinx](https://user-images.githubusercontent.com/7778936/209745848-acfc14eb-74cd-4513-b386-8bc6e0bcc09f.png)

![compare-zinx](https://user-images.githubusercontent.com/7778936/209745864-7d8984b0-bd73-4109-b4ec-aec152f8f8e8.png)


### The honor of zinx
#### GVP Most Valuable Open Source Project of the Year at OSCHINA

![GVP-zinx](https://s2.ax1x.com/2019/10/13/uvYVBV.jpg)




## II. Zinx architecture
![Zinx框架](https://user-images.githubusercontent.com/7778936/220058446-0ad45112-2225-4b71-b0d8-69a7f3cee5ca.jpg)
Expand Down
89 changes: 89 additions & 0 deletions examples/zinx_dynamic_bind/client/client.go
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)
}
9 changes: 9 additions & 0 deletions examples/zinx_dynamic_bind/server/conf/zinx.json
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"
}
58 changes: 58 additions & 0 deletions examples/zinx_dynamic_bind/server/server.go
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()
}
8 changes: 8 additions & 0 deletions zconf/zconf.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ const (
const (
WorkerModeHash = "Hash" // By default, the round-robin average allocation rule is used.(默认使用取余的方式)
WorkerModeBind = "Bind" // Bind a worker to each connection.(为每个连接分配一个worker)

//Hash 模式有阻塞的问题(虽然有异步的方式可解决)。
//Bind 模式下,如果配置MaxConn值比较大的话 就会后台就会起很多worker在等着,当服务器接入连接较少时, 很多worker都是空闲; MaxConn 设置小的话,服务器能接入的连接就会受限。

//WorkerModeDynamicBind 也是一个连接对应一个worker, 给连接分配worker时, 如果工作池里初始化的worker已经用完了,就动态创建一个worker绑定到每个连接。这个临时创建的worker, 会在连接断开后销毁。
//跟WorkerModeHash的区别是,如果业务层回调有阻塞操作的话,也不影响其他连接的业务层处理。
//跟WorkerModeBind的区别是,不需要像Bind模式那样一开始就创建很多worker,而是根据连接数动态创建worker,这样可以避免闲置worker数量过多导致的资源浪费。
WorkerModeDynamicBind = "DynamicBind" // Dynamic binding of a worker to each connection when there is no worker in worker pool.(临时动态创建一个worker绑定到每个连接)
)

/*
Expand Down
9 changes: 8 additions & 1 deletion ziface/iclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

package ziface

import "time"
import (
"net/url"
"time"
)

type IClient interface {
Restart()
Expand Down Expand Up @@ -66,4 +69,8 @@ type IClient interface {
// Get the name of this Client
// 获取客户端Client名称
GetName() string

SetUrl(url *url.URL)

GetUrl() *url.URL
}
13 changes: 13 additions & 0 deletions znet/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/tls"
"fmt"
"net"
"net/url"
"time"

"github.com/aceld/zinx/zdecoder"
Expand All @@ -20,6 +21,7 @@ type Client struct {
Ip string
// Port of the target server to connect 目标链接服务器的端口
Port int
Url *url.URL // 扩展,连接时带上其他参数
// Client version tcp,websocket,客户端版本 tcp,websocket
version string
// Connection instance 链接实例
Expand Down Expand Up @@ -122,6 +124,9 @@ func (c *Client) Restart() {
switch c.version {
case "websocket":
wsAddr := fmt.Sprintf("ws://%s:%d", c.Ip, c.Port)
if c.Url != nil {
wsAddr = c.Url.String()
}

// Create a raw socket and get net.Conn (创建原始Socket,得到net.Conn)
wsConn, _, err := c.dialer.Dial(wsAddr, nil)
Expand Down Expand Up @@ -300,3 +305,11 @@ func (c *Client) SetName(name string) {
func (c *Client) GetName() string {
return c.Name
}

func (c *Client) SetUrl(url *url.URL) {
c.Url = url
}

func (c *Client) GetUrl() *url.URL {
return c.Url
}
Loading

0 comments on commit d0ac08f

Please sign in to comment.