1. 程式人生 > 其它 >SignalR 循序漸進(五)多個Hub伺服器下的訊息訂閱

SignalR 循序漸進(五)多個Hub伺服器下的訊息訂閱

SignalR的通訊方式決定了其高效能,但是即便如此,當訊息的併發量上來以後,單節點的Hub伺服器依然可能無法承載總的訊息吞吐量,那麼如何對Hub伺服器做水平擴充套件呢?

從微軟官方的文件上看,SignalR是具有訊息底板功能的,SignalR核心元件公開了一個IMessageBus的介面,只需要實現該介面,就能實現訊息訂閱功能。官網提供了3種解決方案:Azure、Redis、SqlServer,nuget平臺上有更多的基於訊息佇列的第三方底板。本篇以Redis為例子展示一下以訊息底板模式運作的Hub伺服器。

服務端

public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            
            GlobalHost.DependencyResolver.UseRedis("192.168.1.66", 6379, string.Empty, "SignalRBus");
            app.Map("/signalr", map =>
            {
                map.UseCors(CorsOptions.AllowAll);

                var hubConfiguration = new HubConfiguration
                {
                    EnableJSONP = true
                };
                map.RunSignalR(hubConfiguration);
            });
        }
    }

在啟動類中,通過DependencyResolver的擴充套件方法來註冊基於Redis的MessageBus,其中前2個引數是地址和埠,第三個引數為Redis伺服器的密碼,訊息訂閱的名稱。

public class ChatHub : Hub
    {
        public void Chat(string msg)
        {
            Clients.All.Display("Receive Msg:" + msg);
        }
    }

建立一個簡單的Hub,只提供一個Chat的方法,內部實現廣播。

static void Main(string[] args)
        {
            using (WebApp.Start<Startup>("http://*:8001/"))
            {
                Console.WriteLine("Server running at http://localhost:8001/");
                Console.ReadLine();
            }
        }
static void Main(string[] args)
        {
            using (WebApp.Start<Startup>("http://*:8002/"))
            {
                Console.WriteLine("Server running at http://localhost:8002/");
                Console.ReadLine();
            }
        }

建立2個啟動項,埠號分別為8001和8002,用以啟動2個hub的例項。

客戶端

static void Main(string[] args)
        {
            var hubConn = new HubConnection("http://localhost:8001");
            var proxy = hubConn.CreateHubProxy("ChatHub");
            hubConn.Start().Wait();
            while (true)
            {
                var guid = Guid.NewGuid().ToString();
                Console.WriteLine("Send Msg:" + guid);
                proxy.Invoke("Chat", guid).Wait();
                Thread.Sleep(2000);
            }

        }

客戶端1連線上8001,利用一個迴圈不斷的往服務端發guid。

static void Main(string[] args)
        {
            var hubConn = new HubConnection("http://localhost:8002");
            var proxy = hubConn.CreateHubProxy("ChatHub");
            proxy.On<string>("Display", (msg) => { Console.WriteLine(msg); });
            hubConn.Start().Wait();
            Console.ReadLine();
        }

客戶端2連線上8002,註冊一個Display的方法,用於接收服務端推送的訊息。

執行情況

圖中可知,client1的send msg,被client2接受到了。

 

SignalR的通訊方式決定了其高效能,但是即便如此,當訊息的併發量上來以後,單節點的Hub伺服器依然可能無法承載總的訊息吞吐量,那麼如何對Hub伺服器做水平擴充套件呢?

從微軟官方的文件上看,SignalR是具有訊息底板功能的,SignalR核心元件公開了一個IMessageBus的介面,只需要實現該介面,就能實現訊息訂閱功能。官網提供了3種解決方案:Azure、Redis、SqlServer,nuget平臺上有更多的基於訊息佇列的第三方底板。本篇以Redis為例子展示一下以訊息底板模式運作的Hub伺服器。

服務端

public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            
            GlobalHost.DependencyResolver.UseRedis("192.168.1.66", 6379, string.Empty, "SignalRBus");
            app.Map("/signalr", map =>
            {
                map.UseCors(CorsOptions.AllowAll);

                var hubConfiguration = new HubConfiguration
                {
                    EnableJSONP = true
                };
                map.RunSignalR(hubConfiguration);
            });
        }
    }

在啟動類中,通過DependencyResolver的擴充套件方法來註冊基於Redis的MessageBus,其中前2個引數是地址和埠,第三個引數為Redis伺服器的密碼,訊息訂閱的名稱。

public class ChatHub : Hub
    {
        public void Chat(string msg)
        {
            Clients.All.Display("Receive Msg:" + msg);
        }
    }

建立一個簡單的Hub,只提供一個Chat的方法,內部實現廣播。

static void Main(string[] args)
        {
            using (WebApp.Start<Startup>("http://*:8001/"))
            {
                Console.WriteLine("Server running at http://localhost:8001/");
                Console.ReadLine();
            }
        }
static void Main(string[] args)
        {
            using (WebApp.Start<Startup>("http://*:8002/"))
            {
                Console.WriteLine("Server running at http://localhost:8002/");
                Console.ReadLine();
            }
        }

建立2個啟動項,埠號分別為8001和8002,用以啟動2個hub的例項。

客戶端

static void Main(string[] args)
        {
            var hubConn = new HubConnection("http://localhost:8001");
            var proxy = hubConn.CreateHubProxy("ChatHub");
            hubConn.Start().Wait();
            while (true)
            {
                var guid = Guid.NewGuid().ToString();
                Console.WriteLine("Send Msg:" + guid);
                proxy.Invoke("Chat", guid).Wait();
                Thread.Sleep(2000);
            }

        }

客戶端1連線上8001,利用一個迴圈不斷的往服務端發guid。

static void Main(string[] args)
        {
            var hubConn = new HubConnection("http://localhost:8002");
            var proxy = hubConn.CreateHubProxy("ChatHub");
            proxy.On<string>("Display", (msg) => { Console.WriteLine(msg); });
            hubConn.Start().Wait();
            Console.ReadLine();
        }

客戶端2連線上8002,註冊一個Display的方法,用於接收服務端推送的訊息。

執行情況

圖中可知,client1的send msg,被client2接受到了。