我用spring mvc框架的,在controller中实现一个长轮询的接口,后台维持了一个队列结构,长轮询如果能从队列中取出结果则返回,如果没有则每隔1秒再取;
@controller
@requestMapping("/infopublish")
@Scope("prototype")
public class InfoPublishController{
@RequestMapping(value="/getsubscribeinfo.do",method=RequestMethod.GET,header="Accept=text/plain")
public @ResponseBody String GetSubscribeInfo(@RequestParam String userInfo){
return UserBox.GetInstance().GetUserInfo(userInfo);
}
@RequestMapping(value="/addsubscribe.do",method=RequestMethod.GET,header="Accept=text/plain")
public @ResponseBody String AddSubscribe(@RequestParam String userInfo){
if( UserBox.GetInstance().AddUserBox(userInfo))
return "true";
else
return "false";
}
@RequestMapping(value="/publishinfo.do",method=RequestMethod.POST,header="Accept=text/plain")
public @ResponseBody String PublishInfo(@RequestParam String userInfo, @RequestParam String info){
if( UserBox.GetInstance().PutInfoToBox(userInfo,info))
return "true";
else
return "false";
}
}
单例的UserBox类
public class UserBox{
//单例代码省略
private Map<String, Queue<String>> box;
public Boolean AddUserBox(String userId){
try{
synchronized(this){
if(box.containsKey(userId)){ return false;}
else{
Queue<String> userBox = new LinkedBlockingQueue<String>();
box.put(userId, userBox);
return true;
}
}
}
catch(Exception e){return false;}
}
public String GetUserInfo(String userId){
if(!box.containsKey(userId)) return "";
else{
try{
while(box.get(userId).size()==0){
Thread.sleep((long)1000.0);
}
String message = box.get(userId).poll();
return message;
}
catch(Exception e){return "";}
}
}
public Boolean PutInfoToBox(String userId, String infoJson){
try{
synchronized(this){
if(!box.containsKey(userId)) return false;
else{
Queue<String> userBox = box.get(userId);
userBox.offer(infoJson);
return true;
}
}
}
catch(Exception e){return false;}
}
}
客户端用C#语言调用了通过httpwebRequest调用controller中的接口:
while(true){
string url="";
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create("http://localhost:8080/infopublish/getsubscribeinfo.do?userInfo="+args[0]);
myRequest.Method = "GET";
myRequest.ContentType = "text/plain:charset-UTF-8";
//myRequest.Timeout = 5000;
//Stream newStream = myRequest.GetRequestStream();//这里提示无法连接到远程服务器
//newStream.Close();
HttpWebResponse res = (HttpWebResponse)myRequest.GetResponse();
stream responseStream = res.GetResponseStream();
StreamReader sr = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
string backstr = sr.ReadToEnd();
sr.Close();
responseStream.close();
res.Close();
console.writeline(backstr);
}
我开启了120个这样的客户端,2个发布消息的客户端,每隔1秒调用publishInfo接口随机向120个用户发布消息,一开始120个客户端都能及时的收到,但是隔一会客户端会报超时异常,这个是正常的,之后偶尔还能收到信息,但是再过一会每个客户端就出现无法连接远程服务器,error 10061目标主机主动拒绝,连接不能建立。
关掉所有客户端,重启1个新的客户端仍然是这样,但是服务端没有报任何错误。
还请大侠帮忙分析下,是不是服务端连接太多有限制啊,还是服务端出现了太多了超时链接后干脆拒绝了所有请求?
------解决思路----------------------
服务端停止响应,停止工作了。具体原因不知道。资源耗尽没释放?网络问题?等等。
网上找找看看排查。
------解决思路----------------------
建议看看TCP/IP 的长链接。。
你知道为什么很多高可用性的解决方案需要加心跳机制么?
解决的就是这现在这样的场景。。
------解决思路----------------------
耗进连接数了,建议你用连接池处理这样的问题