㈠ 即时通讯IM系统开发
我于2014年开启即时通讯的开发之路,历经从服务端到客户端,从第三方到自研,经历过诸多的研发难题,都一一破解。现将经验总结如下,希望对行业内从事IM开发的程序员有所帮助。
①P2P方式
P2P方式多用于局域网内聊天,这种方式在有种种限制和不便。一方面它只适合在线的点对点消息传输,对离线,群组等支持不够。另一方面由于 NAT 的存在,使得不同局域网内机器互联难度大大上升,在某些网络类型(对称NAT)下无法建立连接。使用P2P方式的软件在启动后一般做两件事情:
1、进行UDP广播:发送自己信息和接受同局域网内其他端信息。
2、开启TCP监听:等待其他端进行连接。
②服务器中转方式
大部分的互联网IM产品都采用服务器中转这种方式进行消息传输,相对于P2P的方式,具有有以下的优点:
1、支持更多P2P无法支持或支持不好的业务,如离线消息,群组,聊天室。
2、方便业务逻辑的拓展和新旧版本的兼容,当然它也有自己的问题,就是服务器架构复杂,并发要求高。
通过以上的比较,建议我们在开发IM系统的时候使用服务器中转的方式。
IM的网络连接方式有基于TCP的长连接和基于HTTP短连接两种:
①基于TCP的长连接
基于TCP长连接则能够更好地支持大批量用户,问题是客户端和服务器的实现比较复杂。也有一些改进,比如下行使用MQTT进行服务器通知/消息的下发,上行使用HTTP短连接进行指令和消息的上传。这种方式能够保证下行消息/指令的及时性,但是在弱网络下上行慢的问题还是比较严重,早期的来往就是基于这种方式。
②基于HTTP短连接
常见于WEB IM系统(现在很多WEBIM都是基于WebSocket实现),它的优点是实现简单,方便开发上手,问题是流量大,服务器负载较大,消息及时性无法很好地保证,对大规模的用户量支持不够,适合小型的IM系统。
IM常见的协议有:XMPP,MQTT,私有协议。各种协议优缺点情况如下:
①XMPP协议
优点:协议开源,可拓展性强,在各个端(有各种语言的实现,对于前期入门级的开发者是很好的选择,方便进入IM开发的程序员快速上手。
缺点:XML表现力弱,有太多冗余信息,流量大。
常见案例:Gtalk、新浪微博、Facebook。
②MQTT协议
优点:协议简单,流量少。
缺点:不是一个专门为IM设计的协议,多使用于推送。
③私有协议
几乎所有主流的IM APP都是使用私有协议。
优点:高效,节约流量(一般使用二进制协议),安全性高,难以破解。
缺点:开发初期没有现有样列可以参考,对于参与IM开发的程序员的要求比较高。
常见案例:微信、钉钉。
根据以上的对比,我们得出结果,一个好的协议需要满足高效、简洁、节约流量、易于拓展等要求,同时又能够和当前的开发团队的技术堆栈匹配,不能选择一个他们很难上手的。
这里再提一下,我当时开发IM系统的时候,上手用的是XMPP,在使用的过程中发现了很多问题,踩了很多坑。
①实时性原则
消息实时到达接收方,如果用户在线,则消息实时到达,如果用户不在线,则消息在用户登录后到达。由于网络波动,以及移动端操作系统对应用前后台切换的管理,如何实现用户连接管理、消息实时推送,推送失败的处理方式,客户端重连机制,消息如何补齐等,都需要IM系统考虑。由于TCP开发略微复杂,早期的基于HTTP短轮询、长轮询的低效的技术方案,也无法达到实时性的要求。
②可靠性原则
是指我们经常听到的“消息送达”,通常用消息的不丢失和不重复两个技术指标来表示。可靠性是要确保消息被发送后,能够被接收者收到。由于网络环境的复杂性,以及用户在线的不确定性,消息的可靠性(不丢失、不重复)是IM系统的核心指标,也是IM系统实现中的难点之一。总体来说,IM系统的消息“可靠性”,通常就是指聊天消息投递的可靠性(准确的说,这个“消息”是广义的,因为还存用户看不见的各种指令和通知,包括但不限于进群退群通知、好友添加通知等,为了方便描述,统称“消息”)。
从消息发送者和接收者用户行为来讲,消息“可靠性”应该分为以下几种情况:
1、发送失败:对于这种情况要感知到,明确反馈给发送方。如果此消息没有发送成功,发送方可以选择重试或者稍后再试。
2、发送成功:如果接收方处在“在线”状态,应该立即收到此消息。如果接收方处在“离线”状态不能收到消息,一旦上线则立刻收到消息。
3、消息不能重复:简言之就是发送的一条消息不能被重复收到多次。
③一致性原则
系统中要重视消息的时序问题,不能出现发送的消息顺序颠倒的问题。通常出现时序的问题有以下的原因:
1、网络传输延迟导致时序不一致。不同用户发送的消息到达服务器的延时差异较大,给消息时序性带来挑战。早期开发过程中经常会遇到这种问题。
2、分布式系统的出现导致时序不一致。IM系统模块众多,接入层、消息逻辑层等、每层都分布式集群化,这些应用分布在不同的机器上,如何保证时序是个难点。
④扩展性原则
扩展性是IM系统后期要考虑的问题,包括功能的扩展,服务器的扩展等,这次就先不展开阐述。
Mina和Netty都是java领域高性能和高可伸缩性网络应用程序的网络应用框架。
Mina是 Apache 组织的项目,它为开发高性能和高可用性的网络 应用程序提供的框架。当前的Mina版本支持基于 Java NIO 技术的 TCP/UDP 应用程序开发、串口通讯程序。目前正在使用 Mina的 软件有:Apache Directory Project、AsyncWeb、AMQP(Advanced Message Queuing Protocol)、RED5 Server(Macromedia Flash Media RTMP)、ObjectRADIUS、Openfire等。
Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、 事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。也就是说Netty是一个基于NIO的客户端和服务器端框架,使用Netty可以确保你快速和简单的开发出一个网络应用。
虽然我使用过Mina,但是建议开发选型上使用Netty 。因为Netty有对google protocal buf的支持,有更完整的ioc容器支持(spring,guice,jbossmc和osgi)。Mina更新到2.0就不再更新了,而Netty一直在更新,目前最新发布的版本已经更新到4.1,从版本更新角度可以看出Netty的社区很活跃,修复问题一直在持续,这将对我们选择它进行开发带来很多便利。
单体Netty IM系统,可以支持10万并发,如果机器性能良好的情况下可以超过10万。
分布式的Netty IM系统,可以支持更高的并发数。各组件的功能如下:
①IM Server 连接器:主要用来负责维持和客户端的TCP连接。
②缓存:负责用户、用户绑定关系、用户群组关系的缓存。 缓存临时数据、加快读速度。可以做成集群方式。
③数据库:用户、群组、离线消息。可以做成集群方式。
④消息队列:用户状态广播、群组消息广播。可以做成集群方式。
开发环境推荐使用netty-4.1.30这个版本,jdk使用1.8及以上版本。如下所示:
io.netty
netty-all
4.1.30.Final
①开发框架采用Netty + Spring(Spring4.x)。
②Spring采用Spring cloud。基于restful 短连接的分布式微服务架构,完成用户在线管理、单点登录系统。
③消息队列采用rocketMQ 高速队列,整流作用。
④数据库采用MYSQL。
⑤协议jsON +自定义数据包采用Fastjson。
基于Netty的IM开源代码在网上有很多,这里就不列举了,可以自行去git上下载。我认为关键是把概念理清楚,技术堆栈选好,总体框架定好,接下来就是开发一个适合中小企业的IM系统了,但是要考虑到后期的扩展性,因为一个好的产品不能自己用,要让更多的人使用。
㈡ Java中如何在无参构造方法中调用有参构造
一般正常的都是参数多的调用参数少的。有参数的调用无参数的居多。
当然你要无参调用的参的也可以。
你用无参,调用有参的。那你有参的参数你需要怎么传呢。当然如果换一个角度也可以。
我手写下。没经过IDE的。提供下思路。我有两种思路,写同一个功能。
public class Person{
private String name;
private int age;
//无参
public Person(){
this.name="张三";
this.age=20;
}
//有参
public Person(String name){
this.name=name;
}
//多参
public Person(String name,int age){
this(name);//调用一个参数的构造方法
this.age=age;
}
}
这是一种写法比较常用的方法。写第一种。用上面的例子直接写
public Person(){
this("张三",20);//调用有参构造方法。设置默认值。和第一种方法功能一样
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
为了程序易读性。一般。参数的扩展和构造方法的调用都是有一定的规律的。
有参调无参,多参调少参。。扩展参数的时候,最好保持原来的顺序。
㈢ redis搴忓垪鍖栨柟寮
redis搴忓垪鍖栨柟寮忥細
1.ByteArrayRedisSerializer
Byte鏁扮粍搴忓垪鍖
2.
鍚孎astJsonRedisSerializer绫讳技
3.FastJsonRedisSerializer
1) 鐢遍樋閲屽反宸碏astJson鍖呮彁渚
2) 浼樼偣锛 1锛岄熷害蹇 2. 鍏煎规у己 3. 鍗犵敤鍐呭瓨灏
4.
1) 搴曞眰浣跨敤Jackson杩涜屽簭鍒楀寲骞跺瓨鍏Redis銆傚逛簬鏅閫氱被鍨(濡傛暟鍊肩被鍨嬶紝瀛楃
2) 瀛樺叆瀵硅薄鏃剁敱浜庢病鏈夊瓨鍏ョ被淇℃伅锛屽垯鏃犳硶鍙嶅簭鍒楀寲銆
5.GenericToStringSerializer
鍚孲tringRedisSerializer涓鏍凤紝浣嗗畠鍙浠ュ皢浠讳綍瀵硅薄娉涘寲涓哄瓧绗︿覆骞跺簭鍒
6.
浼樼偣
1) RedisTemplate榛樿ゅ簭鍒楀寲
2) 閫氱敤鎬у己
3) 鍙嶅簭鍒楀寲鏃朵笉闇瑕佹彁渚涚被鍨嬩俊鎭(class)
缂虹偣
1) 搴忓垪鍖栭熷害鎱
2) 搴忓垪鍖栧崰鐢ㄥ唴瀛樺ぇ
3) 搴忓垪鍖栧硅薄蹇呴』瀹炵幇Serializable鎺ュ彛
4) 鍙璇绘у樊(鏁版嵁瀛樺叆redis鍚庯紝濡傛灉鐩存帴浠庡悗鍙拌诲彇鏁版嵁锛屽彲璇绘т笉鍙嬪ソ)
</br>
7.OxmSerializer
1) 浠xml鏍煎紡瀛樺偍锛堜絾杩樻槸String绫诲瀷鍝︼級锛岃В鏋愯捣鏉ヤ篃姣旇緝澶嶆潅銆
缂虹偣锛
1) 閫熷害鎱
2) 鍗犵敤绌洪棿澶
8.StringRedisSerializer
StringRedisTemplate榛樿ゅ簭鍒楀寲
浼樼偣锛
1) 鍙璇绘у己
2) 涓嶉渶瑕佽浆鎹
缂虹偣锛
1) 鍙鑳藉瑰瓧绗︿覆搴忓垪鍖
2) 涓嶈兘瀵瑰硅薄搴忓垪鍖
9.Jackson2JsonRedisSerializer
1) 浣跨敤Jackson搴撳皢瀵硅薄搴忓垪鍖栦负JSON瀛楃︿覆銆
浼樼偣锛
1) 閫熷害蹇
2) 搴忓垪鍖栧悗鐨勫瓧绗︿覆鐭灏忕簿鎮
3) 涓嶉渶瑕佸疄鐜癝erializable鎺ュ彛
缂虹偣锛
蹇呴』鎻愪緵瑕佸簭鍒楀寲瀵硅薄鐨勭被鍨嬩俊鎭(.class瀵硅薄)
浣跨敤FastJsonRedisSerializer闇瑕佸紩鐢