前言
最近因为一些情况,需要帮忙部署一个nginx,并且让web集群,负载均衡,所以记录一下Nginx的快速使用
以前的部署如果是C#,就是直接部署到IIS上
在多站点的情况下,必然会出现他们之间的端口被占用,或需要单独一个项目作网关转发,这样感觉上比较费劲
而这时候就用Nginx,它已经非常傻瓜化,很轻量,配置起来也非常简单,有win和linux\docker的版本.也很成熟了
好多年来不少公司都是用它来做网关
### 一、安装
[Nginx 下载](http://nginx.org/en/download.html)
Win直接上取下载就行
Linux和Docker就比较简单
使sudo apt-get nginx 或 docker pull nginx就行
### 二、运行
#### Win

解压官网下载的压缩包就能即用,双nginx.exe就会运行
因为双击打开也只是闪一下,第一次使用会以为运行失败,是否运行可以打开任务管理器查看到两个nginx的进程

而我比较喜欢使用命令,因为执行是否成功会换行,感觉直观些
start ./nginx
有时候在使用重载命令的时候,可能会出现没效果,这就很有可能开了多个nginx,那样就会看到两个以上nginx.exe进程,这就需要关掉多余的才能正常重载。
#### Linux \ Docker
这两个比较简单,基本不会有太多的坑,就不细说
分别是进入nginx的目录直接执nginx
而docker 直接run就得了,或者可以看我另一篇文章 [部署一个自己的halo博客](https://blog.kagamikun.com/archives/%E9%83%A8%E7%BD%B2%E4%B8%80%E4%B8%AA%E8%87%AA%E5%B7%B1%E7%9A%84halo%E5%8D%9A%E5%AE%A2)
### 三、配置
配置文件在 conf\nginx.conf
对于改了配置,nginx需要更新加载配置文件才能加载到变更的内容
nginx -s reload
#### 1.站点配置
打开后会发现一堆代码,但大部分都是注释,删掉后内容就比较少了,我们从少来看

稍微简单说明一下,对于我们添加站点,一般只需要考虑 http 里面的 server即可
http是指使用http,而https则是https,我这边就先说http。
然后就是server内部
其中listen的数字很熟悉了,是端口。需要注意,这个端口不能够被其他应用占用才能正常工作
server_name 则填外面访问我们服务器的地址或域名
location则是映射的路径,如果用过IIS就清楚网站必须有个自己的目录,比如你的html放在 D:\web中,则就填写改地址,在访问的时候,会按照这个目录作为根目录访问
比如,我现在有个html文件需要挂在到Nginx上,让其能在浏览器上访问,则server可以这样配置

```nginx
server {
listen 8088;
server_name localhost;
location / {
root D:\Web;
}
}
```
运行起来后,就能通过访问
http://localhost:8088/index2.htmlhttp://localhost:8088/index.html访问到两个html
一般我们都是说用nginx来反代,大致就是nginx会将请求,转发到我们内网的web上,比我我这里有个内网地址172.17.0.3:8090的博客,就可以这样配
```nginx
server {
listen 8088;
server_name localhost;
location / {
proxy_pass http://172.17.0.3:8090;
}
}
```
proxy_pass 既是指向的反代目标地址,重启后,访localhost:8088效果就跟直接访172.17.0.3:8090一样
(这个说法是对内网来说的,因为外网是不能访问 172.17.0.3)
#### 2.负载均衡
nginx的负载均衡也非常好配置,nginx带了好几种负载均衡的模式
##### 配置
配置方面,只是在server同层添加上 upstream,调整下反代的地址即可
upstreamName是反代块的名称,这个可以自定义
server *** ;则是负载的服务器,比如下面的例子,我设置了三台服务器(bushi其实是web,反正效果一样)
proxy_pass 调整到我要的反代的那个块
在刷新的时候,会能发现,页面出来的内容会按顺序出现,从5051~5053的web一直循环
```
upstream upstreamName {
server localhost:5051 max_fails=2 fail_timeout=300s;
server localhost:5052 max_fails=2 fail_timeout=300s;
server localhost:5053 max_fails=2 fail_timeout=300s;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://upstreamName;
}
}
```
##### 宕机说明
nginx的负载宕机是通过请求刺探的方式判断的
对于负载的机子宕机连不上的情况下,nginx会将请求转发到下一台负载的机子上
这个时间默认10s 和 1次
意思是10s内,负载机子有一次连不上,则在下个10s周期内,认为该机子宕机,不再负载它,在10s后,到达了下一个周期,则在尝试转发一个请求,若依然无法链接,则继续标识宕机,等待下一周期......
##### Nginx的负载策略
##### a. 轮询
没有配置其他内容,只配置了负载机子,则是默认的轮询方式负载
```
upstream upstreamName {
server localhost:5051;
server localhost:5052;
server localhost:5053;
}
```
##### b.权重
权重是以手动的方式去均衡请求量,一般情况下都是使用这种方式,因为认为设置和控制,则需要严格了解服务器的性能冗余情况,对服务器的健康情况有一点的约束能力
```
upstream upstreamName {
server localhost:5051 weight=2;
server localhost:5052 weight=2;
}
```
##### c.Ip哈希
与名字一样,他对请求方的ip进行哈希,然后求出应该映射到哪台负载机子上
因此他能解决一些ip造成的session问题
当然缺陷也明显,想把他临时排除到负载外,只能手动down,不能只让负载机子直接宕机的方式转移流量
```
upstream upstreamName {
ip_hash;
server localhost:5051;
server localhost:5052;
}
```
##### d.连接量
如题,若负载机子1的请求都是耗时的长链接,则负载机子2就会分配到更多的流量,直至连接量多台负载自己都平衡
```
upstream upstreamName {
least_conn;
server localhost:5051;
server localhost:5052;
}
```
##### 其他
worker_processes 是指nginx的worker个数,他就像本体是一条线程,而worker是另一条真正工作的线程,所以如果访问量太大,则就可以改大些,更多的给nginx压榨cpu的性能
worker_connections是指单个worker处理请求的量,对于并发非常大的情况下才需要调整这个值,当然需要按照服务器的性能情况调整,这里不深入讨论
gzip on;这是打开请求压缩,因为对于网络IO,一般情况下Cpu的性能会有冗余,额外使用Cpu压缩请求内容,分担网络IO的量,很多时候都会快很多.就如同你100m的文件压缩到5m再上传是一个效果
listen 443 ssl http2;如果你使用了ssl,那非常推荐加http2,这是起启用https2,大部分情况下,对于css、js、图片这类资源会因请求的方式与原先的http不同,速度会快不少。原理这里不细说,有兴趣可以额外查一查
四、关于Reload与平滑更新
对于流量较大的情况下,需要调整nginx的配置又要重载,这样会丢失这期间的请求.....吗? 然而并不会 !

官方已经说了,对于reload命令,nginx会开启新的worker,并且将流量都指向新的worker,在旧的worker链接全部关闭前,旧的worker是不会关闭的。
所以不需要担心请求丢失
我本地也测试了让Api挂起10s的情况下reload,请求不会丢失,而且也不是重发请求。
那这就好玩了,平滑更新我们能通过调整配置文件的负载,就能平滑更新站点。
当然,这也有一个问题,如果有一个请求非常长时间保持链接,那么oldworker就不会被关闭
这官方也考虑到了,给我们提供worker_shutdown_timeout配置,若worker超过设置的时间,则会被强制关闭