2021-01-27 大数据课程笔记 day7

时间煮雨
@R星校长

Nginx
问题引入

在这里插入图片描述

单个 tomcat 支持最高并发
在这里插入图片描述
怎么解决高并发问题,解决单个服务器过载问题?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Nginx概述
Nginx 介绍

1、 Nginx (“engine x”) 是一个高性能的 静态HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。
2、 第一个公开版本0.1.0发布于2004年10月4日。
3、 其将源代码以类 BSD 许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名
4、 官方测试 nginx 能够支撑 5 万并发链接,并且 cpu、内存等资源消耗却非常低,运行非常稳定
5、 2011年6月1日,nginx 1.0.4 发布。apache httpd
6、 Nginx 是一款轻量级的 Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个 BSD-like 协议下发行。由俄罗斯的程序设计师 Igor Sysoev 所开发,其特点是占有内存少,并发能力强,事实上 nginx 的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用 nginx 网站用户有:新浪、网易、腾讯等。
在这里插入图片描述

Nginx 和 apache 的优缺点

nginx 相对于 apache 的优点:

1、	轻量级,同样起web 服务,比apache 占用更少的内存及资源 
2、	抗并发,nginx 处理请求是异步非阻塞(可参考文章https://zhuanlan.zhihu.com/p/82935440)的,而apache 则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能  NIO netty NIO
3、	高度模块化的设计,编写模块相对简单 
4、	社区活跃,各种高性能模块出品迅速
apache 相对于nginx 的优点:
1、	rewrite ,比nginx 的rewrite 强大 
2、	模块超多,基本想到的都可以找到 
3、	少bug ,nginx 的bug 相对较多 
4、	Nginx 配置简洁, Apache 复杂 
5、	最核心的区别在于apache是同步多进程模型,一个连接对应一个进程;nginx是异步的,多个连接(万级别)可以对应一个进程

在这里插入图片描述

Tengine介绍

tengine网址:http://tengine.taobao.org/
Tengine 是由淘宝网发起的 Web 服务器项目。它在 Nginx 的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine 的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的 Web 平台。

从2011年12月开始,Tengine 成为一个开源项目,Tengine 团队在积极地开发和维护着它。Tengine 团队的核心成员来自于淘宝、搜狗等互联网企业。Tengine 是社区合作的成果,我们欢迎大家参与其中,贡献自己的力量。

tengine和nginx性能测试:http://tengine.taobao.org/document_cn/benchmark_cn.html

1.	Tengine相比Nginx默认配置,提升200%的处理能力。
2.	Tengine相比Nginx优化配置,提升60%的处理能力。

tengine更详细参数解释详见:
http://tengine.taobao.org/nginx_docs/cn/docs/
由于 Nginx 使用更为普及,我们主要讲解 Nginx 。

Nginx下载与安装(已经讲-见day03)
Nginx下载

官网下载 Nginx 软件 http://nginx.org

Nginx 官方提供了三个类型的版本:

  Mainline Version:主线版,是最新版,但未经过过多的生产测试。
  Stable Version:稳定版,生产环境使用版本。
  Legacy Version:老版本。

我们需要下载的是 Stable Version。其中又分为两种版本:Linux 版与 Windows 版。开发时这两个版本我们都下载。Linux 版用于生产环境,而 Windows 版用于开发测试。

在这里插入图片描述
在这里插入图片描述

Nginx 的源码安装

安装前准备工作

克隆一个没有安装其它软件的纯净主机。完成以下配置:

 1.修改主机名:vim /etc/sysconfig/network
[root@nginx1 ~]# hostname nginx1
[root@nginx1 ~]# vim /etc/sysconfig/network
HOSTNAME  nginx1
 2.修改网络配置:vim /etc/sysconfig/network-scripts/ifcfg-eth0
   192.168.20.95
安装 Nginx
  1. 安装源码编译以及 Nginx 依赖的库
yum install gcc gcc-c++ pcre  pcre-devel openssl openssl-devel zlib  zlib-devel vim -y
  1. 创建存放源文件的文件夹
首先在目录 /opt 下创建 apps 目录,用于存放源文件以及解压后的文件
  1. 上传 Nginx 到 2 创建的目录

  2. 解压 Nginx

[root@nginx1 apps]# pwd
/opt/apps
[root@nginx1 apps]# ls
nginx-1.16.1.tar.gz
[root@nginx1 apps]# tar -zxvf nginx-1.16.1.tar.gz

进入到 /opt/apps 目录中的 Nginx 解压包目录,查看 Nginx 的目录。
其中各个目录中存放的文件作用为:

  auto:存放 Nginx 自动安装的相关文件
  conf:存放 Nginx 服务器配置文件
  configure:命令,用于对即将安装的软件的配置,完成 Makefile 编译文件的生成
  contrib:存放由其他机构贡献的文档材料
  html:存放 Nginx 欢迎页面
  man:manual,手册,存放 Nginx 帮助文档
  src:存放 Nginx 源码
  1. 生成 Makefile
    在 Nginx 解压目录下运行 make 命令,用于完成编译。但此时会给出提示:没有指定目标,并且没有发现编译文件 makefile。编译命令 make 需要根据编译文件 makefile 进行编译,所以在编译之前需要先生成编译文件 makefile。使用 configure 命令可以生成该文件。那么,configure 命令需要配置些什么参数呢?使用 --help 可以查看到可以使用的参数说明。这些参数可以分为三类:
第一类:基本信息的配置。
第二类:默认没有安装,可以指定安装的模块,使用--with 开头。Nginx 的高扩展性就
体现在这里。
第三类:默认已经安装,可以指定卸载的模块,使用--without 开头。

下面是简单配置的命令执行。命令中每一行的最后添加了反斜杠\表示当前命令并未结束,回车不会执行该命令。执行成功后,会给出配置报告。下面以安装对 https 访问协议支持的模块 http_ssl_module 为例。

--prefix:用于指定 nginx 的安装目录。注意,安装目录与解压目录不一样。
  --http_ssl_module:https 访问协议需要安装 Http 安全连接协议模块 SSL(Secure SocketsLayer,安全套接层)。注意,在执行过 configure 命令后并不会立即生成/usr/local/nginx 目录,也不会马上开始安装指定的模块,而仅仅是将命令中指定的参数及默认配置写入到即将要生成的 Makefile文件中。
配置报告以两部分构成:第一部分给出了配置的系统库;第二部分给出了系统配置信息。
  path prefix:Nginx 安装目录
  binary file:Nginx 命令文件
  modules path:Nginx 模块存放路径
  configuration prefix:Nginx 配置文件存放路径
  configuration file:Nginx 配置文件名
  pid file:Nginx 的进程 id 文件
  error log file:错误日志文件
  http access log file:http 访问日志文件;
  http xxx:其它 http 请求相关的文件。

配置成功后,再次查看 Nginx 解压目录,发现其中多出了一个文件 Makefile。后面的编译就是依靠该文件进行的。

[root@nginx1 nginx-1.16.1]# mkdir –p /var/tmp/nginx/client
[root@nginx1 nginx-1.16.1]# pwd
/opt/apps/nginx-1.16.1
[root@nginx1 nginx-1.16.1]# ./configure \
  --prefix=/opt/nginx \
  --sbin-path=/usr/sbin/nginx\
  --conf-path=/etc/nginx/nginx.conf \
  --error-log-path=/var/log/nginx/error.log \
  --http-log-path=/var/log/nginx/access.log \
  --pid-path=/var/run/nginx/nginx.pid \
  --lock-path=/var/lock/nginx.lock \
  --user=nginx \
  --group=nginx \
  --with-http_ssl_module \
  --with-http_flv_module \
  --with-http_stub_status_module \
  --with-http_gzip_static_module \
  --http-client-body-temp-path=/var/tmp/nginx/client/ \
  --http-proxy-temp-path=/var/tmp/nginx/proxy/ \
  --http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \
  --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \
  --http-scgi-temp-path=/var/tmp/nginx/scgi \
  --with-pcre  

注意: /var/tmp/nginx/client 目录需要手动创建

也可以使用简单安装,指定安装目录和 https 访问支持:

./configure --prefix=/opt/nginx --with-http_ssl_module --with-http_gzip_static_module --error-log-path=/var/log/nginx/nginx.log --pid-path=/var/log/nginx/pid
  1. 编译安装
    这是两个命令,make 为编译命令,make install 为安装命令,可以分别执行。这里使用 && 将两个命令连接执行,会在前面命令执行成功的前提下才会执行第二个命令。
make && make install
  1. nginx 命令随处可用
    在 Nginx 的安装目录 /opt/nginx 中有一个 sbin 目录,其中存放着 nginx 的命令程序 nginx。默认情况下,若要使用 nginx 命令,则必须要在 /opt/nginx/sbin 目录中,或指定命令路径,使用起来很不方便。为了能够在任意目录下均可直接执行 nginx 命令,可通过以下两种方式完成。
    方式一 、 修改 /etc/profile 文件
    在 /etc/profile 文件最后添加以下内容,将安装目录下的 sbin 目录添加到 PATH 系统环境变量中。然后再重新加载该文件即可。
#修改环境变量
export PATH=$PATH:/usr/sbin/nginx  #注意执行文件的位置
useradd nginx  #添加用户(默认添加nginx用户组)
nginx  #启动nginx

方式二 、 添加安装的 nginx 到服务列表:将如下内容添加到 /etc/init.d/nginx 脚本中,nginx 需要具有可执行权限。

[root@nginx1 nginx-1.16.1]# vim /etc/init.d/nginx

少参数版本

#!/bin/sh
#
# nginx - this script starts and stops the nginx daemon
#
# chkconfig:   - 85 15 
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
 
# Source function library.
. /etc/rc.d/init.d/functions
 
# Source networking configuration.
. /etc/sysconfig/network
 
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0
 
nginx="/opt/nginx/sbin/nginx"
prog=$(basename $nginx)
 
NGINX_CONF_FILE="/opt/nginx/conf/nginx.conf"
 
[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx
 
lockfile=/var/lock/subsys/nginx
 
make_dirs() {
   # make required directories
   user=`nginx -V 2>&1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -`
   options=`$nginx -V 2>&1 | grep 'configure arguments:'`
   for opt in $options; do
       if [ `echo $opt | grep '.*-temp-path'` ]; then
           value=`echo $opt | cut -d "=" -f 2`
           if [ ! -d "$value" ]; then
               # echo "creating" $value
               mkdir -p $value && chown -R $user $value
           fi
       fi
   done
}
 
start() {
    [ -x $nginx ] || exit 5
    [ -f $NGINX_CONF_FILE ] || exit 6
    make_dirs
    echo -n $"Starting $prog: "
    daemon $nginx -c $NGINX_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}
 
stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}
 
restart() {
    configtest || return $?
    stop
    sleep 1
    start
}
 
reload() {
    configtest || return $?
    echo -n $"Reloading $prog: "
    killproc $nginx -HUP
    RETVAL=$?
    echo
}
 
force_reload() {
    restart
}
 
configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}
 
rh_status() {
    status $prog
}
 
rh_status_q() {
    rh_status >/dev/null 2>&1
}
 
case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
        exit 2
esac

修改 nginx 文件的执行权限

chmod +x nginx

添加该文件到系统服务中去

chkconfig --add nginx

查看是否添加成功

chkconfig --list nginx

启动,停止,重新装载

service nginx start|stop|reload 

设置开机启动

[root@nginx1 conf]# chkconfig nginx on
[root@nginx1 conf]# chkconfig
nginx          	0:off	1:off	2:on	3:on	4:on	5:on	6:off
Nginx 的工作模型
Master-Worker模式

1、Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程。
2、Master 接收来自外界的信号,向各 worker 进程发送信号,每个进程都有可能来处理这个连接。
3、Master 进程能监控 Worker 进程的运行状态,当 worker 进程退出后(异常情况下),会自动启动新的 worker 进程。
在这里插入图片描述

accept_mutex

由于所有子进程都继承了父进程的 sockfd,那么当连接进来时,所有子进程都将收到通知并“争着”与它建立连接,这就叫“惊群现象”。大量的进程被激活又挂起,只有一个进程可以 accept() 到这个连接,这当然会消耗系统资源。Nginx 提供了一个 accept_mutex 加在 accept 上的一把共享锁。即每个 worker 进程在执行 accept 之前都需要先获取锁,获取不到就放弃执行 accept() 。有了这把锁之后,同一时刻,就只会有一个进程去 accpet() ,这样就不会有惊群问题了。

当一个 worker 进程在 accept() 这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,完成一个完整的请求。一个请求,完全由 worker 进程来处理,而且只能在一个 worker 进程中处理。

为什么使用进程不使用线程?

1、节省锁带来的开销。每个worker进程都是独立的进程,不共享资源,不需要加锁。同时在编程以及问题查上时,也会方便很多。
2、独立进程,减少风险。采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,master进程则很快重新启动新的worker进程。当然,worker进程的也能发生意外退出。

如何处理并发请求?

每进来一个 request,会有一个 worker 进程去处理。但不是全程的处理,处理到什么程度呢?处理到可能发生阻塞的地方,比如向上游(后端)服务器转发 request ,并等待请求返回。那么,这个处理的 worker 不会这么傻等着,他会在发送完请求后,注册一个事件:“如果 upstream 返回了,告诉我一声,我再接着干”。于是他就休息去了。此时,如果再有 request 进来,他就可以很快再按这种方式处理。而一旦上游服务器返回了,就会触发这个事件,worker 才会来接手,这个 request 才会接着往下走。由于 web server 的工作性质决定了每个 request 的大部份生命都是在网络传输中,实际上花费在 server 机器上的时间片不多,这就是几个进程就能解决高并发的秘密所在。

Nginx参数详解
nginx.conf 配置文件全览
#号是注释。
#---全局块开始----
#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;
#----全局块结束----

#====events块开始====
events {
    worker_connections  1024;
}
#====events块结束====
#****http块开始****
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块结束****

nginx 由三部分组成:

第一部分:全局块

从配置文件开始到 events 之间的内容,主要会设置一些影响 nginx 服务器整体运行的配置命令。主要包括配置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以及配置文件的引入等。

#user  nobody; 
worker_processes  1; 
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#pid        logs/nginx.pid;

worker_processes 是 Nginx 服务器并发处理服务的关键配置,值越大,可以支持的并发处理量也越多,但是会受到硬件、软件等设备的制约。
error_log 配置 nginx 日志文件的全路径名
pid 配置进程 PID 存放路径

第二部分:events块
events {
    worker_connections  1024;
}

events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否允许同时接受多个网络连接,选取哪种事件驱动模型来处理连接请求,每个work process可以同时支持的最大连接数等。
上述的例子表示每个 work process 支持的最大连接数为 1024 。这部分的配置对 Nginx 的性能影响比较大,在实际中应该灵活配置。

第三部分:http 块{ }

这是 Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。需要注意的是:http 块也可以包括 http 全局块、server 块。

http 全局块

http 全局块配置的指令包括文件引入、MIME-TYPE定义、连接超时时间、单链接请求数上限等。

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;
    #tcp_nopush     on;
    #keepalive_timeout  0;
    keepalive_timeout  65;#连接超时时间

    #gzip  on;#是否启动压缩
    server {
    ......
    }
  }
server块

这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本。
每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机。而每个 server 块也分为全局 server 块,以及可以同时包含多个 location 块。

#gzip  on;
    server {
        listen       80;#监听的端口号
        server_name  localhost;#监听的域名
        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / { #路径中包含 /
            root   html;
            index  index.html index.htm;
        }
        #error_page  404              /404.html;
        # redirect server error pages to the static page /50x.html
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /$.ht {
        #    deny  all;
        #}
    }
全局 server 块

最常见的配置是本虚拟主机的监听配置和本虚拟主机的名称或IP配置。

location块

一个 server 块可以配置多个 location 块。
这块的主要作用是基于 Nginx 服务器接受到的请求字符串(例如 server_name/uri-string),对虚拟主机名称(也可以是 IP 别名)之外的字符串(列如 前面的 /uri-string)进行匹配,对特定的请求进行处理。地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。

工作模式与连接数上限
#user  nobody;
worker_processes  1;
events {
use epoll;
worker_connections 1024;
}
  1. 用户与工作进程
#user  nobody;
worker_processes  1;
[root@nginx1 conf]# ps aux |grep nginx
root       1170  0.0  0.0  22568   680 ?        Ss   09:14   0:00 nginx: master process /opt/nginx/sbin/nginx -c /opt/nginx/conf/nginx.conf
nobody     1171  0.0  0.1  23020  1288 ?        S    09:14   0:00 nginx: worker process                              
root       1174  0.0  0.0 103264   876 pts/0    S+   09:14   0:00 grep nginx
[root@nginx1 conf]# ps aux |grep nginx
root       1170  0.0  0.0  22568   680 ?        Ss   09:14   0:00 nginx: master process /opt/nginx/sbin/nginx -c /opt/nginx/conf/nginx.conf
nobody     1171  0.0  0.1  23020  1288 ?        S    09:14   0:00 nginx: worker process                              
 [root@nginx1 conf]# id nobody
uid=99(nobody) gid=99(nobody) groups=99(nobody)
[root@nginx1 conf]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
……
nobody:x:99:99:Nobody:/:/sbin/nologin
  1. use epoll;
参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ];  epoll 模型是 Linux 2.6 以上版本内核中的高性能网络 I/O 模型,如果跑在 FreeBSD 上面,就用 kqueue 模型。
uname -a :查看服务器系统相关的信息
  1. worker_connections 1024;
单个后台 worker process 进程的最大并发链接数。
并发总数是 worker_processes 和 worker_connections 的乘积
     即 max_clients = worker_processes * worker_connections
在设置了反向代理的情况下,max_clients=worker_processes * worker_connections / 4

为什么上面反向代理要除以4,应该说是一个经验值
    # worker_connections 值的设置跟物理内存大小有关
    # 因为并发受IO约束,max_clients的值须小于系统可以打开的最大文件数

系统可以打开的最大文件数和内存大小成正比,一般 1GB 内存的机器上可以打开的文件数大约是10万左右

    # 我们来看看360M内存的VPS可以打开的文件句柄数是多少:
    # $ cat /proc/sys/fs/file-max
    # 输出 34336
    # 32000 < 34336,即并发连接总数小于系统可以打开的文件句柄总数,这样就在操作系统可以承受的范围之内  5   16G *9.7w
    # worker_connections 的值需根据 worker_processes 进程数目和系统可以打开的最大文件总数进行适当地进行设置
    # 使得并发总数小于操作系统可以打开的最大文件数目
    # 其实质也就是根据主机的物理CPU和内存进行配置
    # 当然,理论上的并发总数可能会和实际有所偏差,因为主机还有其他的工作进程需要消耗系统资源。
    # ulimit -SHn 65535  设置可以打开的文件数量
开启零拷贝

在这里插入图片描述

sendfile 实际上是 Linux2.0+ 以后的推出的一个系统调用,web 服务器可以通过调整自身的配置来决定是否利用 sendfile 这个系统调用。先来看一下不用 sendfile 的传统网络传输过程:

read(file,tmp_buf, len);
write(socket,tmp_buf, len);

硬盘 >> kernel buffer >> user buffer>> kernel socket buffer >>协议栈
在这里插入图片描述

一个基于 socket 的服务,首先读硬盘数据,然后写数据到 socket 来完成网络传输的。上面2行用代码解释了这一点,不过上面2行简单的代码掩盖了底层的很多操作。来看看底层是怎么执行上面2行代码的:

1、系统调用 read()产生一个上下文切换:从 user mode 切换到 kernel mode,然后 DMA 执行拷贝,把文件数据从硬盘读到一个 kernel buffer 里。

2、数据从kernel buffer拷贝到user buffer,然后系统调用 read() 返回,这时又产生一个上下文切换:从kernel mode 切换到 user mode。

3、 系统调用write()产生一个上下文切换:从 user mode切换到 kernel mode,然后把步骤2读到 user buffer的数据拷贝到 kernel buffer(数据第2次拷贝到 kernel buffer),不过这次是个不同的 kernel buffer,这个 buffer和 socket相关联。

4、系统调用 write()返回,产生一个上下文切换:从 kernel mode 切换到 user mode ,然后 DMA 从 kernel buffer拷贝数据到协议栈。

上面 4 个步骤有 4 次上下文切换,有 4 次拷贝,我们发现如果能减少切换次数和拷贝次数将会有效提升性能。在 kernel2.0+ 版本中,系统调用 sendfile() 就是用来简化上面步骤提升性能的。sendfile() 不但能减少切换次数而且还能减少拷贝次数。

再来看一下用 sendfile()来进行网络传输的过程:

sendfile(socket,file, len);

硬盘 >> kernel buffer (快速拷贝到kernelsocket buffer) >>协议栈

1、 系统调用sendfile()通过 DMA把硬盘数据拷贝到 kernel buffer,然后数据被 kernel直接拷贝到另外一个与 socket相关的 kernel buffer。这里没有 user mode和 kernel mode之间的切换,在 kernel中直接完成了从一个 buffer到另一个 buffer的拷贝。

2、DMA 把数据从 kernelbuffer 直接拷贝给协议栈,没有切换,也不需要数据从 user mode 拷贝到 kernel mode,因为数据就在 kernel 里。

简单说,sendfile 是个比 read 和 write 更高性能的系统接口, 不过需要注意的是,sendfile 是将 in_fd 的内容发送到 out_fd 。而 in_fd 不能是 socket , 也就是只能文件句柄。 所以当 Nginx 是一个静态文件服务器的时候,开启 SENDFILE 配置项能大大提高 Nginx 的性能。 但是当 Nginx 是作为一个反向代理来使用的时候,SENDFILE 则没什么用了,因为 Nginx 是反向代理的时候。 in_fd 就不是文件句柄而是 socket,此时就不符合 sendfile 函数的参数要求了。

keepalive_timeout

在这里插入图片描述
测试时改为 0 ,便于看出负载切换的效果,部署到生产前进行优化来提高效率。

是否启用压缩

在这里插入图片描述
压缩可以有效减少文件的大小,有利于网络传输。

autoindex
autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。
nginx虚拟主机演示

在这里插入图片描述

虚拟主机,就是将一台物理服务器虚拟为多个服务器来使用,从而实现在一台服务器上配置多个站点,即可以在一台物理主机上配置多个域名。Nginx 中,一个 server 标签就是一台虚拟主机,配置多个 server 标签就虚拟出了多台主机。Nginx 虚拟主机的实现方式有两种:域名虚拟方式与端口虚拟方式。域名虚拟方式是指不同的虚拟机使用不同的域名,通过不同的域名虚拟出不同的主机;端口虚拟方式是指不同的虚拟机使用相同的域名不同的端口号,通过不同的端口号虚拟出不同的主机。基于端口的虚拟方式不常用。
在这里插入图片描述

  1. 修改 nginx.conf 文件
    gzip  on;
    server {
       listen  80;
       server_name www.sxthenhao.com;
       location / {
           root /mnt;
           autoindex on;
       }
    }
    server {
        listen       80;
        server_name www.123.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }
......

重新加载 nginx

[root@nginx1 conf]# service nginx reload
  1. 修改本机hosts文件(C:\Windows\System32\drivers\etc)
192.168.20.11 nginx1 www.123.com  www.sxthenhao.com
  1. 访问测试
    在这里插入图片描述
    在这里插入图片描述

自动提供了一个欢迎页面,由于 /mnt 下什么也没有挂载,所以列表中什么也没有。
4. 为/mnt挂载,并重新测试

[root@nginx1 conf]# mount /dev/cdrom /mnt

在这里插入图片描述
对比下图
在这里插入图片描述

日志配置

Nginx 还可以作为日志服务器

[root@nginx1 logs]# pwd
/opt/nginx/logs
 [root@nginx1 logs]# tail -f access.log

本地浏览器访问:http://www.123.com/2019-12-03maxwd19

先不管 404 的问题,查看日志多了一条记录
在这里插入图片描述
修改一下http://www.123.com/2019-12-04maxwd20,日志又记录一条
在这里插入图片描述
当然日志格式我们也可以自定义
在这里插入图片描述
access_log 配置 http 下,多 server 公用,配置 http-> 某 server 下,仅对该 server 使用。
在这里插入图片描述
http://www.sxthenhao.com/2019-12-04maxwd20myfmt.log 日志记录多一条

http://www.123.com/2019-12-04maxwd20 日志记录 access.log 多一条(并没有使用 myfmt.log )

Location(重点)

参考:
http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_core_module.html

语法

    location [ = | ~ | ~* | ^~ ] uri { ... }
    location @name { ... }

默认值 -
上下文 server, location

让我们用一个例子解释上面的说法:

location = / {
    [ configuration A ]
}

location / {
    [ configuration B ]
}

location /documents/ {
    [ configuration C ]
}

location ^~ /images/ {
    [ configuration D ]
}

location ~* \.(gif|jpg|jpeg)$ { 
    [ configuration E ] 
} 
请求“/”匹配配置A,
请求“/index.html”匹配配置B, 
请求“/documents/document.html”匹配配置C,
请求“/images/1.gif”匹配配置D, 
请求“/documents/1.jpg”匹配配置E。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 修改 nginx.conf 配置文件
  server {
       listen  80;
       server_name www.sxthenhao.com;
       access_log   logs/myfmt.log  myfmt;
       location / {
           root /mnt;
           autoindex on;
       }
       location /ooxx {
          proxy_pass http://192.168.20.92/;#带上/访问该url对应的首页,
#不带/ 访问http://192.168.20.92/ooxx
       }
    }
  1. 重新加载 nginx
[root@nginx1 conf]# !ser

在这里插入图片描述

  1. 访问测试
    http://www.sxthenhao.com/ooxx
    在这里插入图片描述

  2. 修改 nginx.conf

  location /ooxx {
      proxy_pass http://www.baidu.com/;
   }
  1. 重启 nginx

[root@nginx1 conf]# !ser

如果重启没有问题,直接跳步骤7.
如果出现下图所示的错误:
在这里插入图片描述
找不到域名,也就是访问不到域名解析服务器。
解决办法:
在这里插入图片描述

  1. 访问测试 http://www.sxthenhao.com/ooxx
    在这里插入图片描述

虽然访问到了百度,但是确实通过重定向的方式,以后发生的事情和我们的服务器就没有半毛钱关系了。优化配置 nginx.conf:
#尽量在服务器端跳转,不要在客户端跳转

proxy_pass https://www.baidu.com/;

重启 nginx,再次测试,地址栏没有重定向,但是当我们查询(比如:ssd )时出现
在这里插入图片描述

修改 nginx.conf

       location /ooxx {
          proxy_pass http://www.baidu.com/;
       }     
		location ~* /s.* {
          proxy_pass https://www.baidu.com;
       }
Bug https protocol requires SSL support in
[root@nginx1 conf]# service nginx reload
nginx: [emerg] https protocol requires SSL support in /opt/nginx/conf/nginx.conf:45
nginx: configuration file /opt/nginx/conf/nginx.conf test failed

当初编译的时候没有启用 SSL 支持,在配置反向代理到 https 的网站时,编辑配置文件报错,无法启动 nginx。
解决办法:先将 nginx.conf 备份 /root/ 目录下,删除 /opt/nginx和/opt/apps/
nginx-1.16.1 ,然后在解压一份,最后编译安装。

[root@nginx1 nginx-1.16.1]# ./configure --prefix=/opt/nginx --with-http_ssl_module
[root@nginx1 nginx-1.16.1]# make && make install
[root@nginx1 nginx-1.16.1]# cd /opt/nginx/conf/
[root@nginx1 conf]# cp /root/nginx.conf  ./
cp: overwrite `./nginx.conf'? yes
[root@nginx1 conf]# service nginx reload
nginx: the configuration file /opt/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /opt/nginx/conf/nginx.conf test is successful
Reloading nginx:     

然后再访问 http://www.sxthenhao.com/ooxx
在这里插入图片描述

反向代理

代理服务器根据其代理对象的不同,可以分为正向代理服务器与反向代理服务器。这里
的“正”与“反”均是站在客户端角度来说的。

正向代理服务器

正向代理是对客户端的代理。客户端 C 想要从服务端 S 获取资源,但由于某些原因不能,直接访问服务端,而是通过另外一台主机 P 向服务端发送请求。当服务端处理完毕请求后,将响应发送给主机 P,主机 P 在接收到来自服务端的响应后,将响应又转给了客户端 C。此时的主机 P,就称为客户端 C 的正向代理服务器。

客户端在使用正向代理服务器时是知道其要访问的目标服务器的地址等信息的。正向代理服务器是为服务用户(客户端)而架设的主机,与服务端无关,对服务器端透明。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

反向代理服务器

反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
在这里插入图片描述
在这里插入图片描述

反向代理之负载均衡

在这里插入图片描述

负载均衡(Load Balancing):就是将对请求的处理分摊到多个操作单元上进行。这个均衡是指在大批量访问前提下的一种基本均衡,并非是绝对的平均。对于 Web 工程中的负载均衡,就是将相同的 Web 应用部署到多个不同的 Web 服务器上,形成多个 Web 应用服务器。当请求到来时,由负载均衡服务器负责将请求按照事先设定好的比例向 Web 应用服务器进行分发,从而增加系统的整体吞吐量。
负载均衡可以通过负载均衡软件实现,也可通过硬件负载均衡器实现。
(1 ) 硬件负载均衡
硬件负载均衡器的性能稳定,且有生产厂商作为专业的服务团队。但其成本很高,一台硬件负载均衡器的价格一般都在十几万到几十万,甚至上百万。知名的负载均衡器有 F5、Array、深信服、梭子鱼等。
在这里插入图片描述

(2 ) 软件负载均衡
软件负载均衡成本几乎为零,基本都是开源软件。例如:LVS、HAProxy、Nginx 等。

该机群包含一台 Nginx 服务器,两台 Web服务器(node2和node3)。
修改nginx.conf文件

  upstream rss{
        server 192.168.20.92;
        server 192.168.20.93;
    }
    server {
       listen  80;
       server_name www.sxthenhao.com;
       access_log   logs/myfmt.log  myfmt;
       location / {
           root /mnt;
           autoindex on;
       }
       location /toms {
           proxy_pass http://rss/;
       }

重启nginx,请求测试:http://www.sxthenhao.com/toms,发现已经实现了负载均衡。(中小企业一般使用该方式)
Node2和node3上:
安装httpd应用:

yum install httpd -y

进入/var/www/html,创建一个index.html
加入:from 192.168.20.92 node2
或:from 192.168.20.93 node3
启动httpd服务:service httpd start

也可以通过在Nginx服务器上配置hosts本地域名解析:

[root@nginx1 conf]# vim /etc/hosts

192.168.20.91 node1
192.168.20.92 node2  xxx
192.168.20.93 node3  xxx
192.168.20.94 node4

修改 nginx.conf 配置文件,添加如下配置

location /cats {
       proxy_pass http://xxx/;
   }

重启nginx,测试:http://www.sxthenhao.com/cats
一样能够实现负载均衡的目的(大型企业使用该方式,一般还会搭建一个DNS域名解析服务器,只需要修改DNS域名解析服务器就ok了)。
Nginx会用到域名解析,如果一个域名解析出多个ip地址,会在这些ip地址之间做负载均衡。

Nginx调优
worker_processes 的设置

打开 nginx.conf 配置文件,可以看到 worker_processes 的默认值为 1。
在这里插入图片描述
worker_processes,工作进程,用于指定 Nginx 的工作进程数量。该值应该设置为多少合适呢?其数值一般设置为 CPU 内核数量,或内核数量的整数倍。注意,现代的 CPU 一般都是多核的,即一块 CPU 中包含多个内核。若当前系统具有 2 块 CPU,而每块 CPU 中包含 2 个内核,那么,worker_processes 的值一般可以设置为 4 或 8。当然,也可以设置为 2。
不过需要注意,该值不仅仅取决于 CPU 内核数量,还与硬盘数量及负载均衡模式相关。
在不确定时可以指定其值为 auto。

worker_cpu_affinity 的设置

为了进一步提高系统性能,我们会将 worker 进程与具体的内核进行绑定。该绑定操作是通过 worker_cpu_affinity 属性进行设置的。affinity,密切关系。不过,若指定 worker_processes 的值为 auto,则无法设置 worker_cpu_affinity。
该设置是通过二进制进行的。每个内核使用一个二进制位表示,0 代表内核关闭,1 代
表内核开启。也就是说,有几个内核,就需要使用几个二进制位。下面通过几个例子来增进对 worker_processes 与 worker_cpu_affinity 的理解。
在这里插入图片描述

1.8 session共享
在这里插入图片描述

http协议是无状态的,即你连续访问某个网页100次和访问1次对服务器来说是没有区别对待的,因为它记不住你。那么,在一些场合,确实需要服务器记住当前用户怎么办?比如用户登录邮箱后,接下来要收邮件、写邮件,总不能每次操作都让用户输入用户名和密码吧,为了解决这个问题,session的方案就被提了出来,事实上它并不是什么新技术,而且也不能脱离http协议以及任何现有的web技术
session的常见实现形式是会话cookie(session cookie),即未设置过期时间的cookie,这个cookie的默认生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。实现机制是当用户发起一个请求的时候,服务器会检查该请求中是否包含sessionid,如果未包含,则系统会创造一个名为JSESSIONID的输出 cookie返回给浏览器(只放入内存,并不存在硬盘中),并将其以HashTable的形式写到服务器的内存里面;当已经包含sessionid是,服务端会检查找到与该session相匹配的信息,如果存在则直接使用该sessionid,若不存在则重新生成新的 session。这里需要注意的是session始终是有服务端创建的,并非浏览器自己生成的。 但是浏览器的cookie被禁止后session就需要用get方法的URL重写的机制或使用POST方法提交隐藏表单的形式来实现
首先我们应该明白,为什么要实现共享,如果你的网站是存放在一个机器上,那么是不存在这个问题的,因为会话数据就在这台机器,但是如果你使用了负载均衡把请求分发到不同的机器呢?这个时候会话id在客户端是没有问题的,但是如果用户的两次请求到了两台不同的机器,而它的session数据可能存在其中一台机器,这个时候就会出现取不到session数据的情况,于是session的共享就成了一个问题。

session一致性解决方案

1、session复制
tomcat 本身带有复制session的功能。(基本不用)
2、共享session
需要专门管理session的软件,
memcached 缓存服务,可以和tomcat整合,帮助tomcat共享管理session。

在这里插入图片描述

安装 jdk, tomcat, memcached
node2和node3上安装jdk和tomcat
[root@node2 apps]# rpm -ivh jdk-7u80-linux-x64.rpm
[root@node2 apps]# find / -name '*java*'

#可以看出/usr/java/jdk1.7.0_80/
配置环境变量

[root@node2 jdk1.7.0_80]# vim /etc/profile

加入以下两行代码:

export JAVA_HOME=/usr/java/jdk1.7.0_80
export PATH=$PATH:$JAVA_HOME/bin

让文件生效:

[root@node2 apps]# source /etc/profile
[root@node2 apps]# jps

13894 Jps #说明jdk安装配置成功

解压apache-tomcat-7.0.69.tar.gz
修改ROOT/index.jsp,dG全删后,添加:
from 192.168.20.102 session=<%=session.getId()%>
另外一台同样的安装配置操作。
然后分别访问node2和node3都可以正常,刷新session也不会变。
修改nginx.conf

    upstream rss {
        server 192.168.20.102:8080;
        server 192.168.20.103:8080;
}

访问测试 http://www.sxthenhao.com/toms,刷新 session 一直改变。

nginx1上安装memcached

1、 安装libevent
a) yum install libevent -y
2、 安装memcached
a) yum install memcached -y
3、启动memcached

memcached -d -m 128m -p 11211 -l 192.168.20.95 -u root -P /opt/
-d:后台启动服务
-m:缓存大小
-p:端口
-l:IP
-P:服务器启动后的系统进程ID,存储的文件
-u:服务器启动是以哪个用户名作为管理用户
配置session共享

1、拷贝jar到tomcat的lib下,jar包见附件
2、配置tomcat,每个tomcat里面的context.xml中加入

<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" 
	memcachedNodes="n1:192.168.20.95:11211" 
    sticky="false" 
    lockingMode="auto"
    sessionBackupAsync="false"
	requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
    sessionBackupTimeout="1000" transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory" 
/>

tomcat添加jar包和配置信息之后需要重启

反向代理之动静分离

在这里插入图片描述

Nginx 动静分离简单来说就是把动态和精通请求分开,不能理解成知识单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求和静态请求分开,可以理解成使用Nginx处理静态页面,Tomcat处理动态页面。
动静分离从目前实现方式大致分为两种:
一是纯粹的把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案。
二是动态和静态文件混合在一起发布,通过nginx分开。通过location指定不同的后缀名实现不同的请求转发。
在这里插入图片描述

动静分离具体实现

  1. index.jsp 修改

node2

<link rel="stylesheet" type="text/css" href="/css/index.css">
<img src="/image/logo.jpg" ><br/>
<font class="myfont">
from 192.168.20.92 <br/> 
 session=<%=session.getId()%></font>

node3

<link rel="stylesheet" type="text/css" href="/css/index.css">
<img src="/image/logo.jpg" ><br/>
<font class="myfont">
from 192.168.20.83 <br/> 
session=<%=session.getId()%></font>
  1. 从nginx1克隆nginx2,修改/etc/udev/ rules.d/70-persistent-net.rules
    [
root@nginx2 rules.d]# pwd
/etc/udev/rules.d
[root@nginx2 rules.d]# vim 70-persistent-net.rules

将原来的 eth0 一行删掉(dd),并将 eth0 ,改为 eth1

  1. 在 nginx2 服务器上创建目录 /data/image 和 /data/css,然后将 logo.jpg 和 index.css 上传到对应的目录
[root@nginx2 rules.d]# mkdir -p /data/image  /data/css
  1. 并修改 nginx2 服务器上的 nginx.conf 配置文件
 [root@nginx2 rules.d]# vim /opt/nginx/conf/nginx.conf
  server {
       listen  80;
       server_name 192.168.20.96;
       location / {
           root /mnt;
           autoindex on;
       }
       location /image {
           root /data;
       }
       location /css {
           root /data;
       }
    }
  1. 修改 nginx1 服务器上的 nginx.conf 配置文件
 server {
       listen  80;
       server_name www.sxthenhao.com;
       location / {
           proxy_pass http://rss/;
       }
       location /image/ {
           proxy_pass http://192.168.20.96;
       }
       location /css/ {
           proxy_pass http://192.168.20.96;
       }
    }

然后重新加载 nginx

  1. 浏览器测试 http://www.sxthenhao.com

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
源码简介: 1.网站信息设置:网站名称,网站地址,站长邮箱,备案ICP,站长QQ,版权信息。 2.广告管理:首页和分类页ads01-ads10 10个广告位置,可自由修改;首页推荐栏文字广告;竞价广告。 3.新站登陆打开与关闭(网站维护时可关闭)、新站登陆验证码识别 4.网站点入和点出统计 5.后台目录名字建议修改,以确保安全! 6.常用软件管理:内置16个软件链接,可以修改软件名字、地址、logo、排序等! 名站导航管理:内置53个名站链接,可以修改名站名字、地址、注释、颜色、排序等! 实用查询管理:内置24个实用查询,可以修改查询工具名字、地址、注释、颜色、排序等! 管理帐号设置:更改当前管理员帐号/密码 查看防注入记录,清空防注入记录 7.√赞助链接管理(方便站长卖链接):内置8个赞助链接,可以修改赞助链接名字、地址、位置(首页/内页)、到期时间、颜色、排序等! 8.网站分类管理:类别添加管理、类别删除管理、类别修改管理、类别拼音转换(重要!) 9.网址管理系统:添加网址链接、站长添加网站列表、用户添加网站列表、用户添加未审网站、有来路未审核网站、报错网站管理、黑名单网站管理、站内网站搜索 10.模版修改管理:分类页面模板、首页页面模板、关于本站页模板、联系本站页模板、使用帮助页模板、公益活动页模板、网址推荐页模板、友情连接页模板、常用软件页模板、竞价推荐页模板等修改/删除  11.生成静态页管理:生成分类页面、生成生成主页及其他页 12.数据库管理:备份数据库、恢复数据库、压缩数据库 13.全站样式与内容分类,标签调用 14.div布局,CSS控制样式,访问速度更快! 注:程序核心:晓宇网址导航系统

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值