Python 官方文档:入门教程 => 点击学习
目录servlet3.0的异步原理使用servlet3.0实现长轮询长轮询实现servlet3.0的异步原理 servlet基础就不做介绍了,这里就介绍servlet3.0的一个重要
servlet基础就不做介绍了,这里就介绍servlet3.0的一个重要的新特性:异步。
servlet3.0原理图:
servlet3.0将tomcat工作线程和业务线程分隔开来,这样tomcat工作线程就能处理更多的连接请求。业务线程主要处理业务逻辑。在这种模式下,可以更好的分配业务线程的数量,也能根据不同的业务,设置不同的线程数量,更加灵活。
注意:tomcat的NIO和servlet3.0的异步没有关系。tomcat Nio模式,是对于Http连接的处理使用,目的是用更少的线程处理更多的连接。servlet3.0是在tomcat工作线程的处理逻辑上实现异步处理功能。
什么是长轮询:
短轮询、长轮询和长连接比较:
优点:后端程序编写比较容易,适于小型应用。。
缺点:请求中有大半是无用,浪费带宽和服务器资源。
优点:在无消息的情况下不会频繁的请求。
缺点:服务器hold连接会消耗资源。
优点:可靠性高,实时性高。
缺点:实现复杂,要维护心跳,服务器维持连接消耗资源。
原理图:
下面看下具体实现:
事件定义,这里只是定义一个简单的事件:
package com.hiwe.demo.event;
import javax.servlet.AsyncContext;
public class HttpEvent {
private String requestName;
private AsyncContext asyncContext;
public HttpEvent(String requestName,AsyncContext asyncContext){
this.requestName = requestName;
this.asyncContext = asyncContext;
}
public String getRequestName() {
return requestName;
}
public AsyncContext getAsyncContext() {
return asyncContext;
}
}
事件管理器:
package com.hiwe.demo.event;
import javax.servlet.AsyncContext;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
public class EventManager {
private final static Map<String,HttpEvent> subHttpEvents = new HashMap<>();
public static void addHttpEvent(HttpEvent event){
subHttpEvents.put(event.getRequestName(),event);
}
public static void onEvent(String requestName){
HttpEvent httpEvent = subHttpEvents.get(requestName);
if(httpEvent==null){
return;
}
AsyncContext asyncContext = httpEvent.getAsyncContext();
try {
PrintWriter writer = asyncContext.getResponse().getWriter();
writer.print(requestName+" request success!");
writer.flush();
asyncContext.complete();
subHttpEvents.remove(requestName);
} catch (IOException e) {
e.printStackTrace();
}
}
}
异步请求监听器:
package com.hiwe.demo.listener;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WEBListener;
import java.io.IOException;
import java.io.PrintWriter;
@WebListener
public class AppAsyncListener implements AsyncListener {
@Override
public void onComplete(AsyncEvent asyncEvent) throws IOException {
System.out.println("AppAsyncListener onComplete");
// we can do resource cleanup activity here
}
@Override
public void onError(AsyncEvent asyncEvent) throws IOException {
System.out.println("AppAsyncListener onError");
//we can return error response to client
}
@Override
public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
System.out.println("AppAsyncListener onStartAsync");
//we can log the event here
}
@Override
public void onTimeout(AsyncEvent asyncEvent) throws IOException {
AsyncContext asyncContext = asyncEvent.getAsyncContext();
ServletResponse response = asyncEvent.getAsyncContext().getResponse();
PrintWriter out = response.getWriter();
//返回code码,以便前端识别,并重建请求
out.write(201+" longPolling timeout");
out.flush();
asyncContext.complete();
}
}
长轮询接口:
package com.hiwe.demo.controller;
import com.hiwe.demo.listener.AppAsyncListener;
import com.hiwe.demo.event.EventManager;
import com.hiwe.demo.event.HttpEvent;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.AsyncContext;
import javax.servlet.http.httpservletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/app")
public class AsyncController {
@GetMapping("/asyncGet")
public void getDemo(@RequestParam(value = "requestName") String requestName, HttpServletRequest request, HttpServletResponse response){
//开启异步支持
request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
AsyncContext asyncContext = request.startAsync();
//添加监听器
asyncContext.addListener(new AppAsyncListener());
//设置超时时间
asyncContext.setTimeout(30000);
//添加到事件集合中去
HttpEvent httpEvent = new HttpEvent(requestName, asyncContext);
EventManager.addHttpEvent(httpEvent);
}
@GetMapping("/trigger")
public void triggerDemo(@RequestParam(value = "requestName") String requestName){
EventManager.onEvent(requestName);
}
}
以上一个简单的长轮询就实现了,我们可以进行一下测试:
启动应用后访问:http://localhost:8080/app/asyncGet?requestName=123
服务端因为数据未准备就绪,所以会hold住请求。当等待30s后会返回超时信息:
我们在30s内触发event:http://localhost:8080/app/trigger?requestName=123
返回:
以上整个长轮询实现完成了,如果有错误,欢迎指正!
到此这篇关于Java servlet通过事件驱动进行高性能长轮询详解的文章就介绍到这了,更多相关Java 高性能长轮询内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: Javaservlet通过事件驱动进行高性能长轮询详解
本文链接: https://www.lsjlt.com/news/151661.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0