`
san_yun
  • 浏览: 2594775 次
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

jetty quick start

 
阅读更多

最近学习solr的时候发现通过jetty快速启动,对jetty的使用方法进行总结。

jetty 依赖

 

	<dependency>
		  <groupId>org.mortbay.jetty</groupId>
		  <artifactId>jetty</artifactId>
		  <version>6.1.14</version>
	</dependency>

 

 

jetty quick start (org.mortbay.jetty.Server)

方法一:

 

		Server server = new Server(10008);
		ServletHandler handler = new ServletHandler();
		server.setHandler(handler);
		handler.addServletWithMapping(JobAddServlet.class, "/jobadd");
		handler.addServletWithMapping(JobInfoServlet.class, "/jobinfo");
		handler.addServletWithMapping(JobStatusServlet.class, "/jobstatus");
		handler.addServletWithMapping(ProxyServlet.class, "/*");

		server.start();
		server.join();

 这种方法比较简单,ServletHandler全部都封装好了。下面是另外一种更底层的方法,这样也能有更多的控制。

 

方法二:

 

Server server = new Server();
QueuedThreadPool threads = new QueuedThreadPool(3);
threads.setDaemon(true);

SocketConnector conn = new SocketConnector();
conn.setPort(8989);
conn.setMaxIdleTime(3600000);
conn.setLowResourceMaxIdleTime(600000);

server.setThreadPool(threads);
server.setConnectors(new Connector[] { conn });
server.setStopAtShutdown(true);
//Initialize the servlets
Context root = new Context(server, "/jettytest", Context.SESSIONS);
//root.addServlet(Servlet404.class, "/*");
root.addServlet(WaitServlet.class, "/*");

server.start();

Thread.currentThread().join();

 Connector除了SocketConnector更常见的是使用SelectChannelConnector

 

 

    SelectChannelConnector conn=new SelectChannelConnector();
    conn.setPort(port);
    conn.setLowResourcesConnections(10240);
    conn.setMaxIdleTime(3600000);
    conn.setLowResourceMaxIdleTime(600000);

 

 

jetty ThreadPool

jetty自己实现了ThreadPool,其实内部实现和j.u.c实现类似,预先创建好Thread,通过dispatch提交一个执行的任务。

 

 

jetty org.mortbay.jetty.Connector

HTTP Connector. Implementations of this interface provide connectors for the HTTP protocol. A connector receives requests (normally from a socket) and calls the handle method of the Handler object. These operations are performed using threads from the ThreadPool set on the connector. When a connector is registered with an instance of Server, then the server will set itself as both the ThreadPool and the Handler. Note that a connector can be used without a Server if a thread pool and handler are directly provided.

前面已经提到两种重要的Connector

1.SocketConnector

Socket Connector. This connector implements a traditional blocking IO and threading model.This Connector should only be used if NIO is not available.

 

2.SelectChannelConnector

Selecting NIO connector. This connector uses efficient NIO buffers with a non blocking threading model. Direct NIO buffers are used and threads are only allocated to connections with requests. Synchronization is used to simulate blocking for the servlet API, and any unflushed content at the end of request handling is written asynchronously.

This connector is best used when there are a many connections that have idle periods.

 

jetty 如何处理请求

从Connector开始着手,SocketConnector两个重要的方法:

 

  1. SocketConnector.open() 。打开socket_serverSocket= new ServerSocket()
  2. SocketConnector.accept() 。接受socket socket = _serverSocket.accept();

 

accept方法的调用顺序

 

代码如下:

 

Socket socket = _serverSocket.accept();
new SocketConnector.Connection(socket).dispatch(); 

 

第一步调用java自带的serverSocket.accept获取到Socket。

第二部 创建一个Connection对象来处理这个socket,这个Connection是SocketConnector的内部类。其dispatch方法实际调用threadPool的dispatch方法,Connection本质是一个任务。看看其run方法:

 

public void run(){
	
	synchronized(_connections)
	{
		_connections.add(this);
	}

	while (isStarted() && !isClosed())
	{
		if (_connection.isIdle())
		{
		    if (getServer().getThreadPool().isLowOnThreads())
		    {
		        int lrmit = getLowResourceMaxIdleTime();
		        if (lrmit>=0 && _sotimeout!= lrmit)
		        {
		            _sotimeout=lrmit;
		            _socket.setSoTimeout(_sotimeout);
		        }
		    }
		}                    
		_connection.handle();
	}
}

内部怎么又有一个_connection对象?这个 _connection是org.mortbay.jetty.HttpConnection的一个实例,在SocketConnector.Connection对象被new时内部创建。

 

 

Jetty org.mortbay.jetty.HttpConnection

 

A HttpConnection represents the connection of a HTTP client to the server and is created by an instance of a Connector. It's prime function is to associate Request and Response instances with a EndPoint.

 

A connection is also the prime mechanism used by jetty to recycle objects without pooling. The Request,Response, HttpParser, HttpGenerator and HttpFields instances are all recycled for the duration of a connection. Where appropriate, allocated buffers are also kept associated with the connection via the parser and/or generator.

 

 

HttpConnection还负责初始化 HttpParser,HttpFields,Request,Response,HttpGenerator,构造函数代码:

 

_parser = new HttpParser(_connector,endpoint,new RequestHandler(),_connector.getHeaderBufferSize(),_connector.getRequestBufferSize());
_requestFields = new HttpFields();
_responseFields = new HttpFields();
_request = new Request(this);
_response = new Response(this);
_generator = new HttpGenerator(_connector,_endp,_connector.getHeaderBufferSize(),_connector.getResponseBufferSize());

这里的Request和Response就是jetty对Servlet API中定义的javax.servlet.HttpServletRequest实现。

 

 

请求过来的调用顺序

写道
request-->SocketConnector.accept()-->new SocketConnector.Connection()-->new HttpConnection()--->QueuedThreadPool.dispatch(this)-->PoolThread.dispatch(Runnable)--->SocketConnector.Connection.run()--->HttpConnection.handle()

看到最后还是交给HttpConnection.handle()来处理这个请求。这里已经注意到了这个处理过程是通过ThreadPoll异步执行的,后面handle阻塞也不会影响到SocketConnector.accept()别的请求。PS: http client仍然会阻塞,因为等待HTTP结果。

 

当Servlet阻塞时,socketConnector.accept()还是会响应到新的socket。

threadPool.dispatch()是异步操作,SocketConnector.accept()的线程不会被阻塞。dispatch方法中会判断是否有空闲线程(_idleList.size()),如果有空闲线程继续用空闲线程。如果没有空闲线程,尝试开启新线程,判断_threads.size()是否小于_maxThreads?如果小于maxThreads创建一个Thread,否则直接返回。

 

这样存在的问题是虽然能响应socket,但实际这些socket永远不会被执行。

yunpeng@yunpeng-duitang:/duitang/dist/sys$ ab -n 10000 -c 500 http://localhost:8989/jettytest/1
yunpeng@yunpeng-duitang:/duitang/dist/sys$ netstat -antp | grep 8989 | wc -l
984

 

一些疑问

问题:SocketConnector.accept()的线程是main线程吗?

答案:当然不是。包括SocketConnector在内的所有Connector实现类都继承于一个AbstractConnector基类,在jetty启动的时候会调用其doStart方法。见stacktrace:

"main" prio=10 tid=0x000000004054b800 nid=0xf9e at breakpoint[0x00007f078256d000]
   java.lang.Thread.State: RUNNABLE
	at org.mortbay.jetty.AbstractConnector.doStart(AbstractConnector.java:279)
	at org.mortbay.jetty.bio.SocketConnector.doStart(SocketConnector.java:147)
	at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
	- locked <0x00000000e18c7b60> (a java.lang.Object)
	at org.mortbay.jetty.Server.doStart(Server.java:235)
	at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
	- locked <0x00000000e187f2a0> (a java.lang.Object)
	at mytest.MyJettyTester.main(MyJettyTester.java:28)

AbstractConnector.doStart()实现:

if (_threadPool==null)
	_threadPool=_server.getThreadPool();
if (_threadPool!=_server.getThreadPool() && (_threadPool instanceof LifeCycle))
	((LifeCycle)_threadPool).start();
    
// Start selector thread
synchronized(this){
    _acceptorThread=new Thread[getAcceptors()];

    for (int i=0;i<_acceptorThread.length;i++)
    {
        if (!_threadPool.dispatch(new Acceptor(i)))
        {
            Log.warn("insufficient maxThreads configured for {}",this);
            break;
        }
    }
}

AbstractConnector.Acceptor.run() 的实现,最终调用accept:

	while (isRunning() && getConnection()!=null){
	  accept(_acceptor); 

	}

可见也是通过threadPool调用的。

 

问题:serverSocket.setReuseAddress()的作用?

答案:google

 

 

分享到:
评论

相关推荐

    启动jetty的start.jar

    启动jetty的start.jar,此文件所在目录下增加lib,etc,context文件夹,lib下增加jetty的主jar包和jetty的util包。在etc下增加jetty的两个配置文件jetty.xml和webdefault.xml。在context下增加test.xml

    jetty start 9.2.13 项目所需要的完整jar包,免费。jetty启动调试

    jetty start 9.2.13 项目所需要的完整jar包,免费。jetty启动调试

    jetty相关的全部jar包

    jetty-security-9.4.8.v20171121.jar,jetty-io-9.4.8.v20171121.jar,jetty-continuation-9.4.8.v20171121.jar,jetty-client-9.4.8.v20171121.jar,jetty-jmx-9.4.8.v20171121.jar,jetty-plus-9.4.8.v20171121....

    jetty-start-9.0.3-8.el7.noarch.rpm

    官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装

    eclipse jetty插件run-jetty-run-1.3.3

    eclipse jetty插件,从...下载run-jetty-run.zip文件,解压后再编写个links文件丢到eclipse的dropins目录下即可,省去了使用eclipse update方式安装的麻烦。 link文件样例如: path=d:\\eclipse_plugins\\run-jetty-run

    Jetty嵌入项目代码中示例

    Jetty嵌入项目代码中示例,现我有一示例项目 e:/workspace/web-demo(称为project_home)...把${jetty_home}/start.jar复制到${project_home}/jetty目录下。 接下来在${project_home}/jetty/contexts目录下加一个文件。

    Jetty多版本软件包

    Jetty软件包内容: jetty-distribution-9.4.51.v20230217.tar.gz jetty-distribution-9.4.51.v20230217.zip jetty-home-10.0.15.tar.gz jetty-home-10.0.15.zip jetty-home-11.0.15.tar.gz jetty-home-11.0.15.zip ...

    jetty6 指南书

    jetty是什么 jetty配置 jetty使用 jetty嵌入 jetty启动 jetty部署 jetty教程 jetty嵌入式 jetty

    jetty嵌入式服务器必须的jar包

    jetty嵌入式服务器开发所必须的jar包,本人使用jetty版本为6.1.3,jar包总数为9个,来自jetty:commons-el-1.0.jar,jasper-compiler-5.5.15,jasper-compiler-jdt-5.5.15.jar,jasper-runtime-5.5.15.jar,jetty-...

    Jetty中文手册

    Jetty Start.jar 配置Jetty 如何设置上下文(Context Path) 如何知道使用了那些jar包 如何配置SSL 如何使用非root用户监听80端口 如何配置连接器(Connectors) 如何配置虚拟主机(Virtual Hosts) 如何配置会话ID...

    jetty相关所有jar包

    jetty相关所有jar包,包含jar包: jetty-continuation-8.1.15.v20140411,jetty-http-8.1.15.v20140411,jetty-io-8.1.15.v20140411,jetty-security-8.1.15.v20140411,jetty-server-8.1.15.v20140411,jetty-util-8.1.15...

    PDF的JETTY文档

    .jetty

    jetty-9.4.6

    jetty-9.4.6

    Jetty配置支持https

    Jetty配置支持HTTPS以及受信网站证书生成方式

    jetty 学习资料合集

    jetty 学习资料合集 jetty 学习资料合集 jetty 学习资料合集 jetty 学习资料合集

    maven集成jetty所需jar包maven-jetty-plugin,多版本

    maven集成jetty必须jar包maven-jetty-plugin,内含多个版本

    Jetty cometd(Continuation)学习笔记

    Jetty 7是Jetty奔向Eclipse后发布的第一个版本,本次的Jetty 7 RC2带给了我们一个十分诱人的新特性-支持跨域名Ajax请求。众所周知因为安全的原因,多数浏览器都限制了Ajax跨域请求和javascript加载的时候只能是与...

    jetty-distribution-9.4.0.v20161208.zip

    * start.jar is jetty7主程序 * VERSION.txt * webapps应用路径,发布的引用基本都放这里 其中比较重要的目录是:etc、contexts、webapps 。个人认为可以类比 tomcat的conf、conf\Catalina\localhost、webapps目录...

    i-jetty libs包

    android i-jetty servlet-api-2.5.jar jetty-servlet-7.6.0.RC4.jar jetty-server-7.6.0.RC4.jar jetty-http-7.6.0.RC4.jar

    jetty 9.2.24

    jetty服务器,9.2版本适合java7+开发环境。 Jetty是一个纯粹的基于Java的网页服务器和Java Servlet容器。 尽管网页服务器通常用来为人们呈现文档,但是Jetty通常在较大的软件框架中用于计算机与计算机之间的通信。 ...

Global site tag (gtag.js) - Google Analytics