JMicro是一个用Java语言实现的开源微服务全家桶,
源码地址:https://github.com/mynewworldyyl/jmicro,
Demo地址:http://jmicro.cn/。
JMicro消息服务特性说明
今天向大家介绍基于JMicro实现的异步在线消息服务,其特点是免费,异步,多客户端支持,高性能,高可用。
现在网上很多宣称免费消息服务,其实到一定量后都是要收费的,但JMicro“不限量”免费,但是由于系统算力限制,不可能无限量大,所以JMicro系统默认为每秒最高50条消息,每条消息最大为8K二进制Byte。如果有需要更大的流量场景,可以在问题反馈里提单说明需求场景,我们评估通过后可适当增大流量(免费)。
客户端支持方面,目前支持Java客户端及JS WEB客户端,后面将陆续增加其他语言平台客户端。每种客户端都支持发布消息和订阅消息。比如可以用Java客户端发送消息,然后在Web客户端接收消息;或者在两个Web客户端之间相互发送或订阅消息,并且站在使用者的角度看就好像无后端服务器支持的消息通信,非常方便。
下面做个Demo,首先打开http://jmicro.cn页面并注册个账号,分别在两个页面登陆并打开消息测试页面,如下图:
在Chrome浏览器打开两个页面,登陆同一个账号或不同账号都可以,用账号登陆成功就行,如上两个页面都使用test01账号登陆。
左边框“发送主题”等于右边框“接收主题”,表示左边框发送消息给右边框,左边框的“订阅主题”等于右边框的“发送主题”,表示左边框接收右边框发送过来的消息。
在左右两个框分别点击“订阅”按钮后,按钮标题将变为“取消订阅”;
分别输入发送内容,并点击发送,将看到消息显示在对方的“接收消息”输出框中。
异步和高性能其实是一个整体,只有异步,才能做到快速的网络通信,而高性能的终极解决方案,基本上只有异步才能实现,了解一个单线程的Redis就会知道。值得一提的是JMicro是多线程的异步,是不是想想都激动!
JMIcro原生支持多主备份实例,所以支持高可用,这方面可以查看前面分享关于JMicro的文章。
JS API客户端Demo
纯JS样例:
http://jmicro.cn/testpubsub.html
源码地址:
https://github.com/mynewworldyyl/jmicro/blob/master/mng.web/public/testpubsub.html
Vue样例
按如下网址打开页面即可
Vue样例源码地址:
https://github.com/mynewworldyyl/jmicro/blob/master/mng.web/src/components/pubsub/JTestingPubsub.vue
JS API客户端使用
1. 首先注册JMicro账号
打开页面 http://jmicro.cn/ 右上角注册即可。注册时邮箱必须有效可用,后面要通过邮箱激活账号。手机号目前虽然没做实际验证,但后面不排除需要实名,所以建议填写真实有效手机号。
2. 引用JS文件
HTML文件头部引入JS,建议将此文件下载到本地引用,速度会快点
<script type="text/javascript" src="http://jmicro.cn/js/rpc.js"></script>
3. 初始化配置
$(function(){ jm.rpc.init("jmicro.cn",80); })
4.账号登陆
//actName账号,pwd密码
jm.rpc.login(actName,pwd,(rst,err)=>{ if(err) { alert(err); }else { //登陆成功 } });
5. 订阅消息
let topic = "/jmicro/test/topic01";
jm.ps.subscribe(topic,{},msgCallback) .then((rst)=>{ if(rst >= 0) { self.subState=true; $("#subscribe").text("Unsubscribe"); }else { console.log(rst); } });
msgCallback是接收消息函数,定义如下:
function msgCallback(msg) { if(!msg || msg.length == 0) { $("#msg").text("Pubsub topic is disconnected by server");
//出错,取消订阅 this.doSubscribe(); }else { let txt = $("#Result").text(); $("#Result").text(txt + " " + msg.data); } }
如果想取消订阅消息,则
let topic = "/jmicro/test/topic01" jm.ps.unsubscribe(topic,msgCallback) .then((succ)=>{ if(succ==true) { self.subState=false; $("#subscribe").text("Subscribe"); } else { console.log(succ); } });
6. 发送消息
let topic = "/jmicro/test/topic01" let content = "Hello jmicro pubsub servcie"; jm.ps.publishString(topic,content,false,false,null,null) .then(rst=>{ console.log(rst); }).catch(err=>{ console.log(err) });
以上发送一个字符串消息。
7. 对JS消息API简单说明
打开rpc.js文件,大概从1200行开始,有如下代码
//byteArray: 发送byte数组 //persist: 指示消息服务器是否持久化消息,如果为true,则持久化到数据库存储24小时,在24小时内可以通过消息历史记录页面查询到已经发送的消息。 //queue: 目前未使用 //callback: 接收消息发送结果主题,需要单独订阅此主题接收结果通知 //itemContext:每个消息都有一个上下文,有于存储消息相关的附加信息 publishBytes: function(topic, byteArray,persist,queue,callback,itemContext){ return this._publishItem(topic, byteArray,persist,queue,callback,itemContext); }, //发送字符串消息 publishString: function(topic,content,persist,queue,callback,itemContext){ return this._publishItem(topic, content,persist,queue,callback,itemContext); }, //通过消息服务器调用别外一个RPC方法,args为RPC方法的参数 callService: function (topic,args,persist,queue,callback,itemContext){ return this._publishItem(topic,args,persist,queue,callback,itemContext); }, //同时发送多个消息,psItems为消息数组 publishMultiItems: function (psItems){ return jm.rpc.callRpcWithParams(this.sn,this.ns,this.v,'publishMutilItems',[psItems]); }, //发送单个消息 publishOneItem: function (psItem){ return jm.rpc.callRpcWithParams(this.sn,this.ns,this.v,'publishOneItem',[psItem]); },
Java API使用用说明
样例源码地址:
https://github.com/mynewworldyyl/jmicro/tree/master/example/gatewayclientapp
1. POM中引用客户端Jar包
<dependency> <groupId>cn.jmicro</groupId> <artifactId>gateway.client</artifactId> <version>0.0.2-SNAPSHOT</version> </dependency>
如果报gateway.client Jar包下载失败,则需要配置一下Maven Settings文件,让其可以使用snapshot创库
<profiles> <profile> <id>dev</id> <repositories> <repository> <id>snapshots</id> <url>https://oss.sonatype.org/content/repositories/snapshots/</url> <releases> <enabled>false</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>public</id> <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </profile>
2 初始化客户端连接
//主题 private String TOPIC = "/jmicro/test/topic01"; //private ApiGatewayClient socketClient = new ApiGatewayClient(new ApiGatewayConfig(Constants.TYPE_HTTP,"jmicro.cn",80)); private ApiGatewayClient socketClient = new ApiGatewayClient(new ApiGatewayConfig(Constants.TYPE_SOCKET,"jmicro.cn",9092)); //账号名 private static final String ACT = "test01"; //密码 private static final String PWD = "1";
Java客户端支持SOCKET及HTTP连接类型,SOCKET支持长连接,可以支持消息订阅,而HTTP只支持发送,不支持订阅。
3.发送字符串消息
@Test public void testPublishString() { socketClient.loginJMAsync(ACT, PWD) .success((resp,cxt)->{ System.out.println("Success login: "+resp.getData().getActName()); .success((id,cxt0)->{ System.out.println("Publish result: "+id); }) .fail((code,msg,cxt1)->{ System.out.println("Fail pubilish content: code: "+ code + ", msg: " + msg); }); }) .fail((code,msg,cxt)->{ System.out.println("Fail login: code"+ code + ", msg: " + msg); }); Utils.getIns().waitForShutdown(); }
因为JMicro是基于异步的RPC,而消息服务是其中的一个应用,所以以上异步代码看起来不是很直观。
最外层的socketClient.loginJMAsync(ACT, PWD)表示登陆消息服务系统,其返回一个IPromise实例,通过其success接收登陆成功通知,fail接收登陆失败通知。
在success方法里面再调用
socketClient.getPubsubClient()
.publishStringJMAsync(TOPIC, "Message from java client!",PSData.FLAG_DEFALUT,null)
发送一个字符串消息,同样,publishStringJMAsync返回IPromise实例,同样有success和fail接收发送消息成功或失败通知。
最后一行Utils.getIns().waitForShutdown();表示让JVM等待,否则JVM直接退出,自然看不到消息发送结果。
4. 订阅消息
定义消息接收器
订阅消息必须有一个消息接收器,用于接收异步下发的消息,代码如下
PSDataListener lis = new PSDataListener() { int id = 0; @Override public void onMsg(PSData item) { System.out.println("Got message: " + item.getData().toString()); } @Override public int getSubId() { return id; } @Override public void setSubId(int id) { this.id = id; } };
主要在onMsg方法里接收消息,别的暂时不用理会。
开始订阅
socketClient.loginJMAsync(ACT, PWD) .success((resp,cxt)->{ System.out.println("Success login: "+resp.getData().getActName()); socketClient.getPubsubClient() .subscribeJMAsync(TOPIC, null, lis) .success((id,cxt0)->{ System.out.println("Subscribe success: "+id); }) .fail((code,msg,cxt1)->{ System.out.println("Fail to subscribe code: "+ code + ", msg: " + msg); }); }) .fail((code,msg,cxt)->{ System.out.println("Fail login: code"+ code + ", msg: " + msg); }); Utils.getIns().waitForShutdown();
和消息发送一样,最外层表示登陆,并在success方法调用订阅,返回的ID大于0表示订阅成功,小于或等于0表示订阅失败。
最后一行Utils.getIns().waitForShutdown()作用和发送消息相同。
你可以通过以上方式在Java与Web页面间反复测试两者之间消息发送与接收功能。
总结果:
JS及Java消息发送与接收是异步的,并且可以订阅消息发送结果通知,确保消息发送成功,以达到同步消息同样的效果;
JS及Java API编程风格基本上相同,都返回Promise接口实例,并在相应的Success及Fail方法接收结果;
实际上,你可以将Java客户端Jar放到支持Java的移动终端里面使用,实现两个无服务器支持的App之间发送接收消息;
基于JMicro消息服务,可以在任何系统之间做消息通信,即使一个没有任何服务器支持的两个HTML页面,也可以做网络通信,并且你不需要为此花费一分钱。
如果你在使用过程中有任何问题,可以在jmicro.cn问题反馈页面提单,我们技术人员有空就会及时回复,还希望你能在里面分享你的使用经验。
最后,如果JMicro项目确实帮助到你,希望你在到Gitgub上给个星
https://github.com/mynewworldyyl/jmicro
非常感谢!