设为首页 收藏本站
查看: 837|回复: 0

[经验分享] Java学习——Jetty服务端编程

[复制链接]

尚未签到

发表于 2017-2-27 06:41:16 | 显示全部楼层 |阅读模式
  下面测试使用Jetty的continuation机制,首先自定义一个服务,分别添加blockservlet和nonblockservlet。开启5个线程的线程池提供server服务。(jetty 8.1.8版本)

package test;

import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
public class PJetty{
public static void main(String[] args) throws Exception {
//设置connectors
SelectChannelConnector connector1 = new SelectChannelConnector();
connector1.setPort(1987);
connector1.setThreadPool(new QueuedThreadPool(5));
Server server = new Server();
server.setConnectors(new Connector[]{connector1});
//使用servlet处理请求
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
context.addServlet(new ServletHolder(new BlockingServlet()), "/block");
context.addServlet(new ServletHolder(new NonBlockingServlet()), "/nonblock");
server.setHandler(context);
server.start();
server.join();
}
}
  先实现一个阻塞的servlet服务BlockingServlet.java如下

package test;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class BlockingServlet extends HttpServlet {
/**
* generated serialize number
*/
private static final long serialVersionUID = -3402527424876194224L;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");//可以方便地修改日期格式

public void service(HttpServletRequest req, HttpServletResponse res)
throws java.io.IOException {
String start = dateFormat.format( new Date() );
String sleeptime = req.getParameter("st");
res.setContentType("text/plain");
res.getWriter().println("Request: "+sleeptime+"\tstart:\t" + start);
res.getWriter().flush();
try {
if(sleeptime != null){
Thread.sleep(Integer.parseInt(sleeptime)*1000);
}
} catch (Exception e) {}
String end = dateFormat.format( new Date() );
res.getWriter().println("Request: "+sleeptime+"\tend:\t" + end);
}
}
  然后实现一个NonBlockingServlet.java如下,continuation采用suspend/resume模式

package test;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
public class NonBlockingServlet extends HttpServlet {
/**
* generated serialize number
*/
private static final long serialVersionUID = 3313258432391586994L;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");//可以方便地修改日期格式
MyAsyncHandler myAsyncHandler ;
public void init() throws ServletException {
myAsyncHandler = new MyAsyncHandler() {  
public void register(final MyHandler myHandler) {
try {  
Thread.sleep(10000);
String end = dateFormat.format( new Date() );
myHandler.onMyEvent(end);  
} catch (InterruptedException e) {  
// TODO Auto-generated catch block  
e.printStackTrace();  
}  
}  
};
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
{
String start = dateFormat.format( new Date() );
String reqId = request.getParameter("st");
// 如果我们需要异步方式得到一个result,并放入request中
Object results = request.getAttribute("results");
if (results==null) // 如果异步处理尚未返回结果
{
final Continuation continuation = ContinuationSupport.getContinuation(request);
if(continuation.isInitial()){
continuation.setTimeout(8000);
response.setContentType("text/plain");
response.getWriter().println("Request: "+reqId+"\tstart:\t"+start);
response.getWriter().flush();
}
// 判断是否超时
if (continuation.isExpired())
{
// 返回超时Response
response.getWriter().println("timeout");
response.getWriter().flush();  
return;
}
// 挂起HTTP连接
continuation.suspend();
// 注册一个异步事件处理器
myAsyncHandler.register(new MyHandler() {  
public void onMyEvent(Object result) {  
continuation.setAttribute("results", result);  
continuation.resume();  
}  
});
return; // or continuation.undispatch();
}
// 连接恢复后返回结果
response.getWriter().println("Request: "+reqId+"\tend:\t" + results);
response.getWriter().flush();  
}

private interface MyAsyncHandler{
public void register(MyHandler myHandler);
}
private interface MyHandler{
public void onMyEvent(Object result);  
}
}
  一旦continuation被挂起,需要注册一系列回调函数,请求将被挂起一直到continuation.resume()或continuation.complete()被调用,如果都没有被调用,则超时。
  运行服务,测试结果如下:

root $ for i in `seq 1 10`; do lynx -dump http://192.168.201.167:1987/block?st=$i &  done
Request: 1      start:  2012/12/19 10:41:59
Request: 1      end:    2012/12/19 10:42:00
Request: 4      start:  2012/12/19 10:41:59
Request: 4      end:    2012/12/19 10:42:03
Request: 9      start:  2012/12/19 10:41:59
Request: 9      end:    2012/12/19 10:42:08
Request: 2      start:  2012/12/19 10:42:08
Request: 10     start:  2012/12/19 10:42:00
Request: 2      end:    2012/12/19 10:42:10
Request: 10     end:    2012/12/19 10:42:10

Request: 8      start:  2012/12/19 10:42:03
Request: 8      end:    2012/12/19 10:42:11
Request: 3      start:  2012/12/19 10:42:10
Request: 3      end:    2012/12/19 10:42:13
Request: 5      start:  2012/12/19 10:42:11
Request: 5      end:    2012/12/19 10:42:16
Request: 7      start:  2012/12/19 10:42:10
Request: 7      end:    2012/12/19 10:42:17
Request: 6      start:  2012/12/19 10:42:13
Request: 6      end:    2012/12/19 10:42:19
root $ for i in `seq 1 10`; do lynx -dump http://192.168.201.167:1987/nonblock?st=$i &  done
Request: 1      start:  2012/12/19 11:43:48
Request: 1      end:    2012/12/19 11:43:49
Request: 2      start:  2012/12/19 11:43:48
Request: 2      end:    2012/12/19 11:43:50
Request: 3      start:  2012/12/19 11:43:48
Request: 3      end:    2012/12/19 11:43:51
Request: 4      start:  2012/12/19 11:43:48
Request: 4      end:    2012/12/19 11:43:52
Request: 5      start:  2012/12/19 11:43:48
Request: 5      end:    2012/12/19 11:43:53
Request: 6      start:  2012/12/19 11:43:48
Request: 6      end:    2012/12/19 11:43:54
Request: 7      start:  2012/12/19 11:43:48
Request: 7      end:    2012/12/19 11:43:55
Request: 9      start:  2012/12/19 11:43:48
Request: 10     start:  2012/12/19 11:43:48
timeout
timeout
Request: 8      start:  2012/12/19 11:43:56
timeout
  再用ab简单测试一下,nonblock模式rps(request per second)要高好几倍的样子吧
  附:当异步handler操作结束返回结果时servlet或filter用来生成响应内容,典型地做法是通过设定request的attribute来传递结果results,用来判断请求是否被挂起。而suspend/continue模式用在异步的handler产生响应时使用。
  continuation的suspend/continue模式实现如下

package test;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
public class NonBlockingServlet extends HttpServlet {
/**
* Suspend/Resume
*/
private static final long serialVersionUID = 3313258432391586994L;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");//可以方便地修改日期格式
MyAsyncHandler myAsyncHandler ;
public void init() throws ServletException {
myAsyncHandler = new MyAsyncHandler() {  
public void register(final MyHandler myHandler,final String sleeptime) {
new Thread(new Runnable() {  
public void run() {  
try {
if(sleeptime != null){
Thread.sleep(Integer.parseInt(sleeptime)*1000);
}
String end = dateFormat.format( new Date() );
try {
myHandler.onMyEvent(end);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}  
} catch (InterruptedException e) {   
e.printStackTrace();  
}
}  
}).start();  
}  
};
}
protected void doGet(HttpServletRequest request, final HttpServletResponse response) throws IOException
{
String start = dateFormat.format( new Date() );
final String sleeptime = request.getParameter("st");
final Continuation continuation = ContinuationSupport.getContinuation(request);
if(continuation.isInitial()){
response.setContentType("text/plain");
response.getWriter().println("Request: "+sleeptime+"\tstart:\t"+start);
response.getWriter().flush();
}
continuation.setTimeout(8000);
// if this is not a timeout
if (continuation.isExpired())
{
// 返回超时Response
response.getWriter().println("timeout");
response.getWriter().flush();  
return;
}
// 挂起请求
continuation.suspend(response); // response may be wrapped.
// register with async service.  The code here will depend on the
// the service used (see Jetty HttpClient for example)
myAsyncHandler.register(new MyHandler()
{
public void onMyEvent(Object result) throws IOException
{
// 连接恢复后返回结果
response.getWriter().println("Request: "+sleeptime+"\tend:\t" + result);
response.getWriter().flush();
continuation.complete();
}
},sleeptime);
}

private interface MyAsyncHandler{
public void register(MyHandler myHandler,String sleeptime);
}
private interface MyHandler{
public void onMyEvent(Object result) throws IOException;  
}
}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-347564-1-1.html 上篇帖子: 杂谈X509证书, Java Keystore与Jetty 下篇帖子: Maven中Jetty插件的配置
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表