Java NIO 高性能服务器编程

passenger 发布于 2014/09/19 09:37
阅读 1K+
收藏 1

最近在研究如何使用NIO技术开发一个多用户在线的即时通讯工具,如题,请问各位大神:

1、如何架构服务器端设计能够增加系统的吞吐量和效率呢?

2、即时通讯过程中非常常见的就是客户端A发送信息给客户端B,使用NIO服务器端通过少量的线程去操作所有的Channel,而且他们都是基于事件的。我想问,当客户端A发送消息给客户端B时,服务器端如何判断B是否在线,并且迅速(高效率)地找到客户端B所对应的Channel进行写数据呢?

加载中
0
写程序的康德
写程序的康德

无论是不是NIO,都无法做到“高效率的找到在线用户”

你必须自己维护一个routeTable一样的东西,里面放的有用户的id和channel,但是请注意,你必须处理如果channel close则需要删除routeTable对应的数据。

用户是否“在线”是没有办法判断的,特别是移动通讯的情况下。因为对物理链路的问题TCP/IP协议是无法探知的,所以你如果要保证“用户肯定能收到消息”就需要用request-response这样的机制。

passenger
passenger
谢谢您的回答,您说“无法高效率查找在线用户“,那么服务器端需要发送消息给特定用户就得要自己写一张您所说的”route table“了,请问这个table一般是如何设计的呢?
0
ksfzhaohui
ksfzhaohui
服务器端维护一个map{用户iD,用户channle}
ksfzhaohui
ksfzhaohui
回复 @passenger : 真要觉得很频繁的话就用concurrentHashMap
passenger
passenger
谢谢,这个方法我考虑过,但是我在想是否这个方式在用户很多的时候效率会下降呢?另外,用户上线,下线,等这个map就会不断的插入和删除操作,一方面多线程map不是线程安全的,另一方面map内部貌似有排序的,这样子的话每次修改map中哪怕是一个信息都会导致整个map重排了?
0
朱宏青
朱宏青

我觉得1楼说的十分在理

0
老盖
老盖
可以通过保活或心跳包实现判断用户是否在线
dimdim
dimdim
回复 @passenger : 再拉一次呗
passenger
passenger
您说的对,心跳包是必须的,不过这个方案在一种情况下就不适用了:假设每个客户端发送心跳的频率为1秒钟,B客户端发送完心跳后掉线了(下一次心跳时间还没到),此时A客户端发送消息给B客户端,服务器则认为B客户端还在线,就将这条消息发送给B所对应的Channel,这时由于B不在线,所以服务器报异常。就在这之前是否有什么好的办法检测B是否连接正常,还是说我只能够使用try-catch方式来判断呢?
0
passenger
passenger

引用来自“fireflyc”的评论

无论是不是NIO,都无法做到“高效率的找到在线用户”

你必须自己维护一个routeTable一样的东西,里面放的有用户的id和channel,但是请注意,你必须处理如果channel close则需要删除routeTable对应的数据。

用户是否“在线”是没有办法判断的,特别是移动通讯的情况下。因为对物理链路的问题TCP/IP协议是无法探知的,所以你如果要保证“用户肯定能收到消息”就需要用request-response这样的机制。

谢谢!
0
Monkey
Monkey

1.提高吞吐量的和效率核心是优秀的构架和数据传输协议。

2.tcp可以提供可靠的数据传输,客户端在大多数情况下都可以获得连接状态,特殊情况使用心跳,防止物理层直接断开。对于快速找到用户的Channel,是你软件构架的问题。

0
passenger
passenger

引用来自“Monkey”的评论

1.提高吞吐量的和效率核心是优秀的构架和数据传输协议。

2.tcp可以提供可靠的数据传输,客户端在大多数情况下都可以获得连接状态,特殊情况使用心跳,防止物理层直接断开。对于快速找到用户的Channel,是你软件构架的问题。

恩谢谢!经过这么多天的思考,我也大概有了一些理解。我在问题里问的想要查找特定的Channel目的是为了向他发消息。我看到有人写的博客里面将Server端的Selector写成几个的,每个分别负责监听不同的I/O事件(读或者连接等),他们分别运行在自己的线程里,然后将读取到的数据或者SelectionKey放入待处理队列中,另外开启其他工作者线程去处理这些请求,可是我照着他们的方式去实现了,但是却没法实现,要么在监听Accept的线程中没有及时处理(我将读取到的SelectionKey放入队列中)导致客户端一直连接不上,服务器端针对一个客户端重复触发Accept事件。。。还有或者在读线程里读取Channel阻塞,无法进行数据的读取。。汗颜啊!那些博客里面都说这是什么mina之类的优秀框架中实现的方式,为啥跑到我这边就不灵了呢。。。 然后我还是放弃了,把所有的事件(Accept和readable)放回到同一个线程中,问题就解决了。。。还有啊,我自定义了一个数据包发送数据数据包的格式是|包头|包长度|包体|包尾|这样子,每个包的大小可能不一样,每次读取之前需要通过包长度子端中的值来读取包。为了解决在缓冲区中粘包的问题,请问如何实现读取的时候保证只有一个完整的包到来的时候读取,否则就不读取的功能呢?再次谢谢啦!
朱宏青
朱宏青
用netty吧 就可以少考虑这些问题 直接关注需求
返回顶部
顶部