这篇文章并不是一个nginx大而全的内容,他更加针对初学者,针对前端开发同学,希望能够帮助从来没有了解过nginx的朋友,能够快速了解nginx的简单功能,他的安装,他的配置语法,能够让大家快速搭建一个简单的web服务器,再来体会他强大的一个功能。
很多人可能或多或少了解过nginx,即使你没有使用过nginx,但是你可能用node搭建过简单的web服务器,写过一些简单的动态页面,这些功能nginx都可以实现。说得简单点nginx就是一个服务。和node服务是一样的,只是他们应用的领域不同。
nginx最重要的四个使用场景我认为反向代理服务,负载均衡,静态资源服务和API服务。
反向代理
什么是反向代理呢?说起来也很简单,比如你拨打一个电话号码,对方问你要找谁,然后帮你转接到对应的人的分机上。每个人拨打的都是相同的号码,但也都会通过转接找到对应的人,如果有人拨打错了,也会有友好的提示。
你没有直接拨打对应人的号码,而是拨打了统一转接人的电话,这个人所做的事情就是反向代理, 反向代理是他会把你的问题转述给对应的人,并且把对应人的回答转述给你。
反向代理对服务器的要求很高,nginx具备这样的素质,所以一般都选用nginx或者OpenResty,OpenResty也是nginx的衍生品。
一个web请求走进服务以后会先经过nginx, 然后由nginx转发到对应的应用服务器。比如你想访问一张图片,你首先进入到nginx,nginx通过你想要的图片路径到对应的图片服务器拿到这张图片,再返回给你。
为什么会有反向代理呢?因为我们的应用服务因为要求开发效率非常的高,所以他的运行效率是很低的,他的qbs,tps并发都是受限的,在处理业务的同时很难兼容处理用户的请求。一般我们会搭建很多台服务,组成一个集群,向用户提供高可用性。正是因为很多服务构成集群的时候,我们才需要nginx具有反向代理的功能,可以把请求传导给应用服务。
而且对于用户的请求收口在nginx层也可以提高网站的安全性和便宜性。假设我们想要修改接口的响应头,只需要修改nginx就可以了,而不需要每台服务都去修改,想要停止服务访问,也只需要关掉nginx, 不需要每台服务都去关闭。
负载均衡
负载均衡是用来解决大流量问题,因为每台服务器可承受的访问量是有限的,随着公司的发展访问量会越来越大,这个时候我们会选择通过增加服务器的方式来平衡每台服务器所受的压力。前面也说了我们的应用服务因为要求开发效率非常的高,所以他的运行效率是很低的,他的qbs,tps并发都是受限的,所以我们需要把很多这样的应用服务组成一个集群,向用户提供高可用性。
每一次web请求进来,nginx都可以选择一台压力较少的服务器,然后将请求发送给这台服务进行处理。这就是负载均衡。
在服务领域一旦很多应用服务构成集群,他一定会带来两个需求,第一个需求我们需要动态的扩容,我们在增加一台服务器的时候,不可能关闭网站,让网站停止使用,他一定是一个无感知的过程,这就是动态扩容nginx是支持的。
第二个则是有些服务出问题的时候我们需要做容灾,假设我们的服务器集群中一台服务器出现了问题,是不应该影响用户访问的,nginx会把请求发送给其它正常的服务器保证线上用户的正常使用。
静态资源缓存
在一个链路中,nginx是处在企业内网的一个边缘节点,也就是网站的最外层,所有的请求和访问都是由nginx做转发,这样随着我们网络链路的增长,用户体验到的时延会增加。
所以如果我们能把一些所有用户看起来不变的,或者在一段时间内看起来不变的动态内容缓存在nginx中,由nginx直接向用户提供访问,那这样用户的时延就会减少很多。
所以反向代理会衍生出另外一个功能叫缓存,他能够加速我们的访问,而很多时候我们在访问像css或者js文件,或者这样一些小图片,那么这样静态的资源是没有必要由应用服务来访问的,他只需要通过本地文件,系统上放置的静态资源,直接由nginx提供访问就可以。这是nginx的静态资源功能。
API服务
由于应用服务它本身的性能存在很多的问题,但是数据库服务要比应用服务好的多,因为他的业务场景比较简单,他的并发性能和tps都要远高于应用服务,所以我们这里衍生出另一个应用场景。
由nginx直接去访问数据库或者redis或者像这样的应用服务,利用nginx的强大的一个并发性能,实现如web防火墙这样复杂的一些业务功能来提供给用户。
这要求我们api服务有非常强大的业务处理功能,所以像nginx就集成了javascript,运用javascript这样的语言功能和他们语言先天自带的一些工具库来提供完整的API服务。
以上是我们介绍nginx四个最主要的使用场景。
nginx 出现的历史背景
下面我们分析下nginx出现的原因和他的历史背景,在我看来nginx出现的原因主要有三个。
第一个是互联网上数据的快速增长,这主要是全球化和物联网的快速发展,导致接入互联网中的人与设备的数量都在快速的上升,数据的快速爆炸,对我们硬件性能提出很高的要求。
而提到硬件大家都知道摩尔定律,之前我的服务跑在1GHZ的CPU上,当一年半以后我更新到2GHZ的CPU时,我可以预测到我的服务会有两倍的性能提升。
但是到了本世纪初,摩尔定律在单颗CPU的频率上已经失效了,CPU开始向着多核方向发展,这个时候当你的服务器现在是跑在8核CPU上时,一年半以后你换到了16核的CPU,你的服务的性能通常是不会有一倍的提升的。
那么这些性能究竟损耗在哪里呢,在我看来主要是操作系统和大量的软件没有做好服务于多核架构的准备,比如说像Apache,在我看来Apache是低效的,因为他的架构模型里一个进程同一时间只会处理一个连接一个请求。只有在这个请求处理完以后才会去处理下一个请求。
这有什么潜台词呢,它实际上在使用操作系统的进程间切换的特性,因为操作系统微观上只有有限的CPU,但是操作系统被设计为同时服务于数百甚至上千的进程。
而Apache一个进程只能服务于一个连接,这样的模式会导致当Apache需要面对几十万,几百万连接的时候,他没有办法去开几百万的进程,而进程间切换的代价成本又太高啦。
当我们并发的连接数越多,这种无谓的进程间切换引发的性能消耗又会越大。
nginx是专门为了这样的应用场景而生的,nginx可以处理数百万甚至上千万的并发连接,nginx目前在web市场份额中排行第二,在过去几年他增长极度迅速,在不久的将来nginx在web端的应用将远远超过其他服务器。
nginx的5个优点
大部分的程序和服务器随着并发连接数的上升他的RPS数会急剧的下降,这里的原理就像我们之前所说过的,他的设计架构是有问题的。
nginx他的第一个优点就是高并发和高性能同时具备的,往往高并发只需要我们对每一个连接所使用的内存尽量的少就可以达到。
而具有高并发的同时达到高性能,往往需要非常好的一个设计,那么nginx可以达到一个什么样的标准呢,比如说我们现在主流的一些服务器32核64G的内存可以轻松达到数千万的并发链接,如果是处理一些简单的静态资源请求,可以达到一百万的RPS这样的级别。
第二个核心原因是他的可扩展性非常好,那么他的可扩展性呢主要体现在他的模块化设计,模块化设计非常的稳定,使得nginx的第三方模块的生态圈非常的丰富。甚至于有像TNG,openRestry这样的第三方插件。在他们之上又生成了一套新的生态圈。丰富的生态圈为我们nginx丰富的功能提供了保证。
第三个优点是它的高可靠性,所谓的高可靠性是指nginx可以在服务器上持续不间断的运行数年,而很多web服务器往往运行几周或者几个月就需要做一个重启。
对于nginx这样一个高并发高性能的反向代理服务器而言,他往往运行在企业内网的边缘节点上,这个时候如果我们企业想提供四个9,五个9,甚至更高的高可用性时,对于nginx持续运行能够down机的时间一年可能只能以秒来计。
所以在这样一个角色中,nginx的高可靠性给我们提供了非常好的保证。
第四个优点热部署,是指可以在不停止服务的情况下升级nginx,这个功能对于nginx来说非常的重要,因为在nginx可能跑了数百万的并发连接。
如果是普通的服务我们可能只用kill掉进程再重启的方式就可以处理好,但是对于nginx而言,因为kill掉nginx进程,会导致操作系统为所有的已经建立连接的客户端发送一个tcp中的reset报文。而很多客户端是没有办法很好的处理这个请求的。
在大并发场景下,一些偶然事件就会导致必然的恶性结果,所以热部署是非常有必要的。
第五个优点是BSD许可证,BSD Listens是指nginx不仅是开源的免费的,而且我们可以在有定制需要的场景下,去修改nginx源代码,再运行在我们的商业场景下,这是合法的。
nginx的优点其实不止这五条,但以上的优点我认为是nginx最核心的特性。
安装nginx
我们这里以mac电脑进行举例。
安装编译工具及库文件
yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel
然后再安装PCRE,他的作用是让nginx支持Rewrite功能,也就是请求的转发,常见的功能是比如你访问的是http链接会自动跳转成https,这就是rewrite做的。
// 进入下载目录
cd /usr/local/src/
// 下载
wget http://downloads.sourceforge.net/project/pcre/pcre/8.42/pcre-8.42.tar.gz
// 解压pcre压缩包
tar zxvf pcre-8.42.tar.gz
// 进入解压目录
cd pcre-8.42
// 编译文件
./configure
// 安装pcre
make && make install
查看pcre版本, 如果能正常显示,则表示pcre安装成功了
pcre-config --version
下面我们开始安装nginx
首先我们需要下载nginx,打开http://nginx.org/
这个网址在页面中我们找到右下角的donwload入口,点击之后我们会发现nginx有两类版本,一类叫MainLine版本,一类就Stable版本,也就是说最新的主要功能都会在MainLine,最新已经到了1.19.5, 而Stable版本是1.18.0。
我们先选择Stable版本的下来链接,右键复制链接地址即可,接着我们进入到命令行。进入对应的目录,我一般习惯在cd /usr/local/src/
目录。然后使用wget下载nginx。
cd /usr/local/src/
wget http://nginx.org/download/nginx-1.18.0.tar.gz
安装方式基本和pcre一致。
// 解压
tar zxvf nginx-1.18.0.tar.gz
// 进入解压后的源文件文件夹
cd nginx-1.18.0
// 查看
ls
这里有很多的文件夹和文件,因为是入门版,这里我们就不过多的介绍了。
接下来我们进行编译,编译的意思就类似于软件安装前的一些配置。--prefix可以指定编译到哪个文件夹,这里我们指定的nginx的安装目录是在/home/nginx目录下。
// 编译
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-pcre=/usr/local/src/pcre-8.42 --with-stream --with-stream_ssl_module --with-http_ssl_module --with-http_v2_module --with-threads
// 打包
make
// 安装
make install
如果没有任何报错,那么nginx就已经编译成功了.
我们可以通过下面的命令查看一下nginx的版本。
/usr/local/nginx/sbin/nginx -v
最后我们再来配置一下软连接,相当于配置环境变量,他可以让我们再任何目录都可以使用nginx命令。
ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx
nginx命令
// 启动nginx
nginx
当我们运行这个命令之后,控制台不会有任何反应,但是nginx已经启动了,我们可以通过访问localhost:8080或者你所在服务器的地址查看,一般是一个welcome to nginx
的默认页面。
// 关闭nginx
nginx -s stop
// 重启nginx
nginx -s reload
nginx配置语法
下面我们来看一下nginx的配置语法,在nginx的二进制文件中,已经指定了他包含了哪些模块,但每一个模块都会提供独一无二的配置语法。
这些所有的配置语法,会遵循同样的语法规则,下面我们来看一下主要的语法规则。
nginx的配置文件呢,是一个ascii文本文件,这个文本文件,主要有两部分组成,一个叫做指令一个叫做指令快。
http {
include mime.types;
upstream thwp {
server 127.0.0.1:8000;
}
server {
listen 443 http2;
# nginx配置语法
limit_req_zone $binary_remote_addr zone=one:10 rate=1r/s;
location ~* \.(gif|jpg|jpeg)$ {
proxy_cache my_cache;
expires 3m;
}
}
}
像上面http就是一个指令快,而include mime.types
;这是一条指令。
每条指令都是以分号结尾的,指令和参数间以空格符号分隔,我们还是拿include mime.types;来看,include是一个指令名,他的中间可以用一个或者多个空格来分隔,那么后面的mime.types就是他的参数,也可以具备多个参数,比如limit_req_zone $binary_remote_addr zone=one:10 rate=1r/s;
他有三个参数。
两条指令间是以分号作为分隔符的,两条指令放在一行中写也是没有问题的。只不过这样可读性会变得很差。
第三个指令块是以 {} 组成的,他会将多条指令组织到一起,比如upstream,他把一条指令server放在了thwp这个指令块下面。
像server他也放置了listen,limit_req_zone这些指令,他还可以包含其他的指令块,比如说location。
那么有些指令块呢可以有名字,比如说像upstream,后面有个thwp, location后面也可以有名字,但是有些指令块是没有名字的,比如说server和http。
nginx配置文件
nginx的配置文件在/usr/local/nginx/conf/nginx.conf
这个位置,我们可以打开看看。
user nginx;
# 运行用户,默认是nginx
worker_processes auto;
# nginx进程数,一般设置为和cpu核数一样
error_log /var/log/nginx/error.log;
# 全局错误日志路径
pid /run/nginx.pid;
# 进程pid路径
# Load dynamic modules. See /usr/share/nginx/README.dynamic.
# 负载动态模块
include /usr/share/nginx/modules/*.conf;
events {
# 工作模式与连接数上限
worker_connections 1024;
# 单个进程的最大连接数
}
http {
# 设置http服务器
log_format main '$http_host $server_addr $remote_addr [$time_local] "$request" $status $request_body $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_response_time';
# 设置日志的格式
access_log /var/log/nginx/access.log main;
# 访问日志的路径
sendfile on;
# 开启高效传输模式
tcp_nopush on;
# 激活tcp_nopush参数可以允许把http response header和文件的开始放在一个文件里发布,作用是减少网络报文段的数量
tcp_nodelay on;
# 激活tcp_nodelay,内核会等待将更多的字节组成一个数据包,从而提高I/O性能
keepalive_timeout 65;
# 长连接超时时间,单位是秒
types_hash_max_size 2048;
# 为了快速处理静态数据集,例如服务器名称, 映射指令的值,MIME类型,请求头字符串的名称,nginx使用哈希表
include /etc/nginx/mime.types;
# 文件扩展名与类型映射表
default_type application/octet-stream;
# 默认文件类型
# Load modular configuration files from the /etc/nginx/conf.d directory.
# 加载模块化配置文件
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
# 基于域名的虚拟主机
listen 80 default_server;
# 监听端口
listen [::]:80 default_server;
server_name _;
# 域名
root /usr/share/nginx/html;
# 站点根目录,即网站程序存放目录
# Load configuration files for the default server block.
# 默认服务器块的加载配置文件
include /etc/nginx/default.d/*.conf;
location / {
# 对“/”启用反向代理
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2 default_server;
# listen [::]:443 ssl http2 default_server;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# location / {
# }
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
用nginx搭建一个可用的静态资源Web服务器
首先我们在nginx的安装目录下新建一个www文件夹,在www中放置一些静态文件。
然后编辑conf/nginx.conf文件。首先我们找到server代码块中,listen配置监听哪个端口,这里我们用8080端口,然后我们需要配置一个location,这里所有的url请求都访问到www文件夹,这里我们使用/表示所有的请求。
我们这里需要指定这个url的后缀要与我们的文件目录后面的后缀一一对应,我们这里有两种用法,root和alias,root相对来说有一个问题,他会把url中的一些路径带到我们目录中来,所以我们通常使用alias。
alias就是nginx安装目录的www目录下,后面的路径与我们的url路径是一一对应的。
server {
listen 8080;
...
location / {
alias www/;
...
}
...
}
那么我们做完配置之后再去重启nginx就可以看到效果了。我们在浏览器中访问localhost:8080就可以访问。url中的路径对应文件的path路径。
nginx -s reload
开启gzip
这里我们开启gzip压缩,做完gzip压缩以后,传输的字节数会大幅度减少,所以通常我们会打开gzip。
首先我们打开nginx.conf文件,找到http代码块中的gzip相关选项,打开gzip(off -> on), gzip_min_length是小于多少字节不再执行压缩,因为小于一定的字节http传输直接就可以发送了,压缩反而消耗cpu性能,这里我们为了测试写成1,gzip_comp_level代表压缩级别,gzip_types是针对某些类型的文件才做gzip压缩。
http {
...
gzip on;
gzip_min_length 1;
gzip_comp_level 2;
gzip_types text/plain applicaton/x-javascript text/css image/png;
...
}
配置好之后我们重启nginx, 浏览器中查看就会发现,传输的文件已经减少了很多,响应头中多出了Content-encoding: gzip。所以使用gzip以后整个web服务传输效率会高很多。
打开目录结构
接下来我们演示另一个常用的功能,比如跟目录下有一个文件夹叫dlib,假定我们需要把dlib中的文件,或者文件夹及其目录结构信息分享给用户,用户来决定使用哪些文件。
这种常用的应用场景下呢,nginx给我们提供了一个官方模块叫做autoindex, 我们先来看一下autoindex的说明,他可以提供当我们访问以/结尾的url时,显示这个目录的结构。使用方法也特别简单,就是autoindex on加入这样一个指令就可以了。
location / {
autoindex on;
}
reload之后代码就生效了,他会把我们所访问的文件夹内所有文件列出来,当我们打开一个目录时,可以继续显示这个目录中的文件,这是一个很好的静态资源帮助功能。
流量限制
还有一个非常常见的功能,比如我们的公网带宽是有限的,当有很多并发用户使用我们的带宽时,他们会形成一个争抢关系,我们可能会为了让用户访问某些大文件的时候来限制他的速度,以期望能够分理出足够的带宽给用户访问一些必要的小文件,如css,js等。
这个时候我们就可以使用set命令,配合我们一些内置的变量去实现这样的功能,比如说我们加上set $limit_rate 1k,他就在限制我们nginx向客户浏览器发送响应的一个速度。
他的意思是每秒传输多少数据到浏览器中,这里我们写的是1k,这个时候我们去访问首页会发现,速度非常慢。
location / {
set $limit_rate 1k;
}
日志功能
接下来我们看下nginx的另外重要的功能,就是记录access日志,首先我们需要记录access日志到底是怎样一种格式,我们找到一个指令叫做log_format, 他用来定义日志的格式。这里可以使用变量。
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
}
remoteaddr为远端的地址,也就是浏览器客户端的ip地址,time_local表示当时的时间。$status是返回的状态码。这样的日志格式我们需要命名,比如说我们这里命名为main。
为什么要做命名的,可能我们要对不同的域名下,做不同格式的日志记录,或者对不同的url一些大文件或者做一些反向代理等等不同用途时,我们记录不同日志格式。
配置好log_format之后我们还要去设置我们日志记录在哪里,我们可以用access_log这条指令,access_log所在的位置决定了他所属的这样一类请求会记录到后面的路径中,采用main这样一种格式。
比如access_log这里放在了server下,也就是所有发现这个域名或者这个端口的请求日志,都会记录到这个文件中。
那么刚刚我们再说日志格式的时候,我们提到了很多变量都可以放进来,这里我们举个例子。只要是变量我们这里都可以使用,gzip中有个变量叫做gzipradio,表示当时使用的压缩比率,我们可以吧gzip_radio放在我们的access.log中。
server {
listen 8080;
access_log logs/yindong.log main;
location / {
alias www;
}
}
当我们配置好yindong.log后,所有的请求在完成之后都会记录下一条日志,在我们的yindong.log中, 我们可以进入logs/yindong.log中查看。每一条都是我们设置的格式。
开启https
https这里我们就不详细介绍了,后面会单开文章来介绍,这里只介绍nginx的配置过程。
首先我们需要有一个域名证书,证书一般分为DV,OV或者EV三种,种类不同功能就不同同时价格也不同,我一般选用最简单的DV证书,主要是可以免费使用...
阿里云上就支持购买免费的证书,然后将证书下载下来。
证书一般包含两个文件证书名字.key
和证书名字.pem
,将下载好的证书放在/usr/local/nginx/conf/certs
文件夹下,certs文件夹需要手动创建。
mkdir certs
然后编辑conf/nginx.conf文件,和http不同https使用的是443端口,默认情况下nginx.conf是关闭了这个端口的。我们需要打开这里的注释。
listen中开启的是443端口,打开ssl顺便也打开了http2,我们再configure的时候已经编译了http2模块。
ssl_certificate和ssl_certificate_key设置了我们的证书名字。在location中设置访问的网页资源。
server {
listen 443 ssl http2;
server_name yindong.com;
ssl_certificate certs/证书名称.pem;
ssl_certificate_key certs/证书名称.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
alias www/;
}
}
重启服务这个时候https就配置完成了。我们可以通过https来访问我们的网站。````https://yindong.com```;
同样的我们也可以通过rewrite将http转发成https, 这个时候修改的就是80端口的server。
server {
listen 80;
server_name yindong.com;
rewrite ^(.*)$ https://$host$1 permanent;
location / {
alias www/;
}
}
proxy_pass
一般情况我们不只是一个静态服务,我们可以通过proxy_pass将请求转发到对应的服务,假设我们服务器中存在一个7001的服务,可以通过本地ip127.0.0.1:7001
访问,这个时候我们就可以使用proxy_pass在location中进行配置。
server {
listen 443 ssl http2;
server_name yindong.com;
ssl_certificate certs/证书名称.pem;
ssl_certificate_key certs/证书名称.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:7001;
}
}
upstream
假设我们有两台服务,一个端口7001一个端口7002,我们可以通过upstream来实现负载均衡,在http代码块中通过upstream创建服务池。然后在server的location中通过proxy_pass转发至这个服务池。这样就实现了一个简单的负载均衡。
http {
upstream myservice {
server 127.0.0.1:7001;
server 127.0.0.1:7002;
}
server {
listen 80;
location / {
proxy_pass http://myservice;
}
}
}
以上就是nginx的常见使用方式,最后还是那句话,这只是nginx的很小一部分功能,不过作为前端工程师知道这些应该足够了。谢谢大家观看, 别忘了点赞...
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!