引言
先来看下 nginx 在 web 服务器排名上的趋势:
存在即合理, 那为什么要使用 nginx 呢? 这得看看 nginx 能帮我们做些什么.
首先, nginx 能做反向代理 [关于反向代理和正向代理此处不做说明了, 感兴趣的小伙伴自行谷歌] ; 比方说, 我想在本地使用 www.glmapper1.com 的域名去访问 www.taobao.com. 那么这个时候我们就可以通过 nginx 去实现.
再者, nginx 能实现负载均衡, 什么是负载均衡呢? 就是说应用部署在不同的服务器上, 但是通过统一的域名进入, nginx 则对请求进行分发, 将请求分发到不同的服务器上去处理, 这样就可以有效的减轻了单台服务器的压力.
在上面这两种情况下, nginx 服务器的作用都只是作为分发服务器, 真正的内容, 我们可以放在其他的服务器上, 这样来, 还能起到一层安全隔壁的作用, nginx 作为隔离层.
解决跨域问题
同源: URL 由协议, 域名, 端口和路径组成, 如果两个 URL 的协议, 域名和端口相同, 则表示他们同源.
浏览器的同源策略: 浏览器的同源策略, 限制了来自不同源的 "document" 或脚本, 对当前 "document" 读取或设置某些属性. 从一个域上加载的脚本不允许访问另外一个域的文档属性.
因为 nginx 和 tomcat 不能共用同一端口, url 一样, 端口不同, 这样就会有跨域问题.
PS: 点到为止, 这里本次测试没有涉及, 就不妄自菲薄了!!!
配置文件解析
配置文件主要由四部分组成:
- main(全区设置)
- server(主机配置)
- http(控制着 nginx http 处理的所有核心特性)
- location(URL 匹配特定位置设置).
- upstream(负载均衡服务器设置)
下面以默认的配置文件来说明下具体的配置文件属性含义:
- #Nginx 的 worker 进程运行用户以及用户组
- #user nobody;
- #Nginx 开启的进程数
- worker_processes 1;
- # 定义全局错误日志定义类型,[debug|info|notice|warn|crit]
- #error_log logs/error.log;
- #error_log logs/error.log notice;
- #error_log logs/error.log info;
- # 指定进程 ID 存储文件位置
- #pid logs/nginx.pid;
- # 事件配置
- events {
- #use [ kqueue | rtsig | epoll | /dev/poll | select | poll ];
#epoll 模型是 Linux 内核中的高性能网络 I/O 模型, 如果在 mac 上面, 就用 kqueue 模型.
use kqueue;
#每个进程可以处理的最大连接数, 理论上每台 nginx 服务器的最大连接数为 worker_processes*worker_connections. 理论值: worker_rlimit_nofile/worker_processes
- worker_connections 1024;
- }
- #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_user_agent" "$http_x_forwarded_for"';
- #连接日志的路径, 指定的日志格式放在最后.
- #access_log logs/access.log main;
- #开启高效传输模式
- sendfile on;
- #防止网络阻塞
- #tcp_nopush on;
- #客户端连接超时时间, 单位是秒
- #keepalive_timeout 0;
- keepalive_timeout 65;
- #开启 gzip 压缩输出
- #gzip on;
- #虚拟主机基本设置
- server {
- #监听的端口号
- listen 80;
- #访问域名
- server_name localhost;
- #编码格式, 如果网页格式与当前配置的不同的话将会被自动转码
- #charset koi8-r;
- #虚拟主机访问日志定义
- #access_log logs/host.access.log main;
- #对 URL 进行匹配
- 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;
- }
- #访问 URL 以. php 结尾则自动转交给 127.0.0.1
- # proxy the PHP scripts to Apache listening on 127.0.0.1:80
- #
- #location ~ \.php$ {
- # proxy_pass http://127.0.0.1;
- #}
- #php 脚本请求全部转发给 FastCGI 处理
- # 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;
- #}
- #禁止访问. ht 页面
- # 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 虚拟主机定义
- # 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;
- # }
- #}
- include servers/*;
- }
反向代理实例
假设我现在需要本地访问 www.baidu.com; 配置如下:
- server {
- #监听 80 端口
- listen 80;
- server_name localhost;
- # individual nginx logs for this web vhost
- access_log /tmp/access.log;
- error_log /tmp/error.log ;
- location / {
- proxy_pass http://www.baidu.com;
- }
验证结果:
可以看到, 我在浏览器中使用 localhost 打开了百度的首页...
负载均衡实例
下面主要验证最常用的三种负载策略. 虚拟主机配置:
- server {
- #监听 80 端口
- listen 80;
- server_name localhost;
- # individual nginx logs for this web vhost
- access_log /tmp/access.log;
- error_log /tmp/error.log ;
- location / {
- #负载均衡
- #轮询
- #proxy_pass http://polling_strategy;
- #weight 权重
- #proxy_pass http://weight_strategy;
- #ip_hash
- # proxy_pass http://ip_hash_strategy;
- #fair
- # proxy_pass http://fair_strategy;
- #url_hash
- # proxy_pass http://url_hash_strategy;
- #重定向
- #rewrite ^ http://localhost:8080;
- }
轮询策略
- # 1, 轮询 (默认)
- # 每个请求按时间顺序逐一分配到不同的后端服务器, 如果后端服务器 down 掉, 能自动剔除.
- upstream polling_strategy {
- server glmapper.net:8080; # 应用服务器 1
- server glmapper.net:8081; # 应用服务器 2
- }
测试结果 (通过端口号来区分当前访问):
- 8081:hello
- 8080:hello
- 8081:hello
- 8080:hello
权重策略
- #2, 指定权重
- # 指定轮询几率, weight 和访问比率成正比, 用于后端服务器性能不均的情况.
- upstream weight_strategy {
- server glmapper.net:8080 weight=1; # 应用服务器 1
- server glmapper.net:8081 weight=9; # 应用服务器 2
- }
测试结果: 总访问次数 15 次, 根据上面的权重配置, 两台机器的访问比重: 2:13; 满足预期!
ip hash 策略
- #3,IP 绑定 ip_hash
- # 每个请求按访问 ip 的 hash 结果分配, 这样每个访客固定访问一个后端服务器,
- # 可以解决 session 的问题; 在不考虑引入分布式 session 的情况下,
- # 原生 HttpSession 只对当前 servlet 容器的上下文环境有效
- upstream ip_hash_strategy {
- ip_hash;
- server glmapper.net:8080; # 应用服务器 1
- server glmapper.net:8081; # 应用服务器 2
- }
iphash 算法: ip 是基本的点分十进制, 将 ip 的前三个端作为参数加入 hash 函数. 这样做的目的是保证 ip 地址前三位相同的用户经过 hash 计算将分配到相同的后端 server. 作者的这个考虑是极为可取的, 因此 ip 地址前三位相同通常意味着来着同一个局域网或者相邻区域, 使用相同的后端服务让 nginx 在一定程度上更具有一致性.
为什么说要解释下 iphash, 因为采坑了; 和猪弟在进行这个策略测试时使用了 5 台机器来测试的, 5 台机器均在同一个局域网内 [192.168.3.X] ; 测试时发现 5 台机器每次都路由到了同一个服务器上, 一开始以为是配置问题, 但是排查之后也排除了这个可能性. 最后考虑到可能是对于同网段的 ip 做了特殊处理, 验证之后确认了猜测.
其他负载均衡策略
这里因为需要安装三方插件, 时间有限就不验证了, 知悉即可!
- #4,fair(第三方)
- # 按后端服务器的响应时间来分配请求, 响应时间短的优先分配.
- upstream fair_strategy {
- server glmapper.net:8080; # 应用服务器 1
- server glmapper.net:8081; # 应用服务器 2
- fair;
- }
- #5,url_hash(第三方)
- # 按访问 url 的 hash 结果来分配请求, 使每个 url 定向到同一个后端服务器,
- # 后端服务器为缓存时比较有效.
- upstream url_hash_strategy {
- server glmapper.net:8080; # 应用服务器 1
- server glmapper.net:8081; # 应用服务器 2
- hash $request_uri;
- hash_method crc32;
- }
重定向 rewrite
- location / {
- #重定向
- #rewrite ^ http://localhost:8080;
- }
验证思路: 本地使用 localhost:80 端口进行访问, 根据 nginx 的配置, 如果重定向没有生效, 则最后会停留在当前 localhost:80 这个路径, 浏览器中的地址栏地址不会发生改变; 如果生效了则地址栏地址变为 localhost:8080;
通过验证, 满足预期!
总结
本文先对 nginx 的作用和基本的配置做了简单说明; 然后通过负载均衡的实例测试了不同负载均衡算法的具体应用反馈结果. 帮助自己更加深刻的理解 nginx 服务器中的一些配置细节. 感谢刘秘提供的 helloworld 程序 [基于 springboot 的脚手架, 有需要的可以联系他获取; 还有就是刘秘是个男的...]
参考
- http://nginx.org/
- https://www.nginx.com/
- http://www.sohu.com/a/161411719_324809
来源: https://juejin.im/post/5adc425f518825670f7b6fc8