Web服务器与应用服务器
什么是web服务器?
Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以向浏览器等Web客户端提供文档,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。
什么是应用服务器?
严格意义上Web服务器只负责处理HTTP协议,只能发送静态页面的内容。而JSP,ASP,PHP等动态内容需要通过CGI、FastCGI、ISAPI等接口交给其他程序去处理。这个其他程序就是应用服务器
二者之间的联系?
在大多数时候,Web服务器和引用服务器这两个术语是可以互换使用的
Web服务器的设计目的是提供HTTP内容,应用服务器也可以提供HTTP内容,但不限于HTTP,它还可以提供其他协议支持,如RMI / RPC。
Web服务器主要是为提供静态内容而设计的,不过大多数Web服务器都有插件来支持脚本语言,比如Perl、PHP、ASP、JSP等,通过这些插件,这些服务器就可以生成动态的HTTP内容
ps:简单来说前台接待(web服务器) ,服务者(应用服务器)。
常见的Web服务器
Apache
Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上。Apache源于NCSAhttpd服务器,经过多次修改,成为世界上最流行的Web服务器软件之一。Apache取自"a patchy server"的读音,意思是充满补丁的服务器,因为它是自由软件,所以不断有人来为它开发新的功能、新的特性、修改原来的缺陷。Apache的特点是简单、速度快、性能稳定,并可做代理服务器来使用
Nginx
Nginx 是一个很强大的高性能Web和反向代理服务,它具有很多非常优越的特性:
Nginx 小巧占内存少,在连接高并发的情况下,Nginx是Apache服务不错的替代品: 能够支持高达 50,000 个并发连接数的响应 ,也就是单个nginx一瞬间可以同时处理50,000个请求。
IIS
IIS本人没怎么接触过,它包括了Web服务器、FTP服务器、NNTP服务器和SMTP服务器,分别用于网页浏览、文件传输、新闻服务和邮件发送等方面,它使得在网络(包括互联网和局域网)上发布信息成了一件很容易的事。ps:桌面配置真的感觉超爽,配置错了或者没有权限当时就知道 不用再去翻日志查看 不得不说微软在用户体验上下足了功夫。
以上为今年十月份web服务器使用排名。Apache依然是霸主地位,但是Nginx即将赶超
常见的应用服务器
Apache tomcat
Tomcat是一个开放源代码、运行Servlet和JSP的容器 Apache:侧重于HTTPServer ,Tomcat:侧重于Servlet引擎,特点 简单、速度快、性能稳定
Eclipse Jetty
Jetty 一个比tomcat的架构更为简单,更加小巧,更加快速的服务器。但是对于Servlet的兼容做的没有Tomcat好,可以同时处理大量连接而且可以长时间保持连接,适合于web聊天应用等等。
Orcale WebLogic (收费) (闭源)
Oracle大佬产的,这货可牛逼,专为java设计的一个基于JAVAEE架构的中间件,用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器。将Java的动态功能和安全性引入大型网络应用的开发、集成、部署和管理之中
RedHat Jboss
基于J2EE的应用服务器,JBoss核心服务不包括支持servlet/JSP的WEB容器,一般与Tomcat绑定使用,JBoss的Web容器使用的是Tomcat
IBM WebSphere(收费)(闭源)
IBM大佬产的,WebSphere Application Server是用于J2EE企业应用级运行所需的WEB容器。一般用于保险,银行等等核心交易系统
CAUCHO Resin
是一个非常流行的支持servlets和jsp的引擎,速度非常快。Resin本身包含了一个支持HTTP/1.1的WEB服务器。它不仅可以显示动态内容,而且它显示静态内容的能力也非常强,速度直逼apache
LiteSpeed
可以替换Apache 使用较小的内存处理更多的链接,ps:但是有得就有失 CPU的使用率怕是扛不住
Lighttpd
是一个德国人领导的开源Web服务器软件。
我们所使用的服务器
IIS+nginx+tomcat
IIS作为web服务器,nginx做代理服务器负责接受http/https请求下发给tomcat处理请求
为什么要用nginx
1.apache与tomcat的瓶颈,tomcat初始产生1000个线程,最大2000线程,每一个请求为一个线程也就是说一个tomcat最多可以处理2000个请求,然而这只是静态请求 而非动态请求
使用loadrunner设置1000并发用户数进行压力测试。
100人-----响应时间0.8秒 完美
150人-----响应时间1秒 完美
200人-----响应时间1.5秒 响应时间有微小波动 比较完美
250人-----响应时间1.8秒 比较完美(此时是理想情况下最大的并发用户数量)
280人-----开始出现连接丢失问题,连接开始不稳定
300人-----响应时间3秒 响应时间有较大波动峰值为6秒 较差
350人-----响应时间3秒 开始大量出现连接丢失问题 连接很不稳定
400人-----响应时间3.8秒 连接丢失数量达到3000次以上
450人-----响应时间4秒 连接丢失数量达到6000次以上
500人-----响应时间4秒 连接丢失数量达到11000次以上
550人-----响应时间6秒 连接丢失数量达到21000次以上
600人-----响应时间6秒 连接丢失数量达到25000次以上
600人开始系统出现异常情况,因此停止测试。测试数据到此为止。
在用户超过350时性能会出现断崖式的下滑 这就是它的瓶颈,所以我们需要用nginx做负载均衡,用两个tomcat分摊压力,也可以做集群分摊压力。
2.nginx 动静分离,即正向代理处理静态资源,反向代理处理动态资源。
3.nginx 压缩机制,可以将过大的数据包或文件压缩,根据压缩级别压缩文件的大小,级别越高压缩越小,ps:cpu消耗也大
4.内置的健康检查功能:如果有一个服务器宕机,会做一个健康检查,再发送的请求就不会发送到宕机的服务器了。重新将请求提交到其他的节点上
5.接收用户请求是异步的:浏览器将请求发送到nginx服务器,它先将用户请求全部接收下来,再一次性发送给后端web服务器,极大减轻了web服务器的压力 一边接收web服务器的返回数据,一边发送给浏览器客户端
Nginx配置
对于 nginx我们只需要知道配置文件在conf文件夹下就可以,其他不需要我们操心,除非你要增加模块或自定义模块
http {
include mime.types;#引用默认文件
default_type application/octet-stream;#默认配置
#日志输出格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;#日志打印地址
sendfile on;#on/off 减少拷贝次数,提升文件传输性能的方法
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;#线程存活时间65s
#gzip 压缩
gzip on;
gzip_comp_level 4; #推荐先设置为中间的值,比如4或者5
gzip_proxied any; #off为关闭,any为压缩所有后端服务器返回的数据。
gzip_types text/plain application/x-javascript text/css application/xml; #一般情况下如此设置
gzip_vary on; #默认为off用于设置是否在使用gzip功能时发送带有"vary:Accept-Encoding" 头域的响应头部,该头域的主要功能时要告诉客户端数据已经在服务器进行了压缩
upstream netitcast.com { #服务器集群名字
server 127.0.0.1:8081 weight=1;#服务器配置 weight是权重的意思,权重越大,分配的概率越大。
server 127.0.0.1:8080 weight=2;
}
server {
listen 443;#端口号
server_name api.carbybus.com;#域名
ssl on;#开启ssl
ssl_certificate 214950803920621.pem; #证书pem
ssl_certificate_key 214950803920621.key; #证书key
ssl_session_timeout 5m;#指定客户端可以重用会话参数的时间(超时后不可使用)
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
#重点来咯
location / {#所有https的请求都到这里
charset utf-8;
# netitcast.com下面的名字要与upsteam后面的名字保持一致
proxy_pass http://netitcast.com; # 反向代理的地址
proxy_redirect default; #代理默认配置 以下是将请求的头传给tomcat
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {#通过80进来的是http请求
listen 80;
server_name api.carbybus.com; # 你的域名
rewrite ^(.*)$ https://$host$1 permanent;# 把http的域名请求转成https
}}
Tomcat配置
server.xml Tomcat配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- 原8005端口 用于关闭tomcat ps:telnet 到8005端口然后执行“SHUTDOWN”(区分大小写),此时也可看到tomcat后台在解析telnet上来的命令,然后果然tomcat被关闭了 -->
<Server port="8007" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<!--连接身份校验 登录tomcat后台时有用没有后台就没用-->
<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>
<Service name="Catalina">
<!-- Define an AJP 1.3 Connector on port 8009 -->
<!--端口8011 原8009 ,负责和其他的HTTP服务器建立连接。-->
<Connector port="8011" protocol="AJP/1.3" redirectPort="8443" />
<!--HTTPS端口号为443 http端口号为80,负责建立HTTP连接。-->
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol" URIEncoding="UTF-8"
SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS"
keystoreFile="/usr/service/apache-tomcat-8.5.35/conf/1564131_gps.carbybus.com.pfx" keystorePass="k7J7UwpP"
>
</Connector>
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<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>
catalina.sh/catalina.bat 一个servlet容器
具体内容我也看不懂~但是有些问题是需要通过修改catalina来解决1.windows 下启动tomcat闪退问题: 需要添加JAVA_HOME的地址解决
2.OutOfMemoryError: Java heap space (堆内存溢出),
OutOfMemoryError: PermGen space(永久保存区域溢出),
OutOfMemoryError: unable to create new native thread(无法创建新的线程),
添加:JAVA_OPTS='-Xms512m -Xmx1024m'
或者 JAVA_OPTS="-server -Xms800m -Xmx800m -XX:MaxNewSize=256m"
或者 CATALINA_OPTS="-server -Xms256m -Xmx300m"解决
自己如何实现tomcat
package clc.dispath.netty.common;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @ProjectName: cicada
* @Package: clc.dispath.netty.common
* @ClassName: TestSErver
* @Description: java类作用描述
* @Author: 孙志成
* @CreateDate: 2018/11/30 10:20
* @UpdateUser: 更新者
* @UpdateDate: 2018/11/30 10:20
* @UpdateRemark: 更新说明
* @Version: 1.0
*/
public class TestSErver {
public static void main(String[] args) throws IOException {
TestSErver testSErver=new TestSErver();
testSErver.start();
}
public void start() throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
Socket socket = null;
System.out.println("启动web服务");
while (true) {
socket = serverSocket.accept();
Thread thread = new Thread(new HttpServerThread(socket));
thread.start();
}
}
// 内部类
private class HttpServerThread implements Runnable {
Socket socket = null;
HttpServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
InputStream is = null;
OutputStream os = null;
BufferedReader br = null;
try {
is = this.socket.getInputStream();
os = this.socket.getOutputStream();
// 页面的请求
br = new BufferedReader(new InputStreamReader(is));
String line = br.readLine();
int i = 0;
while (null != line && br.ready()) {
line = br.readLine();
System.out.println("第" + i + "行信息:" + line);
i++;
}
// 页面的响应
String reply = "HTTP/1.1\n"; // 必须添加的响应头
reply += "Content-type:text/html\n\n"; // 必须添加的响应头
reply += "<h1>!@#!@#</h1>";
os.write(reply.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
os.close();
is.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}