精华内容
下载资源
问答
  • jetty

    2017-12-08 16:50:32
    jetty

    jetty下载压缩包加压缩后,配置环境变量
    war包放入\webapps目录启动想目jetty即可访问项目

    在jetty目录下执行:java -jar start.jar 启动服务器
    start.ini 可设置接口等

    直接访问有可能失败,因为webapps目录没有部署任何应用,所以请求处理失败。

    Jetty并不推荐我们在JETTY_HOME目录下启动服务器,而是从JETTY_BASE目录启动。为了贯彻这一理念,Jetty在发布包中提供了一个用于演示的BASE目录:JETTY_HOME/demo-base,通过它可以演示Jetty推荐的启动方式。

    执行以下命令,将JETTY_HOME/demo-base/作为JETTY_BASE启动Jetty:
    cd JETTYHOME/demobase/javajar JETTY_HOME/start.jar

    可以在jetty目录下创建启动文件jetty.bat
    文件内容为java -jar start.jar

    展开全文
  • Jetty

    2017-07-30 20:00:34
    一、Jetty简介 1.1 什么是Jetty  Jetty是一个提供HHTP服务器、HTTP客户端和javax.servlet容器的开源项目。    这个入门教程分为五个部分: 第一部分部分重点介绍如何使用Jetty,它提供如下信息,如什么是Jetty...


    一、Jetty简介

    1.1 什么是Jetty

      Jetty是一个提供HHTP服务器、HTTP客户端和javax.servlet容器的开源项目。
     
      这个入门教程分为五个部分:
    • 第一部分部分重点介绍如何使用Jetty,它提供如下信息,如什么是Jetty,从哪可以下载它,怎么在像Maven一样的仓库中找到它。这一部分同样会提供启动Jetty和如何配置Jetty的快速入门。
    • 第二部分从更细致的方面介绍Jetty的配置,介绍怎么用Jetty来部署一个web应用程序,怎么配置容器和连接,以及如何实现SSL和其它安全措施。
    • Jetty的管理员应该关注第三部分。从启动Jetty容器开始到session管理,日志记录,HTTP/2支持和Jetty优化,这一章节将帮助Jetty管理员获得更多关于Jetty服务以外的知识,这一章节同样包含容器最常用的特性配置如JNDI和JMX。
    • 针对使用Jetty的高级用户,第四部分着重于Jetty的开发,本章节的重点是如何将Jetty嵌入一个已经存在的应用程序中。这部分包含几个简单的例子和操作Jetty框架的指南。这一部分同样包含如何使用Jetty的maven插件以及Jetty调试。
    • 最后一个部分是引用部分,也包含Jetty的架构信息,Jetty的XML语法介绍,以及常见问题的解析,这章也介绍如何参与Jetty社区,如何贡献代码,以及如何寻求帮助。

    1.2 如何选择Jetty的版本

      Jetty9是Jetty的最近一个版本且比之前的版本有很大的改进,其中一个改进是Jetty所有特性已经体现在Jetty9的文档里。所以对于很多使用Jetty老版本的用户,我们建议使用Jetty9,我们也表示将会在接下来的几年里积极维护这一个版本。
     
    表格1.1Jetty版本
    版本 Year Home JVM 协议 Servlet JSP 状态

    9.3

    2015

    Eclipse

    1.8

    HTTP/1.1 (RFC 7230), HTTP/2 (RFC 7540), 

    WebSocket (RFC 6455, JSR 356), FastCGI

    3.1

    2.3

    稳定版本

    9.2

    2014

    Eclipse

    1.7

    HTTP/1.1 RFC2616, javax.websocket, SPDY v3

    3.1

    2.3

    稳定版本

    8

    2009-

    Eclipse/Codehaus

    1.6

    HTTP/1.1 RFC2616, WebSocket RFC 6455, SPDY v3

    3.0

    2.2

    珍贵版本

    7

    2008-

    Eclipse/Codehaus

    1.5

    HTTP/1.1 RFC2616, WebSocket RFC 6455, SPDY v3

    2.5

    2.1

    珍贵版本

    6

    2006-2010

    Codehaus

    1.4-1.5

    HTTP/1.1 RFC2616

    2.5

    2.0

    已经作废

    5

    2003-2009

    Sourceforge

    1.2-1.5

    HTTP/1.1 RFC2616

    2.4

    2.0

    已经作废

    4

    2001-2006

    Sourceforge

    1.2, J2ME

    HTTP/1.1 RFC2616

    2.3

    1.2

    远古时期

    3

    1999-2002

    Sourceforge

    1.2

    HTTP/1.1 RFC2068

    2.2

    1.1

    石器时代

    2

    1998-2000

    Mortbay

    1.1

    HTTP/1.0 RFC1945

    2.1

    1.0

    传说级别

    1

    1995-1998

    Mortbay

    1.0

    HTTP/1.0 RFC1945

    -

    -

    神话级别

    1.3 Jetty 和Java EE Web规范

      Jetty实现的Java EE规范主要是Servlet规范,最新的Java EE平台介绍了一个新的Web 规范,建议开发者只需要大部分技术中的一部分即可。然而Jetty没有实现Web 规范中所有的技术,Jetty设计为一个容器,可以使用插件自由扩展想要的功能。

    1.3.1 Java EE 7 Web规范

      在Java EE7的规范中,更新了一些重要的功能以及添加了一些新的:
     
    表格1.2 JavaEE7 Web Profile
    JSR 名称 jetty-9.1.x是否包含 支持插件

    JSR 340

    Servlet Specification API 3.1

    Yes

     

    JSR 344

    Java Server Faces 2.2 (JSF)

    No

    Yes, Mojarra or MyFaces

    JSR 245 / JSR 341

    Java Server Pages 2.3/Java Expression Language 3.0 (JSP/EL)

    Yes

    Yes

    JSR 52

    Java Standard Tag Library 1.2 (JSTL)

    Yes

    Yes

    JSR 45

    Debugging Support for Other Languages 1.0

    Yes (via JSP)

    Yes (via JSP)

    JSR 346

    Contexts and Dependency Injection for the 

    JavaEE Platform 1.1 (Web Beans)

    No

    Yes, Weld

    JSR 330

    Dependency Injection for Java 1.0

    No

    Yes as part of a CDI implementation, Weld

    JSR 316

    Managed Beans 1.0

    No

    Yes, as part of another technology

    JSR 345

    Enterprise JavaBeans 3.2 Lite

    No

     

    JSR 338

    Java Persistance 2.1 (JPA)

    No

    Yes, eg Hibernate

    JSR 250

    Common Annotations for the Java Platform 1.2

    Yes

    Partially (for non-core Servlet Spec annotations)

    JSR 907

    Java Transaction API 1.2 (JTA)

    Yes

    Yes

    JSR 349

    Bean Validation 1.1

    No

    Yes as part of another technology eg JSF, or 

    a stand-alone implementation such as Hiberate Validator

    JSR 339

    Java API for RESTful Web Services 2.0 (JAX-RS)

    No

     

    JSR 356

    Java API for Websocket 1.0

    Yes

    No

    JSR 353

    Java API for JSON Processing 1.0 (JSON-P)

    No

    Yes, eg JSON-P reference implementation

    JSR 318

    Interceptors 1.2

    No

    Yes as part of a CDI implementation


    1.3.2 Jetty EE 6 Web Profile

      下面介绍JavaEE6 Web Profile,以及与Jetty的关系

    表格 1.3. Java EE 6 Web Profile

    JSR Name Included with jetty-9.0.x Pluggable

    JSR 315

    Servlet Specification API 3.0

    Yes

     

    JSR 314

    JavaServer Faces 2.0 (JSF)

    No

    Yes, for example, Mojarra or MyFaces

    JSR 245

    JavaServer Pages 2.2/Java Expression

    Language 2.2 (JSP/EL)

    Yes

    Yes

    JSR 52

    Java Standard Tag Library 1.2 (JSTL)

    Yes

    Yes

    JSR 45

    Debugging Support for Other Languages 1.0

    Yes (via JSP)

    Yes (via JSP)

    JSR 299

    Contexts and Dependency Injection for

    the Java EE Platform 1.0 (Web Beans)

    No

    Yes, Weld or OpenWebBeans

    JSR 330

    Dependency Injection for Java 1.0

    No

    Yes as part of a CDI implementation, Weld

    JSR 316

    Managed Beans 1.0

    No

    Yes, as part of another technology.

    JSR 318

    Enterprise JavaBeans 3.1

    No

    Yes, OpenEJB

    JSR 317

    Java Persistance 2.0 (JPA)

    No

    Yes, Hibernate

    JSR 250

    Common Annotations for the Java Platform

    Yes

    Partially (for non-core Servlet Spec annotations)

    JSR 907

    Java Transaction API (JTA)

    Yes

    Implementations are pluggable, such as Atomikos, JOTM, 

    Jencks (Geronimo Transaction Manager)

    JSR 303

    Bean Validation 1.0

    No

    Yes as part of another technology (JSF), or a stand-alone 

    implementation such as Hiberate Validator

    1.4 在Maven中获取Jetty

    1.4.1 Maven坐标

      Jetty从一开始就已经存在于Maven中心了,所以Maven的坐标在最近几年也发生了变化,当Jetty基于SourceForge管理时Maven的groupId是org.mortbay.jetty,当Jetty 7来到eclipse后groupId也改变了。
    Jetty的POM坐标如下
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-project</artifactId>
      <version>${project.version}</version>
    </dependency>

     1.4.2 在Maven中心的更新日志

      Jetty不同版本的更新日志记录在一个叫做VERSIONS.txt的文件中,也可以在Maven中心找到,坐标如下
    复制代码
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-project</artifactId>
      <version>${project.version}</version>
      <classifier>version</classifier>
      <type>txt</type>
    </dependency>
    复制代码

     二、Jetty的使用

      你可以通过多种方式将Jetty植入使用的程序中,在不同的系统中使用它,或者做为一个独立的服务器来使用,这一节介绍了后者,即作为一个单独的服务器来部署web应用。

    2.1 下载Jetty

    2.1.1 下载Jetty项目

      Jetty的下载网页为:https://www.eclipse.org/jetty/download.html

      如果jdk环境支持尽量使用最新版本,将下载后的解压放在使用的位置,以后章节将使用JETTY_HOME或者 $(jetty.home)来代表Jetty的存放路径。

    2.1.2 Jetty工程简介

      Jetty所有顶级目录简介:

    表格 2.1. Contents

    Location Description

    license-eplv10-aslv20.html

    Jetty的许可文件

    README.txt

    有用的开始信息

    VERSION.txt

    版本信息

    bin/

    存放在Unix系统下运行的shell脚本

    demo-base/

    一个可运行包含示例web应用的Jetty服务器基目录

    etc/

    Jetty的配置文件

    lib/

    Jetty运行所必须的jar文件

    logs/

    日志

    modules/

    各个模块

    notice.html

    许可信息等

    resources/

    包含新增到classpath配置文件夹,如log4j.properties

    start.ini

    存放启动信息

    start.jar

    运行Jetty的jar

    webapps/

    一个用来存放运行在默认配置下的Jetty Web应用目录

    2.2 运行Jetty

      执行以下代码,Jetty会在默认8080端口运行
    cd $JETTY_HOME
    java -jar start.jar

       若执行成功会输出以下信息

    复制代码
    2015-06-04 10:50:44.806:INFO::main: Logging initialized @334ms
    2015-06-04 10:50:44.858:WARN:oejs.HomeBaseWarning:main: This instance of Jetty is not running from a separate {jetty.base} directory, this is not recommended. See documentation at http://www.eclipse.org/jetty/documentation/current/startup.html
    2015-06-04 10:50:44.995:INFO:oejs.Server:main: jetty-9.3.0.v20150601
    2015-06-04 10:50:45.012:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:///opt/jetty-distribution-9.3.0.v20150601/webapps/] at interval 1
    2015-06-04 10:50:45.030:INFO:oejs.ServerConnector:main: Started ServerConnector@19dfb72a{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
    2015-06-04 10:50:45.030:INFO:oejs.Server:main: Started @558ms
    复制代码

      你可以通过浏览器访问http://localhost:8080.。然而在$JETTY_HOME/webapps目录下并没有部署任何web应用,所以你将会看到一个Jetty提供的404错误页面,并不推荐在$JETTY_HOME下运行Jetty,而是建议运行一个Jetty基础应用。错误页面如下


    2.2.1 基础应用例子

      标准的Jetty应用,有一个demo-base的文件夹,可以不在$JETTY_HOME下运行Jetty,在demo-base文件夹下执行以下命令:
    > cd $JETTY_HOME/demo-base/
    > java -jar $JETTY_HOME/start.jar

      成功运行将有如下信息输出:

    复制代码
    2015-06-04 10:55:24.161:INFO::main: Logging initialized @308ms
    2015-06-04 10:55:24.431:WARN::main: demo test-realm is deployed. DO NOT USE IN PRODUCTION!
    2015-06-04 10:55:24.434:INFO:oejs.Server:main: jetty-9.3.0.v20150601
    2015-06-04 10:55:24.457:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:///opt/jetty-distribution-9.3.0.v20150601/demo-base/webapps/] at interval 1
    2015-06-04 10:55:24.826:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@c038203{/,file:///opt/jetty-distribution-9.3.0.v20150601/demo-base/webapps/ROOT/,AVAILABLE}{/ROOT}
    2015-06-04 10:55:24.929:WARN::main: test-jaas webapp is deployed. DO NOT USE IN PRODUCTION!
    2015-06-04 10:55:24.978:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@46238e3f{/test-jaas,file:///tmp/jetty-0.0.0.0-8080-test-jaas.war-_test-jaas-any-9105214562680121772.dir/webapp/,AVAILABLE}{/test-jaas.war}
    2015-06-04 10:55:25.162:WARN::main: async-rest webapp is deployed. DO NOT USE IN PRODUCTION!
    2015-06-04 10:55:25.208:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@6b67034{/async-rest,[file:///tmp/jetty-0.0.0.0-8080-async-rest.war-_async-rest-any-1023939491558622183.dir/webapp/, jar:file:///tmp/jetty-0.0.0.0-8080-async-rest.war-_async-rest-any-1023939491558622183.dir/webapp/WEB-INF/lib/example-async-rest-jar-9.3.0.v20150601.jar!/META-INF/resources],AVAILABLE}{/async-rest.war}
    2015-06-04 10:55:25.311:WARN::main: test-jndi webapp is deployed. DO NOT USE IN PRODUCTION!
    2015-06-04 10:55:25.386:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@8b96fde{/test-jndi,file:///tmp/jetty-0.0.0.0-8080-test-jndi.war-_test-jndi-any-1692053319754270133.dir/webapp/,AVAILABLE}{/test-jndi.war}
    2015-06-04 10:55:25.508:WARN::main: test-spec webapp is deployed. DO NOT USE IN PRODUCTION!
    2015-06-04 10:55:25.594:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@69930714{/test-spec,[file:///tmp/jetty-0.0.0.0-8080-test-spec.war-_test-spec-any-5518740932795802823.dir/webapp/, jar:file:///tmp/jetty-0.0.0.0-8080-test-spec.war-_test-spec-any-5518740932795802823.dir/webapp/WEB-INF/lib/test-web-fragment-9.3.0.v20150601.jar!/META-INF/resources],AVAILABLE}{/test-spec.war}
    2015-06-04 10:55:25.781:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@3eb7fc54{/proxy,file:///tmp/jetty-0.0.0.0-8080-xref-proxy.war-_xref-proxy-any-3068657547009829038.dir/webapp/,AVAILABLE}{/xref-proxy.war}
    2015-06-04 10:55:25.786:INFO:oejsh.ContextHandler:main: Started o.e.j.s.h.MovedContextHandler@59662a0b{/oldContextPath,null,AVAILABLE}
    2015-06-04 10:55:25.951:WARN::main: test webapp is deployed. DO NOT USE IN PRODUCTION!
    2015-06-04 10:55:26.248:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@4f83df68{/test,file:///tmp/jetty-0.0.0.0-8080-test.war-_test-any-5238659347611323540.dir/webapp/,AVAILABLE}{/test.war}
    2015-06-04 10:55:26.255:INFO:oejs.ServerConnector:main: Started ServerConnector@5a9c4ad9{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
    2015-06-04 10:55:26.259:INFO:oejus.SslContextFactory:main: x509={jetty.eclipse.org=jetty} wild={} alias=null for SslContextFactory@23941fb4(file:///opt/jetty-distribution-9.3.0.v20150601/demo-base/etc/keystore,file:///opt/jetty-distribution-9.3.0.v20150601/demo-base/etc/keystore)
    2015-06-04 10:55:26.269:INFO:oejs.ServerConnector:main: Started ServerConnector@5d908d47{SSL,[ssl, http/1.1]}{0.0.0.0:8443}
    2015-06-04 10:55:26.270:INFO:oejs.Server:main: Started @2417ms
    复制代码

      现在可以通过浏览器访问 http://localhost:8080,  此时可以看到一个Jetty的欢迎页面,页面上包含几个简单的例子,欢迎页面如下


    警告

    示例的web应用程序不一定是绝对安全的,所以不应该部署在生产环境上。

      你可以通过以下命令查看示例应用的配置信息 

    > cd $JETTY_HOME/demo-base/
    > java -jar $JETTY_HOME/start.jar --list-modules
    ...
     
    > java -jar %JETTY_HOME/start.jar --list-config
    ...

    --list-modules:此命令将返回当前服务所有可用的模块,同时也会显示本地的模块,信息包括模块实现的顺序,依赖模块以及相应的jar信息

    --list-config:显示运行环境和配置文件等信息 

    2.2.2 创建一个新的Jetty基目录

      demo-base目录是jetty.base的一个基目录,在Jetty9.1版本中新增加的。一个Jetty基目录允许配置和web应用分开部署,可以方便升级系统。Jetty默认的配置基于两个属性:
    jetty.home:这个属性定义了Jetty的路径,jar包,默认模块和默认xml配置(典型有 start.jar,lib等)
    jetty.base:这个属性表示一个特殊Jetty服务应用的路径,包括它的日志,配置和web应用(典型有 start.ini,start.d,logs和webapps)
      以下命令用于创建一个新的根路径,同时激活HTTP connector和web 应用部署模块,并且拷贝一个web应用例子来部署。
    复制代码
    > JETTY_BASE=/tmp/mybase
    > mkdir $JETTY_BASE
    > cd $JETTY_BASE
    > java -jar $JETTY_HOME/start.jar
     
    WARNING: Nothing to start, exiting ...
     
    Usage: java -jar start.jar [options] [properties] [configs]
    java -jar start.jar --help # for more information
     
    > java -jar $JETTY_HOME/start.jar --add-to-startd=http,deploy
     
    INFO: server initialised (transitively) in ${jetty.base}/start.d/server.ini
    INFO: http initialised in ${jetty.base}/start.d/http.ini
    INFO: security initialised (transitively) in ${jetty.base}/start.d/security.ini
    INFO: servlet initialised (transitively) in ${jetty.base}/start.d/servlet.ini
    INFO: webapp initialised (transitively) in ${jetty.base}/start.d/webapp.ini
    INFO: deploy initialised in ${jetty.base}/start.d/deploy.ini
    MKDIR: ${jetty.base}/webapps
    INFO: Base directory was modified
     
    > cp $JETTY_HOME/demo-base/webapps/async-rest.war webapps/ROOT.war
    > java -jar $JETTY_HOME/start.jar
     
    2015-06-04 11:10:16.286:INFO::main: Logging initialized @274ms
    2015-06-04 11:10:16.440:INFO:oejs.Server:main: jetty-9.3.0.v20150601
    2015-06-04 11:10:16.460:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:///tmp/mybase/webapps/] at interval 1
    2015-06-04 11:10:16.581:WARN::main: async-rest webapp is deployed. DO NOT USE IN PRODUCTION!
    2015-06-04 11:10:16.589:INFO:oejw.StandardDescriptorProcessor:main: NO JSP Support for /, did not find org.eclipse.jetty.jsp.JettyJspServlet
    2015-06-04 11:10:16.628:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@1a407d53{/,[file:///tmp/jetty-0.0.0.0-8080-ROOT.war-_-any-4510228025526425427.dir/webapp/, jar:file:///tmp/jetty-0.0.0.0-8080-ROOT.war-_-any-4510228025526425427.dir/webapp/WEB-INF/lib/example-async-rest-jar-9.3.0.v20150601.jar!/META-INF/resources],AVAILABLE}{/ROOT.war}
    2015-06-04 11:10:16.645:INFO:oejs.ServerConnector:main: Started ServerConnector@3abbfa04{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
    2015-06-04 11:10:16.646:INFO:oejs.Server:main: Started @634ms
    复制代码

      以上命令是Linux下的命令,简单解释:创建一个JETTY_BASE环境变量,并创建指定的文件夹,在此文件夹下运行start.jar时提示没有可以启动的东西,系统退出,此时输入java -jar $JETTY_HOME/start.jar --add-to-startd=http,deploy命令为当前基目录添加标准文件及文件夹,然后java -jar $JETTY_HOME/start.jar运行即可运行成功。在Windows下操作如下:

    (1)可以手动创建一个空的文件夹,本例使用D:\temp\jetty
    (2)在CMD中定位到当前目录下,输入java -jar D:\data\frame\jetty-distribution-9.3.11.v20160721\start.jar (注:D:\data\frame\jetty-distribution-9.3.11.v20160721目录为我的电脑Jetty目录,请输入本机Jetty目录)输出信息如下:
     

    (3)输出结果同Linux,再次输入java -jar D:\data\frame\jetty-distribution-9.3.11.v20160721\start.jar --add-to-startd=http,deploy,输出信息如下:

    (4)提示信息中说明创建了哪些文件,已经基目录被修改等信息,此时到新建的基目录下可以看到如下新增的东西:
    jetty
        |-start.d
            |-deploy.ini
            |-http.ini
            |-server.ini
        |-webapps
    (5)启动后,会同样看到404页面,也可同上面的方法,拷贝ROOT项目到当前基目录的webapps下

    2.2.3 改变Jetty的端口

      通过在启动命令中设置jetty.http.port属性的值,可以让Jetty运行在修改后的端口上。
    > cd $JETTY_BASE
    > java -jar $JETTY_HOME/start.jar jetty.http.port=8081
    ...

      另外,可以将要设置的端口属性添加到start.ini或者start.d/http.ini文件中。默认情况,在start.d/http.ini文件中定义的jetty.http.port属性可以被修改成另一个值。

    提示

    配置属性信息通过如下方式获得

    • 首先去start.d/http.ini文件中找jetty.http.port=8080配置信息,若找到配置端口即为指定端口
    • 根据模块modules/http.mod文件找到指定配置默认为etc/jetty-http.xml,在此配置文件中有jetty.http.port配置信息,若找到即为此端口配置
    • 若上面两个都没有,则随机一个没有使用的端口

    2.2.4 为HTTPS & HTTP2增加SSL

      可通过如下命令,添加并激活HTTPS和HTTP2模块
    复制代码
    > java -jar $JETTY_HOME/start.jar --add-to-startd=https,http2
    [...]
     
    > java -jar $JETTY_HOME/start.jar
    [...]
     
    2015-06-04 13:52:01.933:INFO:oejs.ServerConnector:main: Started ServerConnector@6f1fba17{SSL,[ssl, alpn, h2, http/1.1]}{0.0.0.0:8443}
    [...]
    复制代码

     --add-to-startd:此命令在ini文件中设置有效的配置信息,使HTTPS和HTTP2支持SSL连接

      输入java -jar $JETTY_HOME/start.jar --add-to-startd=https,http2命令后会提示下载一些jar包,输入y按回车,最终提示信息如下,说明操作成功:


    2.2.5 修改Jetty的HTTPS端口

      你可以通过增加jetty.ssl.port启动参数来修改HTTPS的端口信息
    > cd $JETTY_BASE
    > java -jar $JETTY_HOME/start.jar jetty.ssl.port=8444

      除了在命令行增加参数的方法外,还可以在start.ini和start.d/*.ini文件中进行配置,所以如果用户使用--add-to-startd命令来使HTTPS生效,同样也可以在start.d/https.ini文件中进行修改。

    2.2.6 更多的start.jar操作选项

      start.jar的工作是用来翻译命令行内容的,start.ini和start.d目录(包含其中的*.ini文件)生成一个classpath环境,各种属性和配置可以使用Jetty相应的xml进行配置,更多的使用方法可以通过使用命令来获得帮助。
    > java -jar $JETTY_HOME/start.jar --help

    2.3 部署Web应用

      Jetty支持热部署,可以自动部署webapps目录下的项目。标准的war文件和Jetty配置文件放置在webapps目录下,通过以下规则进行热部署
    • 例如一个包含 WEB-INF/ 子文件夹的example/文件夹做为一个标准的web应用进行部署,否则就按静态资源部署,context路径为/example(访问路径: http://localhost:8080/example/);若文件夹名字为ROOT,则访问路径为/;若文件夹名字末尾为.d则此文件夹被忽略(除非被特殊的配置文件引用)
    • 若一个文件example.war被部署在webapps下,则context路径为example/,如果名字为ROOT则访问路径为/,如果example.war文件和example/文件夹同时存在,只有war文件会被部署(这个文件会被当做一个没有被解压的目录来使用)
    • 一个像example.xml的配置文件,若文件中是标准的配置信息,也会被部署,文件中必须包含context path,如果context path和example.xml同时存在,只有example.xml会被部署。
      如果你有一个标准的web应用,可以直接将其拷贝到webapps文件夹下进行热部署。

    2.3.1 Jetty示例Web Application

      demo-base/webapps文件下的项目包含如下部署和附加的的文件:
     
    ROOT/:这个文件夹包含各种静态资源。包含Jetty欢迎页面,默认访问路径为/
    test.d:一个包含附加配置文件的文件夹,被test.xml使用用来为test.war增加额外的配置
    test.xml:一个context配置文件,用来配置和部署test.war,包含上下文环境和test.d里面的配置附加的配置信息
    test.war:在test.xml里面配置的示例web程序
    async-rest.war:一个异步示例的web应用程序
    test-jaas.war:一个使用JAAS身份验证的web应用程序。
    test-jaas.xml:用来配置test-jaas.war的配置文件
    test-jndi.war:一个使用JNDI的示例应用
    test-jndi.xml:用来配置test-jndi.war的配置文件
    test-spec.war:一个使用注解,ServletContainerInitializers 和Servlet 3.0/3.1规范的示例应用
    test-spec.xml:用来配置test-spec.war的配置文件
    xref-proxy.war:使用代理的一个示例应用
    example-moved.xml:一个演示MovedContextHandler重定向使用的示例应用

    三、Jetty配置信息介绍

    3.1如何配置jetty

    3.1.1 Jetty POJO 配置

      Jetty的核心组件是POJO(Plain Old Java Objects),配置Jetty的过程就是实例化一个Jetty POJOs并对其进行配置的过程,可以通过如下实现:
    • 编写Java代码来直接实例化并配置Jetty对象,这称为嵌入式Jetty。
    • 使用Jetty的xml配置文件,这是一个控制反转框架模式,从xml文件中实例化Jetty对象。 etc/jetty.xml配置文件是Jetty的主要配置文件,但是也有很多etc/jetty-__feature__.xml类型的文件被Jetty使用
    • 使用第三方IOC框架,如Spring来实例化Jetty对象做为一个Spring Beans
      因为配置Jetty的主要方法是IoC,所以这个文档主要介绍此种方法。

    3.1.2 Jetty启动配置文件

      Jetty使用如下配置文件来实例和启动一个服务,通过start.jar处理
    ini files:
    Jetty启动原理使用命令行,使用$JETTY_BASE/start.ini和$JETTY_BASE/start.d/*.ini文件来创建一个有效的命令参数参数如下:
    • 激活的模块  --module=name
    • 通过name=value的来为Jetty的IOC配置属性
    • XML files in Jetty IoC (or Spring) XML format
    • 一个标准的Java属性文件包含额外的启动属性
    • 其他start.jar选项(see java -jar start.jar --help)
    • 一些JVM参数组合通过--exec,例如-Xbootclasspath.

    提示

    在Jetty9,只有Jetty基路径下的配置文件被编辑,属性才会被修改

    mod files:
    $JETTY_HOME/modules/*.mod文件包含各个模块的定义,可以被--module=name命令激活,每个mod文件定义:
    • 模块依赖如何排序以及激活
    • 被模块需要并且要就在到classpath的jar包
    • 被模块需要并且内容会被执行的xml文件
    • 被激活模块需要的文件
    • 一个示例的ini文件,当被-add-to-start=name选项激活时使用

    Note

    常见典型的模块配置信息通长很少被改动,*.mod文件通常位于$JETTY_HOME/modules/文件夹下,但是额外增加的或者编辑过的通常放在 $JETTY_BASE/module下,如果一个模块需要被修改,最好的做法是在修改前从$JETTY_HOME/modules/拷贝*.mod到 $JETTY_BASE/modules/

    XML files:  

    xml文件一般用与IoC以及spring使用,用在命令行或者模块定义中。xml文件里面的配置将被注入到描述服务的一个对象里。通常改变属性的方法是改变对应的ini文件。xml文件通常放在$JETTY_HOME/etc/下,但是新增的或者被编辑的xml应该被放在 $JETTY_BASE/etc/下,如果xml配置文件有修改的必要,最好的做法是在修改前将xml文件从$JETTY_HOME/etc拷贝到$JETTY_BASE/etc/ 。
    下图是各种配置文件(ini, mod 和 XML)的关系

    3.1.3 其它配置文件

      除了上面描述的配置文件以外,服务的配置信息可以使用如下的文件:
    Context XML files:
      所有在/webapps目录下用来被IoC使用的xml文件,用来部署相应的模块,注入信息到HttpContext ,最终创建一个容器。这些可能是标准的web应用程序或定制上下文创建的特殊目的的处理器。
    web.xml:
      web.xml用来定义和配置过滤器,servlet或者资源。Jetty WebAppContext组件使用这个XML文件用来:
    • 设置一个web项目的默认的根路径
    • 通过WEB-INF/web.xml进行特殊的配置
    • Interpret descriptor fragments included in the META-INF directory of Jar files within WEB-INF/lib.

    Note

    通常web应用的web.xml文件应该在WEB-INF/web.xml位置被发现,Jetty还支持多个web.xml,可以在 WEB-INF/web.xml文件加载前或者加载后加载(使用方法见test.xml)

    Property Files:
      标准的Java配置文件,同样适用于Jetty配置:
    • 可以为Jetty IoC增加参数
    • 配置默认日志信息(StdErrLog),其他日志框架也可以通过配置被使用(例如,log4j)
    • 数据库的登录配置信息等 

    3.1.4 Jetty IoC XML使用

      为了理解Jetty IOC XML使用方法,如下面的示例Java中,嵌入式Jetty服务器实例并配置
    复制代码
    //
    //  ========================================================================
    //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
    //  ------------------------------------------------------------------------
    //  All rights reserved. This program and the accompanying materials
    //  are made available under the terms of the Eclipse Public License v1.0
    //  and Apache License v2.0 which accompanies this distribution.
    //
    //      The Eclipse Public License is available at
    //      http://www.eclipse.org/legal/epl-v10.html
    //
    //      The Apache License v2.0 is available at
    //      http://www.opensource.org/licenses/apache2.0.php
    //
    //  You may elect to redistribute this code under either of these licenses.
    //  ========================================================================
    //
    package org.eclipse.jetty.embedded;
    import org.eclipse.jetty.server.Connector;
    import org.eclipse.jetty.server.Handler;
    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.server.ServerConnector;
    import org.eclipse.jetty.server.handler.DefaultHandler;
    import org.eclipse.jetty.server.handler.HandlerCollection;
    import org.eclipse.jetty.servlet.ServletContextHandler;
    public class ExampleServer
    {
        public static void main( String[] args ) throws Exception
        {
            Server server = new Server();
            ServerConnector connector = new ServerConnector(server);
            connector.setPort(8080);
            server.setConnectors(new Connector[] { connector });
            ServletContextHandler context = new ServletContextHandler();
            context.setContextPath("/");
            context.addServlet(HelloServlet.class, "/hello");
            context.addServlet(AsyncEchoServlet.class, "/echo/*");
            HandlerCollection handlers = new HandlerCollection();
            handlers.setHandlers(new Handler[] { context, new DefaultHandler() });
            server.setHandler(handlers);
            server.start();
            server.join();
        }
    }
    复制代码

     

    注意事项:
    • 注意Jetty的最低使用的jdk版本,最新版本使用jdk1.8
    • HelloServlet是一个继承了HttpServlet的servlet
    • 运行成功后程序会被挂起,等待用户连接,在浏览器中输入http://localhost:8080/hello即可访问
      Jetty IoC XML format也允许用户通过XML来实例化应用服务而不用写任何代码(下面配置文件的具体使用方法以后会讲到)
    复制代码
    <?xml version="1.0"?>
    <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
    <Configure id="ExampleServer" class="org.eclipse.jetty.server.Server">
      <Set name="connectors">
        <Array type="org.eclipse.jetty.server.Connector">
          <Item>
            <New class="org.eclipse.jetty.server.ServerConnector">
              <Arg><Ref refid="ExampleServer"/></Arg>
              <Set name="port">8080</Set>
            </New>
          </Item>
        </Array>
      </Set>
      <New id="context" class="org.eclipse.jetty.servlet.ServletContextHandler">
        <Set name="contextPath">/hello</Set>
        <Call name="addServlet">
          <Arg>org.eclipse.jetty.embedded.HelloServlet</Arg>
          <Arg>/</Arg>
        </Call>
      </New>
      <Set name="handler">
        <New class="org.eclipse.jetty.server.handler.HandlerCollection">
          <Set name="handlers">
            <Array type="org.eclipse.jetty.server.Handler">
              <Item>
                <Ref refid="context" />
              </Item>
              <Item>
                <New class="org.eclipse.jetty.server.handler.DefaultHandler" />
              </Item>
            </Array>
          </Set>
        </New>
      </Set>
    </Configure>
    复制代码

     

    3.2 可以在Jetty中配置什么

      这一节将介绍Jetty常用的配置。

    3.2.1 配置服务

      Server实例是Jetty服务的重要组成部分,它为其它Jetty组件提供服务和生命周期管理。在标准的Jetty应用中,核心的配置信息在etc/jetty.xml文件中 ,但是你也可以在配置文件中添加其它配置 ,包括:
    ThreadPool:
      服务器实例提供了一个默认ThreadPool实例,用来供其它组件调用。配置线程池的主要参数有最大和最小数量的设置,设置在start.ini文件或者start.d/server.ini文件中。
    Handlers:
      一个Jetty服务器可以只有一个处理程序实例来处理传入的HTTP请求。然而一个处理程序可能是一个容器或包装其他处理程序形成一个树的处理程序。在etc/jetty.xml文件中配置的默认的处理程序包含处理程序集合和一个默认的处理程序,根据路径找到相应的处理程序,默认的处理器处理404错误。其他配置信息可以增加到处理树中(例如,jetty-rewrite.xml, jetty-requestlog.xml), 或者配置一个组件用于热部署处理(例如,jetty-deploy.xml) 。
    Server Attributes:
      服务器可以通过字符串来映射到一个对象上,如果一个对象实现了LifeCycle接口,那么这个对象可以监听这个Jetty服务的启停。通常服务器的属性保存在服务器生命周期内。
    Server fields:
      服务器也有一些特殊的的配置属性,配置在start.ini或者start.d/server.ini文件中,除了控制属性外还有发送时间和http响应的版本。
    Connectors:
      服务器拥有一个连接的集合,用来接收http请求,和其它Jetty支持的协议请求,下一章节将要介绍配置连接。对于服务器可以设置所有的连接也可以增加或者删除个别连接。
    Services:
      服务器能容纳额外的服务对象,有时作为属性,但经常做为有生命周期的bean。

    3.2.2配置连接

      Jetty服务器连接器是一个网络端点接受连接一个或多个协议产生Jetty服务器的请求或消息。在标准Jetty服务器中,可以通过额外的文件增加Jetty服务器支持的协议,例如http.ini,https.ini 和jetty-http2.xml,连接的配置一般都是典型的,如下:
    Port:
      监听TCP/IP连接请求的端口,使用jetty.http.port(或者jetty.ssl.port)属性进行配置,如果没有配置默认8080(TLS默认8443)。
    Host:
      您可以配置一个主机的主机名或IP地址来识别一个特定的网络接口的监听。如果没有设置,或者设置为0.0.0.0,连接器将监听所有主机。可以通过xml文件中jetty.host的这个属性进行设置。
    Idle Timeout:
      时间以毫秒为单位,一个连接的超时时间。
    HTTP Configuration:
      通过HttpConfiguration 实例来配置HTTP连接(包含HTTP, HTTPS 和HTTP2),可以独立于特定的网络协议,标准的Jetty服务通过jetty.xml来配置一个单例的HttpConfiguration对象。
    SSL Context Factory:
      通过本地的密钥来保证ssl连接的安全性。

    Note

    虚拟主机不能配置连接,用户应该通过虚拟主机的context来实现它们的相应。

    Note

    Jetty9同时支持连接协议(HTTP,HTTPS,AJP,SPDY)和自然连接(NIO或者BIO),Jetty9以后只有一个主要的连接器ServerConnector

    3.2.3配置上下文环境

    一个Jetty环境包含一组处理器处理指定路径的请求。一个Jetty环境可以包含默认处理器和用户自定义处理器。

    Note

    servlet规范定一个web应用。在Jetty规范中一个标准的web项目必须有一个标准的WEB-INF/web.xml文件,用来配置classpath,资源,session处理,登录,以及servlet,jsp,以及静态资源。标准的web应用需要很少的额外的配置文件。

    常见的上下文配置:
    contextPath:
      contextPath 是URL的前缀。例如一个contextPath 是/foo,它将处理 /foo, /foo/index.html, /foo/bar/,and /foo/bar/image.png等请求,但是它不会处理像/,/other/,or /favicon.ico这样的请求,若contextPath是/,则为根contextPath。contextpath可以被默认设置(默认为部署的文件名),也可以在xml里面或者代码里面进行设置,或者在WEB-INF/jetty-web.xml文件中设置。
    virtualHost:
      配置监听主机ip或名称,没有配置的将不会被监听到。
    classPath:
      配置类路径,标准的类路径为 WEB-INF/lib和WEB-INF/classes ,也可以增加额外的路径到classpath下。
    attributes:
      配置属性,可以传递到实体类中,比如javax.servlet.context.tempdir属性用来配置临时目录。
    resourceBase:
      配置资源,这个配置是一个目录,包含各种静态资源信息,可以是图片或者HTML页面。

    3.2.3.1 通过API配置上下文

    在嵌入式的server,用户可以通过ContextHandler API来配置上下文,示例如下:
    复制代码
    //
    //  ========================================================================
    //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
    //  ------------------------------------------------------------------------
    //  All rights reserved. This program and the accompanying materials
    //  are made available under the terms of the Eclipse Public License v1.0
    //  and Apache License v2.0 which accompanies this distribution.
    //
    //      The Eclipse Public License is available at
    //      http://www.eclipse.org/legal/epl-v10.html
    //
    //      The Apache License v2.0 is available at
    //      http://www.opensource.org/licenses/apache2.0.php
    //
    //  You may elect to redistribute this code under either of these licenses.
    //  ========================================================================
    //
    package org.eclipse.jetty.embedded;
    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.server.handler.ContextHandler;
    public class OneContext
    {
        public static void main( String[] args ) throws Exception
        {
            Server server = new Server( 8080 );
            // Add a single handler on context "/hello"
            ContextHandler context = new ContextHandler();
            context.setContextPath( "/hello" );
            context.setHandler( new HelloHandler() );
            // Can be accessed using http://localhost:8080/hello
            server.setHandler( context );
            // Start the server
            server.start();
            server.join();
        }
    }
    复制代码

     

    3.2.3.2 通过Ioc XML配置上下文

      用户可以创建一个IoC的XML(或使用spring的Jetty插件)
    复制代码
    <?xml version="1.0"  encoding="UTF-8"?>
    <!DOCTYPE Configure PUBLIC
        "-//Mort Bay Consulting//DTD Configure//EN"
        "http://www.eclipse.org/jetty/configure_9_0.dtd">
    <!--
      Configure a custom context for serving javadoc as static resources
    -->
    <Configure class="org.eclipse.jetty.server.handler.ContextHandler">
      <Set name="contextPath">/javadoc</Set>
      <Set name="resourceBase"><SystemProperty name="jetty.home" default="."/>/javadoc/</Set>
      <Set name="handler">
        <New class="org.eclipse.jetty.server.handler.ResourceHandler">
          <Set name="welcomeFiles">
            <Array type="String">
              <Item>index.html</Item>
            </Array>
          </Set>
          <Set name="cacheControl">max-age=3600,public</Set>
        </New>
      </Set>
    </Configure>
    复制代码

     

    3.2.4 配置web应用

    servlet规范定义了一个web应用程序,当调用打包为一个WAR文件(web应用程序存档),Jetty通过如下进行配置:
    • 初始化classpath,在WEB-INF/lib和WEB-INF/classes下。
    • 根据标准的WEB-INF/web.xml进行解析初始化参数,过滤器,监听器,欢迎页面等信息。
    • WEB-INF/jetty-web.xml文件可能包含Jetty IoC的配置。

    3.2.4.1 配置contextpath

      可以增加一个WEB-INF/jetty-web.xml文件用来配置classpath
    复制代码
    <?xml version="1.0"  encoding="UTF-8"?>
    <!DOCTYPE Configure PUBLIC
        "-//Mort Bay Consulting//DTD Configure//EN"
        "http://www.eclipse.org/jetty/configure_9_0.dtd">
    <Configure class="org.eclipse.jetty.webapp.WebAppContext">
        <Set name="contextPath">/contextpath</Set>
    </Configure>
    复制代码

       还有一种做法是,不用增加配置文件,在war文件同目录,建一个同名的xml文件,内容如下:

    复制代码
    <?xml version="1.0"  encoding="UTF-8"?>
    <!DOCTYPE Configure PUBLIC
        "-//Mort Bay Consulting//DTD Configure//EN"
        "http://www.eclipse.org/jetty/configure_9_0.dtd">
    <Configure class="org.eclipse.jetty.webapp.WebAppContext">
      <Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/test.war</Set>
      <Set name="contextPath">/test</Set>
    </Configure>
    复制代码

       配置例子可以参照$JETTY_HOME/webapps/test.xml

    3.2.4.2 Web应用部署

    Jetty能够部署各种Web应用程序的格式。这是通过 扫描${jetty.base}/webapps 文件夹下
    一个Context可以有如下
    • 一个标准的war文件(必须以war结尾)
    • 一个标准的web应用(必须有{dir}/WEB-INF/web.xml 文件)
    • 一个包含静态资源的文件夹
    • 一个Jetty描述XML,引用一个web应用
    新WebAppProvider将试图避免双重部署,以及其他需要注意的方面,如下:
    • 隐藏文件将被忽略(以.开头的文件)
    • 以.d开头的文件夹将被忽略
    • 如果一个文件夹和war名字一样,则只有war会部署
    • 如果一个文件夹和同名xml配置,则xml配置的会被部署
    • 如果一个war文件和xml文件同名,则xml配置的会被部署

    3.2.4.3 设置身份验证区域

      身份验证方法和域名校验可以在web.xml里面进行描述:
    ...
    <login-config>
      <auth-method>BASIC</auth-method>
      <realm-name>Test Realm</realm-name>
    </login-config>
    ...

       这个例子使用名为Test Realm.的验证,但是没有说明其是怎么实现的,在Jetty中有几种实现方式,其中一种是HashLoginService可以读取登录用户,并在配置文件中查找,为了配置HashLoginService用来匹配Test Realm,可以配置$JETTY_BASE/etc/test-realm.xml文件,并且该文件必须在start.ini或者start.d/server.ini中设置。

    复制代码
    <?xml version="1.0"?>
    <!DOCTYPE Configure PUBLIC "-" "http://www.eclipse.org/jetty/configure_9_3.dtd">
    <Configure id="Server" class="org.eclipse.jetty.server.Server">
        <!-- =========================================================== -->
        <!-- Configure Authentication Login Service                      -->
        <!-- Realms may be configured for the entire server here, or     -->
        <!-- they can be configured for a specific web app in a context  -->
        <!-- configuration (see $(jetty.home)/webapps/test.xml for an    -->
        <!-- example).                                                   -->
        <!-- =========================================================== -->
        <Call name="addBean">
          <Arg>
            <New class="org.eclipse.jetty.security.HashLoginService">
              <Set name="name">Test Realm</Set>
              <Set name="config"><Property name="jetty.demo.realm" default="etc/realm.properties"/></Set>
              <Set name="refreshInterval">0</Set>
            </New>
          </Arg>
        </Call>
        <Get class="org.eclipse.jetty.util.log.Log" name="rootLogger">
          <Call name="warn"><Arg>demo test-realm is deployed. DO NOT USE IN PRODUCTION!</Arg></Call>
        </Get>
    </Configure>
    复制代码

       通过创建和配置LoginService到web应用中,当部署应用时,会通过名字去寻找匹配的登录Service。 

    展开全文
  • Jetty 与 Tomcat

    万次阅读 2021-09-01 14:35:20
    Jetty 整体架构 简单来说,Jetty Server 就是由多个 Connector(连接器)、多个 Handler(处理器), 以及一个线程池组成。整体结构请看下面这张图。 Jetty Server 可以有多个 Connector 在不同的端口上监听客户请求...

    Tomcat 的关键指标有吞吐量、响应时间、错误数、线程池、CPU 以及 JVM 内存
    线程池中的线程数量不足会影响吞吐量和响应时间;
    但是线程数太多会耗费大量 CPU;
    当内存不足时会触发频繁地 GC,耗费 CPU;

    Tomcat 中的关键的性能指标以及如何监控这些指标:主要有吞吐量、响
    应时间、错误数、线程池、CPU 以及 JVM 内存。
    在实际工作中,我们需要通过观察这些指标来诊断系统遇到的性能问题,找到性能瓶颈。如果我们监控到 CPU 上升,这时我们可以看看吞吐量是不是也上升了,如果是那说明正常;如果不是的话,可以看看 GC 的活动,如果 GC 活动频繁,并且内存居高不下,基本可以断定是内存泄漏。

    线程池大小 = 每秒请求数 × 平均请求处理时间

    这是理想的情况,也就是说线程一直在忙着干活,没有被阻塞在 I/O 等待上。实际上任务
    在执行中,线程不可避免会发生阻塞,比如阻塞在 I/O 等待上,等待数据库或者下游服务
    的数据返回,虽然通过非阻塞 I/O 模型可以减少线程的等待,但是数据在用户空间和内核
    空间拷贝过程中,线程还是阻塞的。线程一阻塞就会让出 CPU,线程闲置下来,就好像工
    作人员不可能 24 小时不间断地处理客户的请求,解决办法就是增加工作人员的数量,一个人去休息另一个人再顶上。对应到线程池就是增加线程数量,因此 I/O 密集型应用需要设置更多的线程.

    请问工作中你如何监控 Web 应用的健康状态?

    1先查看日志,那些方法耗时较大,用阿里爸爸开源arthas监控有问题的方法,排查问题
    2 使用prometheus + grafana 监控各种指标,每天上班前看一下昨天的情况,设置好阈
    值,如果达到就报警
    3 监控系统会每隔一段时间,ping下我们系统,我们系统会pong回监控系统,并带上ip地
    址,jvm当前使用率,cpu使用率等信息,如果超过一定数值,监控系统就会发出预警信
    息,我们就需要去生产管理通过日志和命令查看,到底出了什么问题

    遇到性能问题的时候是如何做问题定位的呢?

    站在设计者的角度想问题?

    假如让你来设计并实现一个 Web 容器,你会怎么做呢?
    如何合理设计顶层模块?
    如何考虑方方面面的需求,比如
    最基本的功能需求是加载和运行 Web 程序,
    最重要的非功能需求是高性能、高并发。
    有意识地训练自己独立设计一个系统的能力。

    学习新技术的小经验:在学习一门技术的时候,一定要先看清它的全貌,我推荐先看官方文档,看看都有哪些模块、整体上是如何设计的。接着我们先不要直接看源码,而是要动手跑一跑官网上的例子,或者用这个框架实现一个小系统,关键是要学会怎么使用。只有在这个基础上,才能深入到特定模块,去研究设计思路,或者深入到某一模块源码之中。这样在学习的过程中,按照一定的顺序一步一步来,就能够即时获得成就感,有了成就感你才会更加专注,才会愿意花更多时间和精力去深入研究。

    第一个是我们需要带着明确的目标去学习。
    第二个是一定要动手实践。另外适当的动手实践能够树立起信心,培养起兴趣,这
    跟玩游戏上瘾有点类似,通过打怪升级,一点点积累起成就感。

    问题:不是很明白线程sleep时间越长,为什么tomcat启动的线程就越多
    回复: 这是Tomcat需要从线程池拿出一个工作线程来处理请求,请求处理(休眠)的时间越长,这些线程被阻塞,休眠时间越长,被阻塞的线程越多,这些线程无法被线程池回收,Tomcat线程池不得不创建更多的线程来处理新的请求。

    Jetty 也是一个“HTTP 服务器+ Servlet 容器

    Jetty 整体架构

    简单来说,Jetty Server 就是由多个 Connector(连接器)、多个 Handler(处理器),
    以及一个线程池组成。整体结构请看下面这张图。

    Jetty Server 可以有多个 Connector 在不同的端口上监听客户请求。
    在这里插入图片描述
    对比一下 Tomcat的整体架构,两者非常的相像。
    在这里插入图片描述
    区别:
    第一个区别是 Jetty 中没有 Service 的概念,Tomcat 中的 Service 包装了多个连接器和
    一个容器组件,一个 Tomcat 实例可以配置多个 Service,不同的 Service 通过不同的连接
    器监听不同的端口;而 Jetty 中 Connector 是被所有 Handler 共享的。
    它们的第二个区别是,在 Tomcat 中每个连接器都有自己的线程池,而在 Jetty 中所有的
    Connector 共享一个全局的线程池。

    Jetty是基于NIO的模型来进行架构设计。

    服务端在 I/O 通信上主要完成了三件事情:
    监听连接、I/O 事件查询以及数据读写。
    因此 Jetty 设计了Acceptor、SelectorManager和 Connection 来分别做这三件事情。

    Acceptor

    通过阻塞的方式来接受连接,这一点跟 Tomcat 也是一样的。

    public void accept(int acceptorID) throws IOException
    {
    	ServerSocketChannel serverChannel = _acceptChannel;
    	if (serverChannel != null && serverChannel.isOpen())
    	{
    		// 这里是阻塞的
    		SocketChannel channel = serverChannel.accept();
    		// 执行到这里时说明有请求进来了
    		accepted(channel);
    	}
    }
    
    

    SelectorManager

    public void accept(SelectableChannel channel, Object attachment)
    {
    	// 选择一个 ManagedSelector 来处理 Channel
    	final ManagedSelector selector = chooseSelector();
    	// 提交一个任务 Accept 给 ManagedSelector
    	selector.submit(selector.new Accept(channel, attachment));
    }
    

    上面这两个过程是什么意思呢?

    打个比方,你到餐厅吃饭,先点菜(注册 I/O 事件),服务员(ManagedSelector)给你一个单子(SelectionKey),等菜做好了(I/O 事件到了),服务员根据单子就知道是哪桌点了这个菜,于是喊一嗓子某某桌的菜做好了(调用了绑定在 SelectionKey 上的EndPoint 的方法)。

    Connection

    这个 Runnable 是 EndPoint 的一个内部类,它会调用 Connection 的回调方法来处理请
    求。Jetty 的 Connection 组件类比就是 Tomcat 的 Processor,负责具体协议的解析,得
    到 Request 对象,并调用 Handler 容器进行处理。

    这段代码就是告诉 EndPoint,数据到了你就调我这些回调方法 _readCallback 吧,有点异
    步 I/O 的感觉,也就是说 Jetty 在应用层面模拟了异步 I/O 模型。而在回调方法 _readCallback 里,会调用 EndPoint 的接口去读数据,读完后让 HTTP 解析器去解析字节流,HTTP 解析器会将解析后的数据,包括请求行、请求头相关信息存到Request 对象里。

    响应处理:Connection 调用 Handler 进行业务处理,Handler 会通过 Response 对象来操作响应流,向流里面写入数据,HttpConnection 再通过 EndPoint 把数据写到
    Channel,这样一次响应就完成了。
    在这里插入图片描述
    1.Acceptor 监听连接请求,当有连接请求到达时就接受连接,一个连接对应一个
    Channel,Acceptor 将 Channel 交给 ManagedSelector 来处理。

    2.ManagedSelector 把 Channel 注册到 Selector 上,并创建一个 EndPoint 和
    Connection 跟这个 Channel 绑定,接着就不断地检测 I/O 事件。

    3.I/O 事件到了就调用 EndPoint 的方法拿到一个 Runnable,并扔给线程池执行。

    1. 线程池中调度某个线程执行 Runnable。

    5.Runnable 执行时,调用回调函数,这个回调函数是 Connection 注册到 EndPoint 中
    的。

    1. 回调函数内部实现,其实就是调用 EndPoint 的接口方法来读数据。

    7.Connection 解析读到的数据,生成请求对象并交给 Handler 组件去处理

    问题:分在不同的线程里我认为是这样分工明确好比工厂流水线最大化提升处理能力。
    我有个疑问是用全局线程池真的好吗,不是应该根据任务类型分配线程池的吗?用全局的
    不会互相干扰吗?
    回复: 全局线程池和多个隔离的线程池各有优缺点。全局的线程池方便控制线程总数,防止过多的线程导致大量线程切换。隔离的线程池可以控制任务优先级,确保低优先级的任务不会去抢高优先级任务的线程。

    问题:感觉jetty就是一个netty模型
    回复:说的很对,Tomcat和Jetty相比,Jetty的I/O线程模型更像Netty,Jetty的EatWhatYouKill线程策略,其实就是Netty 4.0中的线程模型。

    Jetty和Tomcat没有本质区别,一般来说Jetty比较小巧,又可以高度裁剪和定制,因此适合放在嵌入式设备等对内存资源比较紧张的场合。而Tomcat比较成熟稳定,对企业级应用支持比较好

    问题:Jetty作为后起之秀,跟tomcat相比,它的优势在哪儿?他们的设计思路不同,我们自己在设计的时候应该依据什么来确定使用哪种呢?
    回复: Jetty的优势是小巧,代码量小,比如它只支持非阻塞IO,这意味着把它加载到内存后占用内存空间也小,另外还可以把它裁剪的更小,比如不需要Session支持,可以方便的去掉相应的Hanlder。

    问题:跑在不同的线程里是为了解耦么?实在想不出,告诉答案吧??
    回复: 反过来想,如果等待连接到达,接收连接、等待数据到达、数据读取和请求处理(等待应用处理完)都在一个线程里,这中间线程可能大部分时间都在”等待“,没有干活,而线程资源是很宝贵的。并且线程阻塞会发生线程上下文切换,浪费CPU资源。

    acceptor、connector和sellector各自承担不同工作,用不同线程执行,
    1.用异步和通知机制,效率更高
    2.一个线程干一个事,代码实现更加简单
    3.更容易定位和分析故障

    Jetty架构之Handler组件

    Connector 会将 Servlet 请求交给Handler 去处理,那 Handler 又是如何处理请求的呢

    Handler 是什么??
    Handler 就是一个接口,它有一堆实现类,Jetty 的 Connector 组件调用这些接口来处理
    Servlet 请求,我们先来看看这个接口定义成什么样子。

    public interface Handler extends LifeCycle, Destroyable
    {
    	// 处理请求的方法
    	public void handle(String target, Request baseRequest, HttpServletRequest request, throws IOException, ServletException;
    	// 每个 Handler 都关联一个 Server 组件,被 Server 管理
    	public void setServer(Server server);
    	public Server getServer();
    	// 销毁方法相关的资源
    	public void destroy();
    }
    

    在这里插入图片描述
    Jetty Server 就是由多个 Connector、多个 Handler,以及一个线程池组成。
    Jetty 的 Handler 设计是它的一大特色,Jetty 本质就是一个 Handler 管理器,Jetty 本身
    就提供了一些默认 Handler 来实现 Servlet 容器的功能,你也可以定义自己的 Handler 来
    添加到 Jetty 中,这体现了“微内核 + 插件”的设计思想。

    总结: 从Tomcat和Jetty中 学习到的 组件化设计规范

    当我们学习一门技术的时候,如果可以勤于思考、善于总结,可以帮助我们看到现象背 后更本质的东西,让我们在成长之路上更快“脱颖而出

    组件化及可配置

    那 Web 容器如何实现这种组件化设计呢?
    有两个要点:
    第一个是面向接口编程。我们需要对系统的功能按照“高内聚、低耦合”的原则进行拆
    分,每个组件都有相应的接口,组件之间通过接口通信,这样就可以方便地替换组件了。
    比如我们可以选择不同连接器类型,只要这些连接器组件实现同一个接口就行。
    第二个是 Web 容器提供一个载体把组件组装在一起工作。组件的工作无非就是处理请
    求,因此容器通过责任链模式把请求依次交给组件去处理。对于用户来说,我只需要告诉
    Web 容器由哪些组件来处理请求。把组件组织起来需要一个“管理者”,这就是为什么
    Tomcat 和 Jetty 都有一个 Server 的概念,Server 就是组件的载体,Server 里包含了连
    接器组件和容器组件;容器还需要把请求交给各个子容器组件去处理,Tomcat 和 Jetty
    都是责任链模式来实现的。

    用户通过配置来组装组件,跟 Spring 中 Bean 的依赖注入相似。Spring 的用户可以通过
    配置文件或者注解的方式来组装 Bean,Bean 与 Bean 的依赖关系完全由用户自己来定
    义。这一点与 Web 容器不同,Web 容器中组件与组件之间的关系是固定的,比如
    Tomcat 中 Engine 组件下有 Host 组件、Host 组件下有 Context 组件等,但你不能在
    Host 组件里“注入”一个 Wrapper 组件,这是由于 Web 容器本身的功能来决定的。

    组件的创建。

    由于组件是可以配置的,Web 容器在启动之前并不知道要创建哪些组件,也就是说,不能
    通过硬编码的方式来实例化这些组件,而是需要通过反射机制来动态地创建。具体来说,
    Web 容器不是通过 new 方法来实例化组件对象的,而是通过 Class.forName 来创建组
    件。无论哪种方式,在实例化一个类之前,Web 容器需要把组件类加载到 JVM,这就涉及
    一个类加载的问题,Web 容器设计了自己类加载器。

    问题:Spring 也是通过反射机制来动态地实例化 Bean,那么它用到的类加载器是从哪里来的呢?
    Web 容器给每个 Web 应用创建了一个类加载器,Spring 用到的类加载器是 Web 容
    器传给它的。

    Tomcat 和 Jetty 都采用了类似的办法来管理组件的生命周期,主要有两个要点,
    一是父组件负责子组件的创建、启停和销毁。这样只要启动最上层组件,整个 Web 容器就被启动起来了,也就实现了一键式启停;
    二是 Tomcat 和 Jetty 都定义了组件的生命周期状态,并且把组件状态的转变定义成一个事件,一个组件的状态变化会触发子组件的变化,比如 Host容器的启动事件里会触发 Web 应用的扫描和加载,最终会在 Host 容器下创建相应的Context 容器,而 Context 组件的启动事件又会触发 Servlet 的扫描,进而创建 Wrapper组件。
    那么如何实现这种联动呢?
    答案是观察者模式。具体来说就是创建监听器去监听容器的状态变化,在监听器的方法里去实现相应的动作,这些监听器其实是组件生命周期过程中的“扩展点”。

    Spring 也采用了类似的设计,Spring 给 Bean 生命周期状态提供了很多的“扩展点”。这
    些扩展点被定义成一个个接口,只要你的 Bean 实现了这些接口,Spring 就会负责调用这
    些接口,这样做的目的就是,当 Bean 的创建、初始化和销毁这些控制权交给 Spring 后,
    Spring 让你有机会在 Bean 的整个生命周期中执行你的逻辑。下面我通过一张图帮你理解
    Spring Bean 的生命周期过程。
    在这里插入图片描述

    回复: 如果业务处理时间过长,阻塞大量Tomcat线程导致线程饥饿,可以考虑异步Servlet,这样Tomcat线程立即返回,耗时处理由业务线程来处理。
    但业务线程同样有线程阻塞的问题,比如阻塞在IO上。基本思路都是用“异步回调”来避免阻塞,采用异步非阻塞IO模型,用少量线程通过事件循环来提高吞吐量。Spring给出的方案是Spring Webflux。Nodejs也是这样,适合IO密集型的应用。
    协程也是这个思路,并且它的网络通信也是通过epoll来实现非阻塞的,只不过它向开发者提供了“同步阻塞”式的API,另外协程的上下文切换开销也比线程小,因为它将“函数调用上下文”保存在应用层面,内核感觉不到,但是这需要额外的内存、调度和管理开销。

    什么是进程和线程?

    这是基于安全上的考虑,用户程序只能访问用户空间,内核程序可以访问整个进程空间,并且只有内核可以直接访问各种硬件资源,比如磁盘和网卡。那用户程序需要访问这些硬件资源该怎么办呢?答案是通过系统调用,系统调用可以理解为内核实现的函数,比如应用程序要通过网卡接收数据,会调用 Socket 的 read 函数。

    在 Linux 中,线程是一个轻量级的进程,轻量级说的是线程只是一个 CPU 调度单元,因此
    线程有自己的task_struct结构体和运行栈区,但是线程的其他资源都是跟父进程共用
    的,比如虚拟地址空间、打开的文件和 Socket 等。

    用户态和用户空间是啥关系?
    回复: 你可以理解为CPU上有个开关,可以设置CPU的工作模式:用户态和内核态。在用户态模式下访问用户空间,也就是低地址的3GB。

    什么是虚拟内存和物理内存?

    什么是用户空间和内核空间??

    线程的阻塞到底意味着什么?

    内核又是如何唤醒用户线程的等等这些问题?

    大体来说,Tomcat 的核心竞争力是成熟稳定,因为它经过了多年的市场考验,应用也相当广泛,对于比较复杂的企业级应用支持得更加全面。也因为如此,Tomcat 在整体结构上比 Jetty 更加复杂,功能扩展方面可能不如 Jetty 那么方便。

    而 Jetty 比较年轻,设计上更加简洁小巧,配置也比较简单,功能也支持方便地扩展和裁
    剪,比如我们可以把 Jetty 的 SessionHandler 去掉,以节省内存资源,因此 Jetty 还可以
    运行在小型的嵌入式设备中,比如手机和机顶盒。当然,我们也可以自己开发一个
    Handler,加入 Handler 链中用来扩展 Jetty 的功能。值得一提的是,Hadoop 和 Solr 都
    嵌入了 Jetty 作为 Web 服务器.

    从设计的角度来看,Tomcat 的架构基于一种多级容器的模式.
    在这里插入图片描述

    Tomcat 线程池调优大法,可以延伸 java 的线程池调优

    线程池的调优就是设置合理的线程池参数。

    Tomcat 线程池中有哪些关键参数:
    在这里插入图片描述

    这里面最核心的就是如何确定 maxThreads 的值

    如果这个参数设置小了,Tomcat 会发生线程饥饿,并且请求的处理会在队列中排队等待,导致响应时间变长;如果maxThreads 参数值过大,同样也会有问题,因为服务器的 CPU 的核数有限,线程数太多会导致线程在 CPU 上来回切换,耗费大量的切换开销

    设置小了,队列中排队等待
    设置大了,发生来回的CPU切换

    利特尔法则

    系统中的请求数 = 请求的到达速率 × 每个请求处理时间

    因此可以总结出一个公式
    线程池大小 = 每秒请求数 × 平均请求处理时间

    这是理想的情况,也就是说线程一直在忙着干活,没有被阻塞在 I/O 等待上。实际上任务
    在执行中,线程不可避免会发生阻塞,比如阻塞在 I/O 等待上,等待数据库或者下游服务
    的数据返回,虽然通过非阻塞 I/O 模型可以减少线程的等待,但是数据在用户空间和内核
    空间拷贝过程中,线程还是阻塞的。线程一阻塞就会让出 CPU,线程闲置下来,就好像工
    作人员不可能 24 小时不间断地处理客户的请求,解决办法就是增加工作人员的数量,一个人去休息另一个人再顶上。对应到线程池就是增加线程数量,因此 I/O 密集型应用需要设置更多的线程。

    线程 I/O 时间与 CPU 时间

    至此我们又得到一个线程池个数的计算公式,假设服务器是单核的。

    线程池大小 = (线程 I/O 阻塞时间 + 线程 CPU 时间 )/ 线程 CPU 时间

    其中:线程 I/O 阻塞时间 + 线程 CPU 时间 = 平均请求处理时间。

    对比一下两个公式,你会发现,平均请求处理时间在两个公式里都出现了,这说明请求时间越长,需要更多的线程是毫无疑问的。

    不同的是第一个公式是用每秒请求数来乘以请求处理时间;而第二个公式用请求处理时间来除以线程 CPU 时间,请注意 CPU 时间是小于请求处理时间的。

    虽然这两个公式是从不同的角度来看待问题的,但都是理想情况,都有一定的前提条件。

    1. 请求处理时间越长,需要的线程数越多,但前提是 CPU 核数要足够,如果一个 CPU
      来支撑 10000 TPS 并发,创建 10000 个线程,显然不合理,会造成大量线程上下文切
      换。
    2. 请求处理过程中,I/O 等待时间越长,需要的线程数越多,前提是 CUP 时间和 I/O 时
      间的比率要计算的足够准确。
    3. 请求进来的速率越快,需要的线程数越多,前提是 CPU 核数也要跟上。

    实际场景下如何确定线程数??

    那么在实际情况下,线程池的个数如何确定呢?这是一个迭代的过程,先用上面两个公式大概算出理想的线程数,再反复压测调整,从而达到最优。

    一般来说,如果系统的 TPS 要求足够大,用第一个公式算出来的线程数往往会比公式二算
    出来的要大。我建议选取这两个值中间更靠近公式二的值。也就是先设置一个较小的线程
    数,然后进行压测,当达到系统极限时(错误数增加,或者响应时间大幅增加),再逐步加大线程数,当增加到某个值,再增加线程数也无济于事,甚至 TPS 反而下降,那这个值可以认为是最佳线程数。

    线程池中其他的参数,最好就用默认值,能不改就不改,除非在压测的过程发现了瓶颈。如果发现了问题就需要调整,比如 maxQueueSize,如果大量任务来不及处理都堆积在
    maxQueueSize 中,会导致内存耗尽,这个时候就需要给 maxQueueSize 设一个限制。
    当然,这是一个比较极端的情况了。

    再比如 minSpareThreads 参数,默认是 25 个线程,如果你发现系统在闲的时候用不到
    25 个线程,就可以调小一点;如果系统在大部分时间都比较忙,线程池中的线程总是远远
    多于 25 个,这个时候你就可以把这个参数调大一点,因为这样线程池就不需要反复地创建和销毁线程了。

    总结:Tomcat 线程池的各种参数,其中最重要的参数是最大线程数 maxThreads。
    理论上我们可以通过利特尔法则或者 CPU 时间与 I/O 时间的比率,计算出一个理想值,这
    个值只具有指导意义,因为它受到各种资源的限制,实际场景中,我们需要在理想值的基础上进行压测,来获得最佳线程数。

    业务的目标是什么?现在的情况是什么?

    问题:其实调优很多时候都是在找系统瓶颈,假如有个状况:系统响应比较慢,但 CPU 的用率不高,内存有所增加,通过分析 Heap Dump 发现大量请求堆积在线程池的队列中,请问这种情况下应该怎么办呢?

    回复: 这种情况应该怀疑大量线程被阻塞了,应该看看web应用是不是在访问外部数据库或者外部服务遇到了延迟。
    回复: 查看调用的服务是不是耗时太长。

    哪些原因可能导致 JVM 抛出 OutOfMemoryError 异常吗?

    JVM 在抛出 java.lang.OutOfMemoryError 时,除了会打印出一行描述信息,还会打印堆
    栈跟踪,因此我们可以通过这些信息来找到导致异常的原因。在寻找原因前,我们先来看看有哪些因素会导致 OutOfMemoryError,其中内存泄漏是导致 OutOfMemoryError 的一
    个比较常见的原因。

    内存溢出场景及方案

    java.lang.OutOfMemoryError: Java heap space

    JVM 无法在堆中分配对象时,会抛出这个异常,导致这个异常的原因可能有三种:

    1. 内存泄漏。Java 应用程序一直持有 Java 对象的引用,导致对象无法被 GC 回收,比如
      对象池和内存池中的对象无法被 GC 回收。
    2. 配置问题。有可能是我们通过 JVM 参数指定的堆大小(或者未指定的默认大小),对于应用程序来说是不够的。解决办法是通过 JVM 参数加大堆的大小。
    3. .finalize 方法的过度使用。如果我们想在 Java 类实例被 GC 之前执行一些逻辑,比如清
      理对象持有的资源,可以在 Java 类中定义 finalize 方法,这样 JVM GC 不会立即回收这些对象实例,而是将对象实例添加到一个叫“java.lang.ref.Finalizer.ReferenceQueue”的
      队列中,执行对象的 finalize 方法,之后才会回收这些对象。Finalizer 线程会和主线程竞
      争 CPU 资源,但由于优先级低,所以处理速度跟不上主线程创建对象的速度,因此
      ReferenceQueue 队列中的对象就越来越多,最终会抛出 OutOfMemoryError。解决办法
      是尽量不要给 Java 类定义 finalize 方法。

    网络通信方面的错误和异常

    网络通信方面的错误和异常也是我们在实际工作中经常碰到的,
    需要理解异常背后的原理,才能更快更精准地定位问题,从而找到解决办法。

    Java Socket 网络编程常见的异常有哪些

    常见异常

    java.net.SocketTimeoutException

    指超时错误。
    超时分为连接超时和读取超时,
    连接超时是指在调用 Socket.connect 方法的时候超时,
    而读取超时是调用 Socket.read 方法时超时。
    请你注意的是,连接超时往往是由于网络不稳定造成的,
    但是读取超时不一定是网络延迟造成的,很有可能是下游服务的响应时间过长。

    java.net.BindException: Address already in use: JVM_Bind

    指端口被占用。当服务器端调用 new ServerSocket(port) 或者 Socket.bind 函数时,如果
    端口已经被占用,就会抛出这个异常。我们可以用netstat –an命令来查看端口被谁占用
    了,换一个没有被占用的端口就能解决。

    java.net.ConnectException: Connection refused: connect

    指连接被拒绝。当客户端调用 new Socket(ip, port) 或者 Socket.connect 函数时,可能
    会抛出这个异常。原因是指定 IP 地址的机器没有找到;或者是机器存在,但这个机器上没
    有开启指定的监听端口。

    解决办法是从客户端机器 ping 一下服务端 IP,假如 ping 不通,可以看看 IP 是不是写错
    了;假如能 ping 通,需要确认服务端的服务是不是崩溃了。

    java.net.SocketException: Socket is closed

    指连接已关闭。出现这个异常的原因是通信的一方主动关闭了 Socket 连接(调用了
    Socket 的 close 方法),接着又对 Socket 连接进行了读写操作,这时操作系统会
    报“Socket 连接已关闭”的错误。

    java.net.SocketException: Connection reset/Connect reset by peer: Socket write error

    指连接被重置。这里有两种情况,分别对应两种错误:
    第一种情况是通信的一方已经将Socket 关闭,可能是主动关闭或者是因为异常退出,这时如果通信的另一方还在写数据,就会触发这个异常(Connect reset by peer);如果对方还在尝试从 TCP 连接中读数据,则会抛出 Connection reset 异常。

    为了避免这些异常发生,在编写网络通信程序时要确保:
    程序退出前要主动关闭所有的网络连接。
    检测通信的另一方的关闭连接操作,当发现另一方关闭连接后自己也要关闭该连接。

    java.net.SocketException: Broken pipe

    指通信管道已坏。发生这个异常的场景是,通信的一方在收到“Connect reset by peer:
    Socket write error”后,如果再继续写数据则会抛出 Broken pipe 异常,解决方法同上。

    java.net.SocketException: Too many open files

    指进程打开文件句柄数超过限制。当并发用户数比较大时,服务器可能会报这个异常。这是因为每创建一个 Socket 连接就需要一个文件句柄,此外服务端程序在处理请求时可能也需要打开一些文件。

    你可以通过lsof -p pid命令查看进程打开了哪些文件,是不是有资源泄露,也就是说进
    程打开的这些文件本应该被关闭,但由于程序的 Bug 而没有被关闭。

    如果没有资源泄露,可以通过设置增加最大文件句柄数。具体方法是通过ulimit -a来查
    看系统目前资源限制,通过ulimit -n 10240修改最大文件数。

    Tomcat 网络参数

    接下来我们看看 Tomcat 两个比较关键的参数:maxConnections 和 acceptCount。

    在解释这个参数之前,先简单回顾下 TCP 连接的建立过程:客户端向服务端发送 SYN 包,服务端回复 SYN+ACK,同时将这个处于 SYN_RECV 状态的连接保存到半连接队列。客户端返回 ACK 包完成三次握手,服务端将 ESTABLISHED 状态的连接移入accept 队列,等待应用程序(Tomcat)调用 accept 方法将连接取走。

    这里涉及两个队列:

    半连接队列:保存 SYN_RECV 状态的连接。队列长度由net.ipv4.tcp_max_syn_bac
    klog设置。

    accept 队列:保存 ESTABLISHED 状态的连接。队列长度为min(net.core.somaxco
    nn,backlog)。其中 backlog 是我们创建 ServerSocket 时指定的参数,最终会传递
    给 listen 方法:

    int listen(int sockfd, int backlog);
    

    如果我们设置的 backlog 大于net.core.somaxconn,accept 队列的长度将被设置为ne
    t.core.somaxconn,而这个 backlog 参数就是 Tomcat 中的acceptCount参数,默认
    值是 100,但请注意net.core.somaxconn的默认值是 128。

    你可以想象在高并发情况下当 Tomcat 来不及处理新的连接时,这些连接都被堆积在 accept 队列中,而acceptCount参数可以控制 accept 队列的长度,超过这个长度时,内核会向客户端发送RST,这样客户端会触发上文提到的“Connection reset”异常。

    而 Tomcat 中的maxConnections是指 Tomcat 在任意时刻接收和处理的最大连接数。当
    Tomcat 接收的连接数达到 maxConnections 时,Acceptor 线程不会再从 accept 队列中
    取走连接,这时 accept 队列中的连接会越积越多。

    maxConnections 的默认值与连接器类型有关:NIO 的默认值是 10000,APR 默认是
    8192。

    所以你会发现 Tomcat 的最大并发连接数等于maxConnections + acceptCount。
    如果acceptCount 设置得过大,请求等待时间会比较长;
    如果 acceptCount 设置过小,高并发情况下,客户端会立即触发 Connection reset 异常。

    我们还分析了 Tomcat 中两个比较重要的参数:acceptCount 和maxConnections。acceptCount 用来控制内核的 TCP 连接队列长度,maxConnections用于控制 Tomcat 层面的最大连接数,我们通过调整 acceptCount 和相关的内核参数somaxconn,增加了系统的并发度。

    我们通过netstat命令发现有大量的 TCP 连接处在 TIME_WAIT 状态,
    请问这是为什么?它可能会带来什么样的问题呢?

    展开全文
  • jetty压缩包

    2018-02-24 10:15:38
    jettyjetty Tar,项目中用到jetty,下载直接解压导入项目即可使用。
  • jetty笔记

    万次阅读 2020-09-03 10:00:30
    【1】安装jetty 【2】目录说明 【3】常用命令 【1】安装jetty #下载安装包 https://www.eclipse.org/jetty/previousversions.html #解压至 E:\Tools\jetty #启动 java -jar start.jar #浏览器访问...

    【1】安装jetty
    【2】目录说明
    【3】常用命令


    【1】安装jetty

    #下载安装包 https://www.eclipse.org/jetty/previousversions.html
    #解压至 E:\Tools\jetty
    #启动 java -jar start.jar
    #浏览器访问http://localhost:8080,检测Jetty是否安装成功
    #非$JETTY_HOME/webapps,运行war
    cd  E:\Tools\jetty\demo-base
    java -jar  E:\Tools\jetty\start.jar
    

    【2】目录说明

    bin 	#Jetty命令,可以将Jetty配置成系统服务
    ect		#Jetty自身的配置文件
    lib		#Jetty的JAR文件
    logs	#Jetty运行时的日志文件
    webapps	#存放Web应用,Jetty会自动加载这个目录下的所有Web应用
    start.jar	#Jetty的启动文件。在命令行环境下以 java -jar start.jar 来启动Jetty
    

    【3】常用命令

    cd $JETTY_HOME/demo-base/
    java -jar $JETTY_HOME/start.jar --list-modules  #此命令将返回当前服务所有可用的模块,同时也会显示本地的模块,信息包括模块实现的顺序,依赖模块以及相应的jar信息
    java -jar %JETTY_HOME/start.jar --list-config	#显示运行环境和配置文件等信息 
    java -jar $JETTY_HOME/start.jar jetty.http.port=8081	#改变Jetty的端口
    java -jar $JETTY_HOME/start.jar --add-to-startd=https,http2  #添加并激活HTTPS和HTTP2模块,--add-to-startd:此命令在ini文件中设置有效的配置信息,使HTTPS和HTTP2支持SSL连接
    java -jar $JETTY_HOME/start.jar jetty.ssl.port=8444 	#修改HTTPS的端口信息
    
    
    展开全文
  • jetty服务器

    2018-12-15 12:02:43
    该资源文件中有jetty服务器安装包,还有eclipse jetty插件,以及配置文档,文档中包含idea的配置和eclipse的配置及跑起web项目的过程。仅供大家下载参考,不知道的可以给我留言。
  • Jetty 9.4.7

    2017-11-27 13:39:58
    Jetty 9.4.7. Jetty 是一个开源的servlet容器,它为基于Java的web容器,例如JSP和servlet提供运行环境。Jetty是使用Java语言编写的,它的API以一组JAR包的形式发布。
  • jetty的安装与使用

    2017-04-06 14:33:29
    jetty
  • jetty插件 jetty

    2011-02-22 08:50:17
    官方网站的第一手资料:http://docs.codehaus.org/display/JETTY/Web+Tooling+Support URL:http://www.webtide.com/eclipse
  • jetty 服务器

    2019-01-25 00:56:29
    jetty 服务器,解压放到任意文件夹,配置路劲即可,。
  • 实战 Jetty

    2014-09-09 21:18:35
    Jetty
  • Jetty篇一之初识Jetty

    万次阅读 多人点赞 2018-06-14 23:12:28
    在学习Jetty之前,一定要了解一些Jetty的基本概念以及优缺点,这样才方便做更深入的学习,现在让我来慢慢揭开它的神秘面纱吧! 基础: 什么是Jetty? 简单来讲Jetty就是一个开源的HTTP服务器和Servlet引擎,它...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 89,909
精华内容 35,963
关键字:

jetty