Tomcat的两个重要身份 1)http服务器 2)Tomcat是⼀个Servlet容器
当⽤户请求某个URL资源时
1)HTTP服务器会把请求信息使⽤ServletRequest对象封装起来
2)进⼀步去调⽤Servlet容器中某个具体的Servlet
3)在 2)中,Servlet容器拿到请求后,根据URL和Servlet的映射关系,找到相应的Servlet
4)如果Servlet还没有被加载,就⽤反射机制创建这个Servlet,并调⽤Servlet的init⽅法来完成初始化
5)接着调⽤这个具体Servlet的service⽅法来处理请求,请求处理结果使⽤ServletResponse对象封装
6)把ServletResponse对象返回给HTTP服务器,HTTP服务器会把响应发送给客户端
负责对外交流: 处理Socket连接,负责⽹络字节流与Request和Response对象的转化
(1)Coyote 封装了底层的⽹络通信(Socket 请求及响应处理)
(2)Coyote 使Catalina 容器(容器组件)与具体的请求协议及IO操作⽅式完全解耦
(3)Coyote 将Socket 输⼊转换封装为 Request 对象,进⼀步封装后交由Catalina 容器进⾏处理,处
理请求完成后, Catalina 通过Coyote 提供的Response 对象将结果写⼊输出流
(4)Coyote 负责的是具体协议(应⽤层)和IO(传输层)相关内容
EndPoint EndPoint 是 Coyote 通信端点,即通信监听的接⼝,是具体Socket接收和发送处理器,是对传输层的抽象,因此EndPoint⽤来实现TCP/IP协议的
Processor Processor⽤来实现HTTP协议,Processor接收来⾃EndPoint的Socket,读取字节流解析成Tomcat Request和Response对象,并通过Adapter将其提交到容器处理,Processor是对应⽤层协议的抽象
ProtocolHandler Coyote 协议接⼝, 通过Endpoint 和 Processor , 实现针对具体协议的处理能⼒
Adapter CoyoteAdapter负责将Tomcat Request转成ServletRequest,再调⽤容器
负责内部处理:加载和管理Servlet,以及具体处理Request请求;
1.每⼀个Service实例下可以有多个Connector实例和⼀个Container实例
<?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <!-- Note: A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html --> <!-- Server 根元素,创建⼀个Server实例,⼦标签有 Listener、GlobalNamingResources、 Service --> <!-- port:关闭服务器的监听端⼝ shutdown:关闭服务器的指令字符串 --> <Server port="8005" shutdown="SHUTDOWN"> <!-- 以⽇志形式输出服务器 、操作系统、JVM的版本信息 --> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> <!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" /> --> <!--APR library loader. Documentation at /docs/apr.html --> <!-- 加载(服务器启动) 和 销毁 (服务器停⽌) APR。 如果找不到APR库, 则会输出⽇志, 并 不影响 Tomcat启动 --> <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> <!-- Prevent memory leaks due to use of particular java/javax APIs--> <!-- 避免JRE内存泄漏问题 --> <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> <!-- 加载(服务器启动) 和 销毁(服务器停⽌) 全局命名服务 --> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <!-- 在Context停⽌时重建 Executor 池中的线程, 以避免ThreadLocal 相关的内存泄漏 --> <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html --> <!--定义服务器的全局JNDI资源 --> <GlobalNamingResources> <!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users --> <Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" /> </GlobalNamingResources> <!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" Note: A "Service" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/service.html --> <!-- 该标签⽤于创建 Service 实例,默认使⽤ org.apache.catalina.core.StandardService。 默认情况下,Tomcat 仅指定了Service 的名称, 值为 "Catalina"。 Service ⼦标签为 : Listener、Executor、Connector、Engine, 其中: Listener ⽤于为Service添加⽣命周期监听器, Executor ⽤于配置Service 共享线程池, Connector ⽤于配置Service 包含的链接器, Engine ⽤于配置Service中链接器对应的Servlet 容器引擎 --> <Service name="Catalina"> <!--The connectors can use a shared executor, you can define one or more named thread pools--> <!-- <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/> --> <!-- 默认情况下,Service 并未添加共享线程池配置。 如果我们想添加⼀个线程池, 可以在<Service> 下添加如下配置: name:线程池名称,⽤于 Connector中指定 namePrefix:所创建的每个线程的名称前缀,⼀个单独的线程名称为 namePrefix+threadNumber maxThreads:池中最⼤线程数 minSpareThreads:活跃线程数,也就是核⼼池线程数,这些线程不会被销毁,会⼀直存在 maxIdleTime:线程空闲时间,超过该时间后,空闲线程会被销毁,默认值为6000(1分钟),单位毫秒 maxQueueSize:在被执⾏前最⼤线程排队数⽬,默认为Int的最⼤值,也就是⼴义的⽆限。除⾮特 殊情况,这个值 不需要更改,否则会有请求不会被处理的情况发⽣ prestartminSpareThreads:启动线程池时是否启动 minSpareThreads部分线程。默认值为false,即不启动 threadPriority:线程池中线程优先级,默认值为5,值从1到10 className:线程池实现类,未指定情况下,默认实现类为 org.apache.catalina.core.StandardThreadExecutor。如果想使⽤⾃定义线程池⾸先需要实现org.apache.catalina.Executor接⼝ --> <Executor name="commonThreadPool" namePrefix="thread-exec-" maxThreads="200" minSpareThreads="100" maxIdleTime="60000" maxQueueSize="Integer.MAX_VALUE" prestartminSpareThreads="false" threadPriority="5" className="org.apache.catalina.core.StandardThreadExecutor"/> <!-- port: 端⼝号,Connector ⽤于创建服务端Socket 并进⾏监听, 以等待客户端请求链接。如果该属性设置 为0, Tomcat将会随机选择⼀个可⽤的端⼝号给当前Connector 使⽤ protocol: 当前Connector ⽀持的访问协议。 默认为 HTTP/1.1 , 并采⽤⾃动切换机制选择⼀个基于 JAVA NIO 的链接器或者基于本地APR的链接器(根据本地是否含有Tomcat的本地库判定) connectionTimeOut: Connector 接收链接后的等待超时时间, 单位为 毫秒。 -1 表示不超时。 redirectPort: 当前Connector 不⽀持SSL请求, 接收到了⼀个请求, 并且也符合security-constraint 约束, 需要SSL传输,Catalina⾃动将请求重定向到指定的端⼝。 executor: 指定共享线程池的名称, 也可以通过maxThreads、minSpareThreads 等属性配置内部线程池。 URIEncoding: ⽤于指定编码URI的字符编码, Tomcat8.x版本默认的编码为 UTF-8 , Tomcat7.x版本默认为ISO- 8859-1 --> <!--org.apache.coyote.http11.Http11NioProtocol , ⾮阻塞式 Java NIO 链接器--> <!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS HTTP/1.1 Connector on port 8080 --> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <!-- A "Connector" using the shared thread pool--> <!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> --> <!-- Define an SSL/TLS HTTP/1.1 Connector on port 8443 This connector uses the NIO implementation. The default SSLImplementation will depend on the presence of the APR/native library and the useOpenSSL attribute of the AprLifecycleListener. Either JSSE or OpenSSL style configuration may be used regardless of the SSLImplementation selected. JSSE style configuration is used below. --> <!-- <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true"> <SSLHostConfig> <Certificate certificateKeystoreFile="conf/localhost-rsa.jks" type="RSA" /> </SSLHostConfig> </Connector> --> <!-- Define an SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2 This connector uses the APR/native implementation which always uses OpenSSL for TLS. Either JSSE or OpenSSL style configuration may be used. OpenSSL style configuration is used below. --> <!-- <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol" maxThreads="150" SSLEnabled="true" > <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /> <SSLHostConfig> <Certificate certificateKeyFile="conf/localhost-rsa-key.pem" certificateFile="conf/localhost-rsa-cert.pem" certificateChainFile="conf/localhost-rsa-chain.pem" type="RSA" /> </SSLHostConfig> </Connector> --> <!-- Define an AJP 1.3 Connector on port 8009 --> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> <!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html --> <!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1"> --> <!-- name: ⽤于指定Engine 的名称, 默认为Catalina defaultHost:默认使⽤的虚拟主机名称, 当客户端请求指向的主机⽆效时, 将交由默认的虚拟主机处 理, 默认为localhost --> <Engine name="Catalina" defaultHost="localhost"> <!--For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) --> <!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/> --> <!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack --> <Realm className="org.apache.catalina.realm.LockOutRealm"> <!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. --> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <!--Host 标签⽤于配置⼀个虚拟主机 --> <Host name="www.2.com" appBase="webapps" unpackWARs="true" autoDeploy="true"> <!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --> <!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> --> <!-- docBase:Web应⽤⽬录或者War包的部署路径。可以是绝对路径,也可以是相对于 Host appBase的 相对路径。 path:Web应⽤的Context 路径。如果我们Host名为localhost, 则该web应⽤访问的根路径为: http://localhost:8080/web_demo。 --> <Context docBase="/Users/yingdian/web_demo" path="/web3"></Context> <!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> <Host name="www.1.com" appBase="webapps" unpackWARs="true" autoDeploy="true"> <!-- SingleSignOn valve, share authentication between web applications Documentation at: /docs/config/valve.html --> <!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> --> <!-- docBase:Web应⽤⽬录或者War包的部署路径。可以是绝对路径,也可以是相对于 Host appBase的 相对路径。 path:Web应⽤的Context 路径。如果我们Host名为localhost, 则该web应⽤访问的根路径为: http://localhost:8080/web_demo。 --> <!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> </Engine> </Service> </Server>
以ServerSocket为核心,导向
ServerSocket serverSocket = new ServerSocket(port);//8080 Socket socket = serverSocket.accept(); socket.close();读取web.xml文件
key 为 /lagou (url-pattern路径)
value是 实例化后的servlet(LagouServlet)实例 存储到Map集合中
<?xml version="1.0" encoding="UTF-8" ?> <web-app> <servlet> <servlet-name>lagou</servlet-name> <servlet-class>server.LagouServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>lagou</servlet-name> <url-pattern>/lagou</url-pattern> </servlet-mapping> </web-app> private void loadServlet() { InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("web.xml"); SAXReader saxReader = new SAXReader(); try { Document document = saxReader.read(resourceAsStream); Element rootElement = document.getRootElement(); //获取节点是servlet的标签 List<Element> selectNodes = rootElement.selectNodes("//servlet"); for (int i = 0; i < selectNodes.size(); i++) { Element element = selectNodes.get(i); // <servlet-name>lagou</servlet-name> Element servletnameElement = (Element) element.selectSingleNode("servlet-name"); String servletName = servletnameElement.getStringValue(); // <servlet-class>server.LagouServlet</servlet-class> Element servletclassElement = (Element) element.selectSingleNode("servlet-class"); String servletClass = servletclassElement.getStringValue(); // 根据servlet-name的值找到url-pattern Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']"); // /lagou String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue(); servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClass).newInstance()); } } catch (DocumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }(RequestProcessor)
// 定义一个线程池 int corePoolSize = 10; int maximumPoolSize =50; long keepAliveTime = 100L; TimeUnit unit = TimeUnit.SECONDS; BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50); ThreadFactory threadFactory = Executors.defaultThreadFactory(); RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler );将请求头封装 获取Get请求方式以及路径
// 构造器,输入流传入 public Request(InputStream inputStream) throws IOException { this.inputStream = inputStream; // 从输入流中获取请求信息 int count = 0; while (count == 0) { count = inputStream.available(); } byte[] bytes = new byte[count]; inputStream.read(bytes); /** /GET /lagou HTTP/1.1 Host: localhost:8080 Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,;q=0.8,application/signed-exchange;v=b3 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9**/ String inputStr = new String(bytes); // 获取第一行请求头信息 String firstLineStr = inputStr.split("\\n")[0]; // GET / HTTP/1.1 String[] strings = firstLineStr.split(" "); this.method = strings[0]; this.url = strings[1]; System.out.println("=====>>method:" + method); System.out.println("=====>>url:" + url); }获取到绝对路径,判断File.isFile()然后输出静态文件
public class Response { private OutputStream outputStream; public Response() { } public Response(OutputStream outputStream) { this.outputStream = outputStream; } // 使用输出流输出指定字符串 public void output(String content) throws IOException { outputStream.write(content.getBytes()); } /** * * @param path url,随后要根据url来获取到静态资源的绝对路径,进一步根据绝对路径读取该静态资源文件,最终通过 * 输出流输出 * /-----> classes */ public void outputHtml(String path) throws IOException { // 获取静态资源文件的绝对路径 String absoluteResourcePath = StaticResourceUtil.getAbsolutePath(path); // 输入静态资源文件 File file = new File(absoluteResourcePath); if(file.exists() && file.isFile()) { // 读取静态资源文件,输出静态资源 StaticResourceUtil.outputStaticResource(new FileInputStream(file),outputStream); }else{ // 输出404 output(HttpProtocolUtil.getHttpHeader404()); } } }####工具类
package server; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class StaticResourceUtil { /** * 获取静态资源文件的绝对路径 * @param path * @return */ public static String getAbsolutePath(String path) { String absolutePath = StaticResourceUtil.class.getResource("/").getPath(); return absolutePath.replaceAll("\\\\","/") + path; } /** * 读取静态资源文件输入流,通过输出流输出 */ public static void outputStaticResource(InputStream inputStream, OutputStream outputStream) throws IOException { int count = 0; while(count == 0) { count = inputStream.available(); } int resourceSize = count; // 输出http请求头,然后再输出具体内容 outputStream.write(HttpProtocolUtil.getHttpHeader200(resourceSize).getBytes()); // 读取内容输出 long written = 0 ;// 已经读取的内容长度 int byteSize = 1024; // 计划每次缓冲的长度 byte[] bytes = new byte[byteSize]; while(written < resourceSize) { if(written + byteSize > resourceSize) { // 说明剩余未读取大小不足一个1024长度,那就按真实长度处理 byteSize = (int) (resourceSize - written); // 剩余的文件内容长度 bytes = new byte[byteSize]; } inputStream.read(bytes); outputStream.write(bytes); outputStream.flush(); written+=byteSize; } } } package server; /** * http协议工具类,主要是提供响应头信息,这里我们只提供200和404的情况 */ public class HttpProtocolUtil { /** * 为响应码200提供请求头信息 * @return */ public static String getHttpHeader200(long contentLength) { return "HTTP/1.1 200 OK \n" + "Content-Type: text/html \n" + "Content-Length: " + contentLength + " \n" + "\r\n"; } /** * 为响应码404提供请求头信息(此处也包含了数据内容) * @return */ public static String getHttpHeader404() { String str404 = "<h1>404 not found</h1>"; return "HTTP/1.1 404 NOT Found \n" + "Content-Type: text/html \n" + "Content-Length: " + str404.getBytes().length + " \n" + "\r\n" + str404; } }迭代升级
项目启动bootstrap.start()
加载server.xml,读取端口port 8080以及HostName和appBase的绝对路径遍历文件夹,读取项目的web.xml文件,获取setvlet的class的类路径,以及url-pattern,实例化存储到对象中请求进来时,截取Url判断相应的servlet,执行相应的请求引导启动类加载器(BootstrapClassLoader) c++编写,加载java核⼼库 java.*,⽐如rt.jar中的类,构造ExtClassLoader和AppClassLoader
扩展类加载器(ExtClassLoader) java编写,加载扩展库 JAVA_HOME/lib/ext⽬录下的jar中的类,如classpath中的jre ,javax.*或者java.ext.dir指定位置中的类
系统类加载器 (SystemClassLoader/AppClassLoader)默认的类加载器,搜索环境变量 classpath 中指明的路径
当某个类加载器需要加载某个.class⽂件时,它⾸先把这个任务委托给他的上级类加载器,递归这个操
作,如果上级的类加载器没有加载,⾃⼰才会去加载这个类。
2.保证核⼼.class不能被篡改。通过委托⽅式,不会去篡改核⼼.class,即使篡改也不会去加载,即使
加载也不会是同⼀个.class对象了。不同的加载器加载同⼀个.class也不是同⼀个.class对象。这样
保证了class执⾏安全(如果⼦类加载器先加载,那么我们可以写⼀些与java.lang包中基础类同名
的类, 然后再定义⼀个⼦类加载器,这样整个应⽤使⽤的基础类就都变成我们⾃⼰定义的类了。
)
Object类 -----> ⾃定义类加载器(会出现问题的,那么真正的Object类就可能被篡改了)
tomcat 8.5 默认改变了严格的双亲委派机制
⾸先从 Bootstrap Classloader加载指定的类
如果未加载到,则从 /WEB-INF/classes加载
如果未加载到,则从 /WEB-INF/lib/*.jar 加载
如果未加载到,则依次从 System、Common、Shared 加载(在这最后⼀步,遵从双亲委派
机制)
Common 通⽤类加载器加载Tomcat使⽤以及应⽤通⽤的⼀些类,位于CATALINA_HOME/lib下,⽐如servlet-api.jar
Catalina ClassLoader ⽤于加载服务器内部可⻅类,这些类应⽤程序不能访问
Shared ClassLoader ⽤于加载应⽤程序共享类,这些类服务器不会依赖
Webapp ClassLoader,每个应⽤程序都会有⼀个独⼀⽆⼆的Webapp ClassLoader,他⽤来加载本应⽤程序 /WEB-INF/classes 和 /WEB-INF/lib 下的类。
(⽐如是否使⽤了共享线程池?IO模型?)
Tomcat8之前的版本默认使⽤BIO(阻塞式IO),对于每⼀个请求都要创建⼀个线程来处理,不适
合⾼并发;Tomcat8以后的版本默认使⽤NIO模式(⾮阻塞式IO)
protocol就是Io模型
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" executor="commonThreadPool"/>可以使⽤Nginx+Tomcat相结合的部署⽅案,Nginx负责静态资源访问,Tomcat负责Jsp等动态资源访问处理(因为Tomcat不擅⻓处理静态资源)。
JDK1.7之后使用G1收集器
JAVA_OPTS="-XX:+UseConcMarkSweepGC"垃圾回收性能指标
吞吐量:⼯作时间(排除GC时间)占总时间的百分⽐, ⼯作时间并不仅是程序运⾏的时间,还包
含内存分配时间。
暂停时间:由垃圾回收导致的应⽤程序停⽌响应次数/时间。
垃圾收集器
串⾏收集器(Serial Collector)单线程执⾏所有的垃圾回收⼯作, 适⽤于单核CPU服务器
⼯作进程(单线程)垃圾回收线程进⾏垃圾收集**|—**⼯作进程继续
并⾏收集器(Parallel Collector)
⼯作进程 (多线程)垃圾回收线程进⾏垃圾收集**|—**⼯作进程继续
⼜称为吞吐量收集器(关注吞吐量), 以并⾏的⽅式执⾏年轻代的垃圾回收, 该⽅式可以显著降
低垃圾回收的开销(指多条垃圾收集线程并⾏⼯作,但此时⽤户线程仍然处于等待状态)。适⽤于多
处理器或多线程硬件上运⾏的数据量较⼤的应⽤
并发收集器(Concurrent Collector)
以并发的⽅式执⾏⼤部分垃圾回收⼯作,以缩短垃圾回收的暂停时间。适⽤于那些响应时间优先于
吞吐量的应⽤, 因为该收集器虽然最⼩化了暂停时间(指⽤户线程与垃圾收集线程同时执⾏,但不⼀
定是并⾏的,可能会交替进⾏), 但是会降低应⽤程序的性能
CMS收集器(Concurrent Mark Sweep Collector)
并发标记清除收集器, 适⽤于那些更愿意缩短垃圾回收暂停时间并且负担的起与垃圾回收共享处
理器资源的应⽤
G1收集器(Garbage-First Garbage Collector)
适⽤于⼤容量内存的多核服务器, 可以在满⾜垃圾回收暂停时间⽬标的同时, 以最⼤可能性实现
⾼吞吐量(JDK1.7之后)
跨平台:Nginx可以在⼤多数类unix操作系统上编译运⾏,⽽且也有windows版本
Nginx的上⼿⾮常容易,配置也⽐较简单
⾼并发,性能好
稳定性也特别好,宕机概率很低
./nginx -s reload 来说明nginx信号处理这部分
1)master进程对配置⽂件进⾏语法检查
2)尝试配置(⽐如修改了监听端⼝,那就尝试分配新的监听端⼝)
3)尝试成功则使⽤新的配置,新建worker进程
4)新建成功,给旧的worker进程发送关闭消息
5)旧的worker进程收到信号会继续服务,直到把当前进程接收到的请求处理完毕后关闭
所以reload之后worker进程pid是发⽣了变化的
Nginx启动后,以daemon多进程⽅式在后台运⾏,包括⼀个Master进程和多个Worker进程,Master进程是领导,是⽼⼤,Worker进程是⼲活的⼩弟。
master进程
主要是管理worker进程,⽐如:
接收外界信号向各worker进程发送信号(./nginx -s reload)
监控worker进程的运⾏状态,当worker进程异常退出后Master进程会⾃动重新启动新的worker进程等
worker进程
worker进程具体处理⽹络请求。多个worker进程之间是对等的,他们同等竞争来⾃客户端的请
求,各进程互相之间是独⽴的。⼀个请求,只可能在⼀个worker进程中处理,⼀个worker进程,
不可能处理其它进程的请求。worker进程的个数是可以设置的,⼀般设置与机器cpu核数⼀致。
tomcat的server.xml中的AJP和HTTP连接器区别
HTTP协议:连接器监听8080端口,负责建立HTTP连接。在通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个连接器。 AJP协议:连接器监听8009端口,负责和其他的HTTP服务器建立连接。在把Tomcat与其他HTTP服务器集成时,就需要用到这个连接器。
AJP(Apache JServ Protocol)是定向包协议。因为性能原因,使用二进制格式来传输可读性文本。WEB服务器通过TCP连接和SERVLET容器连接。
WEB服务器一般维持和Web容器的多个TCP Connecions,即TCP连接池,多个request/respons循环重用同一个Connection。
但是当Connection被分配(Assigned)到某个请求时,该请求完成之前,其他请求不得使用该连接。
Protocol 协议 ==>ProtocolHandler
Rejected 拒绝
Block 块,阻塞 Policy 政策,方针 trigger触发
protocols 协议
extension 延伸
Executor 执行者
available 可用 digest 消化,摘要
internal 内部
standard 标准
Upgrade升级,往上
artifact 成品