Nginx 用得好,这个知识点最重要!

来源:运维部落

ID:linux178

很多人都知道nginx可以做反向代理和负载均衡,但是关于nginx的健康检查(health_check)机制了解的不多。

其实社区版nginx提供的health_check机制其实很薄弱,主要是通过在upstream中配置max_fails和fail_timeout来实现,这边文章主要是深入分析社区版的health_check机制。

当然还有更好的一些建议,比如商业版的nginx plus或者阿里的tengine,他们包含的健康检查机制更加完善和高效,如果你坚持使用nginx社区版,当然还可以自己写或者找第三方模块来编译了。

首先说下我的测试环境,CentOS release 6.4 (Final) + nginx_1.6.0 + 2台tomcat8.0.15作为后端服务器。(声明:以下所有配置仅仅为测试所用,不代表线上环境真实所用,真正的线上环境需要更多配置和优化。)

nginx配置如下:

#user nobody;
worker_processes 1;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
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;
keepalive_timeout 65;
upstream backend {
server localhost:9090 max_fails=1 fail_timeout=40s;
server localhost:9191 max_fails=1 fail_timeout=40s;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://backend;
proxy_connect_timeout 1;
proxy_read_timeout 1;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}

关于nginx和tomcat的配置的基本配置不再说明,大家可以去看官方文档。

我们可以看到我在upstream 指令中配置了两台server,每台server都设置了max_fails和fail_timeout值。

现在开始启动nginx,然后启动后台的2台server, 故意把在Tomcat Listener中Sleep 10分钟,也就是tomcat启动要花费10分钟左右,端口已开,但是没有接收请求,然后我们访问http://localhost/response/ (response这个接口是我在tomcat中写的一个servlet接口,功能很简单,如果是9090的server接收请求则返回9090,如果是9191端口的server则返回9191.),现在观察nginx的表现。

我们查看nginx中

access.log

192.168.42.254 - - [29/Dec/2014:11:24:23 +0800] "GET /response/ HTTP/1.1" 504 537 720 380 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36" 2.004 host:health.iflytek.com

192.168.42.254 - - [29/Dec/2014:11:24:24 +0800] "GET /favicon.ico HTTP/1.1" 502 537 715 311 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36" 0.000 host:health.iflytek.com

error.log

2014/12/29 11:24:22 [error] 6318#0: *4785892017 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.42.254, server: health.iflytek.com, request: "GET /response/ HTTP/1.1", upstream: "http://192.168.42.249:9090/response/", host: "health.iflytek.com"

2014/12/29 11:24:23 [error] 6318#0: *4785892017 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.42.254, server: health.iflytek.com, request: "GET /response/ HTTP/1.1", upstream: "http://192.168.42.249:9191/response/", host: "health.iflytek.com"

2014/12/29 11:24:24 [error] 6318#0: *4785892017 no live upstreams while connecting to upstream, client: 192.168.42.254, server: health.iflytek.com, request: "GET /favicon.ico HTTP/1.1", upstream: "http://health/favicon.ico", host: "health.iflytek.com"

(为什么要在listener中设置睡眠10分钟,这是因为我们的业务中需要做缓存预热,所以这10分钟就是模拟服务器启动过程中有10分钟的不可用。)

观察日志发现在两台tomcat启动过程中,发送一次请求,nginx会自动帮我们进行重试所有的后端服务器,最后会报 no live upstreams while connecting to upstream错误。这也算是nginx做health_check的一种方式。这里需要特别强调一点,我们设置了proxy_read_timeout 为 1秒。后面再重点讲解这个参数,很重要。

等待40s,现在把9090这台服务器启动完成,但是9191这台服务器仍然是正在启动,观察nginx日志表现。

access.log

192.168.42.254 - - [29/Dec/2014:11:54:18 +0800] "GET /response/ HTTP/1.1" 200 19 194 423 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36" 0.210 host:health.iflytek.com

192.168.42.254 - - [29/Dec/2014:11:54:18 +0800] "GET /favicon.ico HTTP/1.1" 404 453 674 311 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36" 0.212 host:health.iflytek.com

error.log

$

没有打印任何错误

浏览器返回9090,说明nginx正常接收请求。

我们再次请求一次。

access.log

192.168.42.254 - - [29/Dec/2014:13:43:13 +0800] "GET /response/ HTTP/1.1" 200 19 194 423 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36" 1.005 host:health.iflytek.com

说明正常返回,同时返回9090

error.log

2014/12/29 13:43:13 [error] 6323#0: *4801368618 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.42.254, server: health.iflytek.com, request: "GET /response/ HTTP/1.1", upstream: "http://192.168.42.249:9191/response/", host: "health.iflytek.com"

发现nginx error.log 增加了一行upstream time out的错误。但是客户端仍然正常返回,upstream默认是轮训的负载,所以这个请求默认会转发到9191这台机器,但是因为9191正在启动,所以这次请求失败,然后有nginx重试转发到9090机器上面。

OK,但是fail_timeout=40s是什么意思呢?我们要不要重现一下这个参数的重要性?

Let's go !

现在你只需要静静的做个美男子,等待9191机器启动完毕!多发送几次请求!然后咦,你发现9191机器返回9191

响应了噢!fail_timeout=40s其实就是如果上次请求发现9191无法正常返回,那么有40s的时间该server会不可用,但是一旦超过40s请求也会再次转发到该server上的,不管该server到底有没有真正的恢复。

所以可见nginx社区版的health_check机制有多么的薄弱啊,也就是一个延时屏蔽而已,如此周而复始!

如果你用过nginx plus其实你会发现nginx plus 提供的health_check机制更加强大,说几个关键词,你们自己去查! zone slow_start health_check match ! 这个slow_start其实就很好的解决了缓存预热的问题,比如nginx发现一台机器重启了,那么会等待slow_starts设定的时间才会再次发送请求到该服务器上,这就给缓存预热提供了时间。

原文发布于微信公众号 - 马哥Linux运维(magedu-Linux)

原文发表时间:2018-05-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Linyb极客之路

nginx常见架构

总结 开启压缩主要是为了减少网络传输消耗,浏览器会对压缩的文件进行解压缩,这个过程要快很多。

854
来自专栏腾讯NEXT学位

阅读前端项目源码的正确姿势!

1213
来自专栏惨绿少年

Nginx的反向代理与负载均衡

1.1 集群是什么   简单地说,集群就是指一组(若干个)相互独立的计算机,利用高速通信网络组成的一个较大的计算机服务系统,每个集群节点(即集群中的每台计算机)...

2290
来自专栏逆向技术

Win32之内存管理之虚拟内存跟物理内存

  我们知道每个应用程序都有自己独立的4GB空间.  假设A进程的 地址123 存储了10  那么B进程的123地址 存储了20

794
来自专栏Java成神之路

Java程序员常用工具集

我发现很多人没办法高效地解决问题的关键原因是不熟悉工具,不熟悉工具也还罢了,甚至还不知道怎么去找工具,这个问题就大条了。我想列下我能想到的一个Java程序员会用...

733
来自专栏xcywt

Linux进程间通信之管道

1,进程间通信 (IPC ) Inter-Process Communication   比较好理解概念的就是进程间通信就是在不同进程之间传播或交换信息。 2,...

1888
来自专栏JMCui

Linux 常用性能工具简介.

一、wget 文件下载 使用wget下载单个文件:wget URL 下载并以不同的文件名保存:wget -O wordpress.zip URL wget限速下...

5035
来自专栏杨建荣的学习笔记

关于任务调度的思考

其实对于Celery来说,网络上的资源和文档其实还是比较匮乏的,能够坚持坐下来,能够维护起来这样一个项目,确实不易。

804
来自专栏Python与爬虫

模拟登陆知乎(最新版)

为啥要写这一篇文章呢? (主要是qq群内有人在模拟登陆知乎,一直不成功)然后我抓包看了下,发现知乎登陆页已经改版了,而且难度大大提高了。 开始抓包 首先内,还是...

36013
来自专栏你不就像风一样

Nginx服务器的安装与反向代理负载均衡

我们生活的世界中,有的时候需要上网。我们可以浏览很多很多的网页,这些网页都是由一系列的程序组成,但是我们是否想过,这些程序存储在什么地方呢?没错,这些程序都是存...

541

扫码关注云+社区