在制定一個規模比較多大的聊天應用時,往往需要制定部署多個應用服務,其一可以保障服務的可靠性,其二可以增加使用者負載量.但制定這樣一種應用體系是一件複雜的事情,畢竟同一群體的使用者實際上會在不同的伺服器接入,這樣資訊轉發和處理就是一件比較麻煩的事情.但通過smartroute的訂閱機制這一系列的事情都變得簡單.
依據客觀情況在設計的時候一般都只是功能優先,對於大規模的應用往往是後期擴充套件.但是基於叢集擴充套件在設計上就需要做得很多工作作和規劃.然而使用smartroute則會變得非常簡單,因為並不需要在設計和規劃上做多餘的工作即可實現跨伺服器叢集互動.也許你感覺這是不太可能的事情,但以下示例會讓你感覺到smartroute的智慧之處.
對於以上場景設計需要考慮的事情比較多除了考慮節點和節點的通訊外,還需要考慮使用者所登陸的節點,訊息如何路由轉發和增加節點需要如何切入叢集等複雜技情況.而用smartroute不需要安裝任何服務和配置即可自動完成,接下來看下如果使用smartroute來解決一些看去都很複雜的工作.
叢集服務端實現
如是一開始上面架構規劃設計,那肯定是很複雜的工作,那加入smartroute後的設計到底怎樣呢?
private static IServer mServer; static void Main(string[] args) { Route.AddLogHandler(new ConsoleLogHandler(LogType.DEBUG | LogType.ERROR | LogType.FATAL | LogType.INFO | LogType.NONE | LogType.WARN)); Route.DefaultNode.Open(); mServer = ServerFactory.CreateTCP(); mServer.Handler = new Program(); mServer.Port = 8012; mServer.Open(); System.Threading.Thread.Sleep(-1); } public void Connect(Beetle.Express.IServer server, Beetle.Express.ChannelConnectEventArgs e) { TCPSubscribeHandler tcpsub = new TCPSubscribeHandler(); tcpsub.Channel = e.Channel; SmartRoute.Protocol.Packet packet = new SmartRoute.Protocol.Packet(); packet.Channel = e.Channel; packet.Receive = OnMessageReceive; e.Channel.Package = packet; Route.Subscribe(e.Channel.ID, tcpsub); } public void Disposed(Beetle.Express.IServer server, Beetle.Express.ChannelEventArgs e) { Route.UnSubscribe(e.Channel.ID); UnRegister ureg = new UnRegister(); ureg.IP = e.Channel.EndPoint.ToString(); ureg.Name = e.Channel.Name; ureg.SendTo(s => s.Mode(ReceiveMode.NotEq), e.Channel.ID); } private void OnMessageReceive(object sender, Beetle.Express.PackageReceiveArgs e) { IMessage message = (IMessage)e.Message; switch (message.MessageType) { case "Register": Register reg = message.GetBody<Register>(); e.Channel.Name = reg.Name; reg.IP = e.Channel.EndPoint.ToString(); reg.SendTo(s => s.Mode(ReceiveMode.All), e.Channel.ID); break; case "Speak": Speak speak = message.GetBody<Speak>(); speak.User = new Register(); speak.User.Name = e.Channel.Name; speak.User.IP = e.Channel.EndPoint.ToString(); speak.SendTo(s => s.Mode(ReceiveMode.NotEq), e.Channel.ID); break; } }
你沒有看錯,以上程式碼就是一個基於叢集的簡單聊天服務閘道器,看上去是不是比編寫一個普通網路程式的來得更簡單多.接下來講解一下主要程式碼的作用.
註冊訂閱
當閘道器接受到接入的時候會向節點註冊一個訂閱Route.Subscribe(e.Channel.ID, tcpsub);,而訂閱的ID則連線在當前服務的唯一標識,而訂閱實現是一個TCP連線訂閱.
取消訂閱
當閘道器接受到斷開的時候則取消訂閱 Route.UnSubscribe(e.Channel.ID);
傳送訊息
而當閘道器接收到訊息的情況則把訊息投遞出去,reg.SendTo(s => s.Mode(ReceiveMode.All), e.Channel.ID)是投遞給所有訂閱, speak.SendTo(s => s.Mode(ReceiveMode.NotEq), e.Channel.ID)則投遞給非當前Channel.ID的所有訂閱
智慧組建節點叢集
如果這個服在當前區域網內只執行一個例項,那它緊緊是一個普通的服務端,但如果節點發現網內還有其他節點在執行的情況下則會去發現對方並組建成通訊叢集.當組建叢集后每個節點的訂閱資訊都會同步到不同節點下,每個節點都是相互直連不存在中心服務.當一個節點接收一個訊息投遞的時候會找相應的訂閱,如果是本機訂閱則會直接呼叫訂閱;如果是訂閱在其他節點則把訊息投遞到相應的節點,由相應的節點呼叫訂閱.
單節點動行效果
多節點執行效果
一旦節點發現網內有其它節點就會發現組建叢集並同步訂閱,一叢集組建完成後就可以通過節點進行資訊互動.
總結
實際上一個聊天服務的功能並不這麼簡單,往往具備有大廳,群組等等.其實使用smartrote處理這些資訊轉發則是非常簡單的事情.可以針對大廳,群組制定訂閱服務節點;然後訊息傳送到相關訂閱,然後再由這些服務查詢出具體的訂閱使用者然後分發即可.所以smartrote的訂閱看上去是很簡的功能,實現上可以實現很多意想不到的功能,如FTP,HTTP和MQ等等訂閱的實現並註冊到smartroute中統一整合分發.