概念解釋
什么是RPC(Remote Procedure Call)遠(yuǎn)程過程調(diào)用,是一種通過網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)程序上請(qǐng)求服務(wù),實(shí)現(xiàn)某個(gè)業(yè)務(wù),但是不需要具體了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議。t-io把程序中對(duì)外實(shí)現(xiàn)通信的各個(gè)協(xié)議模塊進(jìn)行了打包處理成一個(gè)盒子,上層應(yīng)用對(duì)外通信就只要對(duì)接盒子的接口,而不必關(guān)心盒子里面的內(nèi)容,RPC服務(wù)要對(duì)外實(shí)現(xiàn)遠(yuǎn)程調(diào)用,首先要跟t-io通信,再到遠(yuǎn)方的服務(wù)。
為什么要使用RPC呢?如果一個(gè)系統(tǒng)(例如,網(wǎng)站、大型應(yīng)用等)中內(nèi)部子系統(tǒng)較多、接口也非常多的情況下,采用RPC的好處就很明顯了,RPC中采用的長(zhǎng)鏈接,不必每次通信都要像有些協(xié)議一樣每次都要進(jìn)行3次握手來建立連接,例如,HTTP協(xié)議,這樣就能減少了網(wǎng)絡(luò)開銷;其次,就是RPC中一般都有注冊(cè)中心,而且有豐富的監(jiān)控管理模塊;應(yīng)用方要進(jìn)行發(fā)布、捆綁下線接口、動(dòng)態(tài)擴(kuò)展等,對(duì)調(diào)用方來說可以是無感知、歸一化的操作。而且RPC的安全性也很好。
可見RPC下面如果有一個(gè)非常高效的網(wǎng)絡(luò)編程框架配合,使用起來會(huì)很方便,由于t-io中內(nèi)置了socket、NIO功能,所以跟RPC對(duì)接具有天然的優(yōu)勢(shì),當(dāng)然也可以使用netty,但是netty的使用起來比t-io會(huì)復(fù)雜很多。
msg服務(wù)器介紹
企業(yè)集群版的t-io,已經(jīng)實(shí)現(xiàn)了msg服務(wù)器。自從有了集群服務(wù)器后,做rpc, 做msg都是很容易的事了!對(duì)于有RPC業(yè)務(wù)需求的老鐵又是一大福音。我自己開發(fā)的IM聊天工具譚聊中已經(jīng)驗(yàn)證的非常完美了。 廢話不多說,請(qǐng)看具體實(shí)現(xiàn)代碼。
示范代碼
DemoMessage.java
package org.tio.msg.demo;
import org.tio.msg.common.bs.msg.Message;
public class DemoMessage extends Message {
private static final long serialVersionUID = -985195945448439158L;
private String name = "hello tio message";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
DemoMessageListener.java
package org.tio.msg.demo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.msg.common.bs.msg.MessageListener;
import org.tio.utils.json.Json;
public class DemoMessageListener implements MessageListener<DemoMessage> {
private static Logger log = LoggerFactory.getLogger(DemoMessageListener.class);
public static final DemoMessageListener me = new DemoMessageListener();
@Override
public void onMessage(String fromCid, DemoMessage message) {
log.warn("收到Tio Message, fromCid[{}], Message:\r\n{}", fromCid, Json.toFormatedJson(message));
}
}
啟動(dòng)類TioMsgDemoStarter.java
package org.tio.msg.demo;
import java.sql.SQLException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.core.Node;
import org.tio.msg.client.MsgClientStarter;
import org.tio.msg.client.MsgApi;
import org.tio.msg.common.utils.JsonInit;
import org.tio.msg.common.utils.PropInit;
import org.tio.utils.jfinal.P;
/**
?* @author tanyaowu
?*/
public class TioMsgDemoStarter {
private static Logger log = LoggerFactory.getLogger(TioMsgDemoStarter.class);
public static MsgClientStarter cluClientStarter = null;
/**
* 基本的初始化,一般用于單元小測(cè)試
* @throws SQLException?
*/
public static void initBase() throws SQLException {
PropInit.init(new String[] { "app.properties" });
JsonInit.init();
}
/**
* @param args
* @author tanyaowu
*/
public static void main(String[] args) {
try {
initBase();
//啟動(dòng)tio cluster client
Node cluServerNode = new Node(P.get("tio.clu.server.ip"), P.getInt("tio.clu.server.port"));
cluClientStarter = new MsgClientStarter(false, null, cluServerNode, null);
cluClientStarter.start();
Thread.sleep(100L);//sleep一下,讓各連接的握手完成,實(shí)際項(xiàng)目中,一般不需要這樣
//添加listener
MsgApi.addListener(cluClientStarter.getClientTioConfig(), DemoMessage.class, DemoMessageListener.me);
for (int i =0; i < 1000; i++) {
//發(fā)布一個(gè)demo 消息
DemoMessage demoMessage = new DemoMessage();
demoMessage.setName("hello tio message " + i);
MsgApi.publish(cluClientStarter.getClientTioConfig(), demoMessage, true);
}
} catch (Throwable e) {
log.error("", e);
System.exit(1);
}
}
}
運(yùn)行
04-24 22:27:01 INFO? o.t.c.client.PacketDispatcher[102]
server:127.0.0.1:1982, client:0:0:0:0:0:0:0:0:13378 收到消息:MessageNtf
04-24 22:27:01 WARN? o.t.m.demo.DemoMessageListener[20]
收到Tio Message, fromCid[1385963494888697856], Message:
{
"name":"hello tio message"
}