关于 Nginx 你还在背诵着培训班中教给你的内容么?面试的时候很多项目都说使用过 Nginx,但是当面试官问你 Nginx 的原理的时候,你还在手足无措么?如果有,那么这篇文章我送给大家,让你面试回答 Nginx 的的时候不再慌张,不需要再去背诵那些内容了,各位看官准备好了么?
01、什么是Nginx
我们来看一下这个百度百科给出的解释:
Nginx (engine x) 是一个高性能的 HTTP 和反向代理 Web 服务器,同时也提供了 IMAP/POP3/SMTP 服务。
Nginx 是一款轻量级的 Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在 BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上 Nginx 的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用 Nginx 网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
以上的内容是百度百科给出的解释,这个可是已经算的上是很全了,总结下来就几点内容:
- HTTP 和反向代理 Web 服务器
- IMAP/POP3/SMTP 服务
02、Nginx 的优点和作用
- Nginx 使用基于事件驱动架构,使得其可以支持数以百万级别的TCP连接
- 高度的模块化和自由软件许可证是的第三方模块层出不穷
- Nginx 是一个跨平台服务器,可以运行在Linux、Windows、FreeBSD、Solaris、AIX、Mac OS 等操作系统上
- 这些优秀的设计带来的极大的稳定性
03、Nginx的代理
说到代理,首先我们要明确一个概念,所谓代理就是一个代表、一个渠道;
此时就设计到两个角色,一个是被代理角色,一个是目标角色,被代理角色通过这个代理访问目标角色完成一些任务的过程称为代理操作过程;如同生活中的专卖店~客人到 Adidas 专卖店买了一双鞋,这个专卖店就是代理,被代理角色就是 Adidas 厂家,目标角色就是用户。
而代理又分为了2种,一种是正向代理,一种是反向代理
1)正向代理
举一个经典的例子,我们访问国外的网站的时候,是没有办法进行访问的,这时候是不是就得需要一个代理服务器,我们把请求发给代理服务器,代理服务器去访问国外的网站,然后将访问到的数据传递给我们!
上述这样的代理模式称为正向代理,正向代理最大的特点是客户端非常明确要访问的服务器地址;服务器只清楚请求来自哪个代理服务器,而不清楚来自哪个具体的客户端;正向代理模式屏蔽或者隐藏了真实客户端信息。
正向代理的用途
- 访问原来无法访问的资源,如 Google
- 可以做缓存,加速访问资源
- 对客户端访问授权,上网进行认证
- 代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息
2)反向代理
我们说完了正向代理之后,我们再来看一下反向代理,最经典的应用,分布式
通过部署多台服务器来解决访问人数限制的问题;某宝网站中大部分功能也是直接使用Nginx进行反向代理实现的,并且通过封装 Nginx 和其他的组件之后起了个高大上的名字:Tengine。
这其实就是反向代理的一个经典应用。
反向代理的用途
- 保证内网的安全,通常将反向代理作为公网访问地址,Web服务器是内网
- 负载均衡,通过反向代理服务器来优化网站的负载
说完了代理,我们就该来看面试中最经常问到的必须回答的内容。
04、你在工作中是怎么对 Nginx 进行配置的
配置文件详解:
- nginx.conf----------------------Nginx 的基本配置文件
- mime.types----------------------MIME 类型关联的扩展文件
- fastcgi.conf----------------------与 fastcgi 相关的配置
- proxy.conf----------------------与 proxy 相关的配置
- sites.conf----------------------配置 Nginx 提供的网站,包括虚拟主机
今天我们先说主要的这个 nginx.conf 配置文件,之后再去讲解其他的配置文件。
nginx.conf 配置文件主要分成四个部分:
- main,全局设置,影响其它部分所有设置
- server,主机服务相关设置,主要用于指定虚拟主机域名、IP 和端口
- location,URL 匹配特定位置后的设置,反向代理、内容篡改相关设置
- upstream,上游服务器设置,负载均衡相关配置
他们之间的关系是:server 继承 main,location 继承server;upstream 既不会继承指令也不会被继承。
通用配置如下:
#定义 Nginx 运行的用户和用户组,默认由 nobody 账号运行, windows 下面可以注释掉。 user nobody; #nginx进程数,建议设置为等于CPU总核心数。可以和worker_cpu_affinity配合 worker_processes 1; #全局错误日志定义类型,[ debug | info | notice | warn | error | crit ] #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #进程文件,window下可以注释掉 #pid logs/nginx.pid; # 一个nginx进程打开的最多文件描述符(句柄)数目,理论值应该是最多打开文件数(系统的值ulimit -n)与nginx进程数相除, # 但是nginx分配请求并不均匀,所以建议与ulimit -n的值保持一致。 worker_rlimit_nofile 65535; #工作模式与连接数上限 events { # 参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; # epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,如果跑在FreeBSD上面,就用kqueue模型。 #use epoll; #connections 20000; # 每个进程允许的最多连接数 # 单个进程最大连接数(最大连接数=连接数*进程数)该值受系统进程最大打开文件数限制,需要使用命令ulimit -n 查看当前设置 worker_connections 65535; } #设定http服务器 http { #文件扩展名与文件类型映射表 #include 是个主模块指令,可以将配置文件拆分并引用,可以减少主配置文件的复杂度 include mime.types; #默认文件类型 default_type application/octet-stream; #charset utf-8; #默认编码 #定义虚拟主机日志的格式 #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指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。 sendfile on; #autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。 #防止网络阻塞 #tcp_nopush on; #长连接超时时间,单位是秒,默认为0 keepalive_timeout 65; # gzip压缩功能设置 gzip on; #开启gzip压缩输出 gzip_min_length 1k; #最小压缩文件大小 gzip_buffers 4 16k; #压缩缓冲区 gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0) gzip_comp_level 6; #压缩等级 #压缩类型,默认就已经包含text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。 gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml; gzip_vary on; //和http头有关系,加个vary头,给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩 #limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用 # http_proxy服务全局设置 client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 75; proxy_send_timeout 75; proxy_read_timeout 75; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; proxy_temp_path /usr/local/nginx/proxy_temp 1 2; # 设定负载均衡后台服务器列表 upstream backend.com { #ip_hash; # 指定支持的调度算法 # upstream 的负载均衡,weight 是权重,可以根据机器配置定义权重。weigth 参数表示权值,权值越高被分配到的几率越大。 server 192.168.10.100:8080 max_fails=2 fail_timeout=30s ; server 192.168.10.101:8080 max_fails=2 fail_timeout=30s ; } #虚拟主机的配置 server { #监听端口 listen 80; #域名可以有多个,用空格隔开 server_name localhost fontend.com; # Server Side Include,通常称为服务器端嵌入 #ssi on; #默认编码 #charset utf-8; #定义本虚拟主机的访问日志 #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; } # 图片缓存时间设置 location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$ { expires 10d; } # JS和CSS缓存时间设置 location ~ .*.(js|css)?$ { expires 1h; } #代理配置 # proxy the PHP scripts to Apache listening on 127.0.0.1:80 #location /proxy/ { # 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; #} } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #}
上面的配置文件不需要你每一行都看过来,你需要注意的地方如下:
#工作模式与连接数上限 events { # 参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; # epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,如果跑在FreeBSD上面,就用kqueue模型。 #use epoll; #connections 20000; # 每个进程允许的最多连接数 # 单个进程最大连接数(最大连接数=连接数*进程数)该值受系统进程最大打开文件数限制,需要使用命令ulimit -n 查看当前设置 worker_connections 65535; } http { include mime.types; #文件扩展名与文件类型映射表 default_type application/octet-stream; #默认文件类型,默认为text/plain #access_log off; #取消服务日志 log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for'; #自定义格式 access_log log/access.log myFormat; #combined为日志格式的默认值 sendfile on; #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块。 sendfile_max_chunk 100k; #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。 keepalive_timeout 65; #连接超时时间,默认为75s,可以在http,server,location块。 upstream mysvr { server 127.0.0.1:7878; server 192.168.10.121:3333 backup; #热备 } error_page 404 https://www.baidu.com; #错误页 server { keepalive_requests 120; #单连接请求上限次数。 listen 4545; #监听端口 server_name 127.0.0.1; #监听地址 location ~*^.+$ { #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。 #root path; #根目录 #index vv.txt; #设置默认页 proxy_pass http://mysvr; #请求转向mysvr 定义的服务器列表 deny 127.0.0.1; #拒绝的ip allow 172.18.5.54; #允许的ip } } }
有时候面试官会问你,你们是怎么修改配置文件实现负载均衡的?
通过在 upstream 参数中添加的应用服务器 IP 后添加指定参数即可实现,如:
upstream tomcatserver1 { server 192.168.72.49:8080 weight=3; server 192.168.72.49:8081; } server { listen 80; server_name 8080.max.com; #charset koi8-r; #access_log logs/host.access.log main; location / { proxy_pass http://tomcatserver1; index index.html index.htm; } }
通过以上配置,便可以实现,在访问 8080.max.com 这个网站时,由于配置了 proxy_pass 地址,所有请求都会先通过 Nginx 反向代理服务器,在服务器将请求转发给目的主机时,读取 upstream 为 tomcatsever1 的地址,读取分发策略,配置 tomcat1 权重为 3,所以 Nginx 会将大部分请求发送给 49 服务器上的 tomcat1,也就是 8080 端口;较少部分给 tomcat2 来实现有条件的负载均衡,当然这个条件就是服务器 1、2 的硬件指数处理请求能力。
面试官又问,你们是怎么配置实现反向代理的呢?
server { listen 80; server_name tomcat1.com; #charset koi8-r; #access_log logs/host.access.log main; location / { proxy_pass http://127.0.0.1:8280; index index.html index.htm; } } server { listen 80; server_name tomcat2.com; #charset koi8-r; #access_log logs/host.access.log main; location / { proxy_pass http://127.0.0.1:8281; index index.html index.htm; } }
- 打开 /conf/nainx.conf 文件,删除 server{ …… },或者注销掉
- 重新添加 server{ }
- listen: 监听的端口号
- server_name: 访问域名
- location :这里配置为 / 直接匹配端口下的默认 ROOT 下的项目,
- proxy_pass :为项目的实际访问地址
然后重启 Nginx 服务器就可以啦!
有时候面试官就会问你,你在使用 Nginx 的时候做过哪些配置,在配置文件中改动过那里,都有什么样子的作用,把列出来的这一行代码解释给面试官听,那么至少你在面试官面前,已经把 Nginx 的比较重要的点解释了一下了,这样也能增加咱们入职的一些胜算。