zabbix自定Nginx状态监控

监控效果

未分类

未分类

自定义监控脚本

#!/bin/bash
#author:51itinfo.com
## Active connections: 对后端发起的活动连接数
## Server accepts handled requests: accepts表示共处理了多少个连接,handled表示成功创建了 多少次握手(没有失败次数),requests表示总共处理了多少个请求
## Reading: Nginx 读取到客户端的 Header 信息数
## Writing: Nginx 返回给客户端的 Header 信息数
## Waiting: 开启 keep-alive 的情况下,这个值等于 active - ( reading + writing ), 意思是 Nginx 已经处理完成,正在等待下一次请求指令的驻留连接
## 在访问效率很高,请求很快被处理完毕的情况下,Waiting 数比较多是正常的。如果 reading + writing 数较多,则说明并发访问量很大,正在处理过程中

case $1 in
    active)
        curl -s http://127.0.0.1/nginx_status | awk '/Active/ {print $3}' ;;
    accepts)
        curl -s http://127.0.0.1/nginx_status | awk 'NR==3 {print $1}' ;;
    handled)
        curl -s http://127.0.0.1/nginx_status | awk 'NR==3 {print $2}' ;;
    requests)
        curl -s http://127.0.0.1/nginx_status | awk 'NR==3 {print $3}' ;;
    reading)
        curl -s http://127.0.0.1/nginx_status | awk '/Reading/ {print $2}' ;;
    writing)
        curl -s http://127.0.0.1/nginx_status | awk '/Writing/ {print $4}' ;;
    waiting)
        curl -s http://127.0.0.1/nginx_status | awk '/Waiting/ {print $6}' ;;
    *)
        echo "Usage: $0 { active | accepts | handled | requests | reading | writing | waiting }" ;;
esac

nginx 服务器重启命令,关闭

未分类

nginx -s reload  :修改配置后重新加载生效
nginx -s reopen  :重新打开日志文件
nginx -t -c /path/to/nginx.conf 测试nginx配置文件是否正确

关闭nginx:

nginx -s stop  :快速停止nginx
nginx -s quit  :完整有序的停止nginx

其他的停止nginx 方式:

ps -ef | grep nginx

kill -QUIT 主进程号 :从容停止Nginx kill -TERM 主进程号 :快速停止Nginx pkill -9 nginx :强制停止Nginx

启动nginx:

nginx -c /path/to/nginx.conf

平滑重启nginx:

kill -HUP 主进程号

Mac下Nginx端口被占用问题

配置PHP过程中看到nginx的日志文件大小达到800多MB,里面的日志内容多是:nginx: [emerg] bind() to 0.0.0.0:80 failed (48: Address already in use)等端口占用信息,不免好奇。

Mac默认的Apache已经stop,再无其他应用、程序占用80端口。事实上,netstat分析也显示没有其他进程占用,但结果就摆在眼前,仍在不停输出。通过搜索发现,可能是IPv6所致。于是带上–with-ipv6选项重新编译,并监听ipv6地址,设为ipv6only=on。重新reload后,转为报错:nginx: [emerg] bind() to [::]:80 failed (48: Address already in use)。看来,网上的解决方案无济于事。

逐渐尝试升级Nginx、换端口,问题依旧,只是提示信息改为8080、8081等。看来,问题并不出在ipv6等配置上。

升级过程中,偶然的发现,sudo launchctl unload org.nginx.plist后,似乎报错停止了。于是,恢复配置,reload后,进行了unload测试。果不其然,事实证实如此。问题完美解决。

nginx yii2 配置路径 500问题

困扰了一个上午的问题

nginx conf中将yii2项目的路径配置到 根目录不会出错。
但是 配置到 frontend/web下 时 访问 就会报错500 服务器内部错误

不死心的我 google了很久。。。。。。。

发现和php 的 open_basedir有关系

改了下。

未分类

更改 你要显示的路径

报错解决。

Nginx 反向代理实现 Kibana 登录认证功能

Kibana 5.5 版后,已不支持认证功能,也就是说,直接打开页面就能管理,想想都不安全,不过官方提供了 X-Pack 认证,但有时间限制。毕竟X-Pack是商业版。

下面我将操作如何使用Nginx反向代理实现kibana的认证功能。

先决条件:

《Centos 7 源码编译安装 Nginx》

https://www.renwole.com/archives/39

1. 安装 Apache Httpd 密码生成工具

$ yum install httpd-tools -y

2. 生成Kibana认证密码

$ mkdir -p /usr/local/nginx/conf/passwd
$ htpasswd -c -b /usr/local/nginx/conf/passwd/kibana.passwd Userrenwolecom GN5SKorJ
Adding password for user Userrenwolecom

3. 配置Nginx反向代理

在Nginx配置文件中添加如下内容(或新建配置文件包含):

$ vim /usr/local/nginx/conf/nginx.conf

server {
listen 10.28.204.65:5601;
auth_basic "Restricted Access";
auth_basic_user_file /usr/local/nginx/conf/passwd/kibana.passwd;
location / {
proxy_pass http://10.28.204.65:5601;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade; 
}
}

4. 配置Kibana

取消下面注释:

$ vim /usr/local/kibana/config/kibana.yml

server.host: "10.28.204.65"

5. 重启 Kibana 及 Nginx 服务使配置生效

$ systemctl restart kibana.service
$ systemctl restart nginx.service

接下来浏览器访问 http://103.28.204.65:5601/ 会提示验证弹窗,输入以上生成的用户密码登录即可。

nginx如何设置图片文件防盗链

关于nginx防盗链的方法网上有很多教程,都可以用,但是我发现很多教程并不完整,所做的防盗链并不是真正的彻底的防盗链!

一般,我们做好防盗链之后其他网站盗链的本站图片就会全部失效无法显示,但是您如果通过浏览器直接输入图片地址,仍然会显示图片,仍然可以右键图片另存为下载文件!

依然可以下载?这样就不是彻底的防盗了!那么,nginx应该怎么样彻底地实现真正意义上的防盗链呢?

首先,我们来看下nginx如何设置防盗链

如果您使用的是默认站点,也就是说,您的站点可以直接输入服务器IP访问的,使用root登录,修改 /usr/local/nginx/conf/nginx.conf 这个配置文件。

如果您新建了站点,那么修改/usr/local/nginx/conf/vhost/你的域名.conf 这个配置文件,找到:

location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
{
 expires      30d;
}

把这一段删掉,修改成:

location ~* .(gif|jpg|png|jpeg)$ {
    expires     30d;
        valid_referers none blocke *.hugao8.com www.hugao8.com m.hugao8.com *.baidu.com *.google.com;
    if ($invalid_referer) {
    rewrite ^/ http://ww4.sinaimg.cn/bmiddle/051bbed1gw1egjc4xl7srj20cm08aaa6.jpg;
    #return 404;
    }
    }

第一行: location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$

其中“gif|jpg|jpeg|png|bmp|swf”设置防盗链文件类型,自行修改,每个后缀用“|”符号分开!

第三行:valid_referers none blocked *.it300.com it300.com;

就是白名单,允许文件链出的域名白名单,自行修改成您的域名!*.it300.com这个指的是子域名,域名与域名之间使用空格隔开!

第五行:rewrite ^/ http://www.it300.com/static/images/404.jpg;

这个图片是盗链返回的图片,也就是替换盗链网站所有盗链的图片。这个图片要放在没有设置防盗链的网站上,因为防盗链的作用,这个图片如果也放在防盗链网站上就会被当作防盗链显示不出来了,盗链者的网站所盗链图片会显示X符号。

这样设置差不多就可以起到防盗链作用了,上面说了,这样并不是彻底地实现真正意义上的防盗链!

我们来看第三行:valid_referers none blocked *.it300.com it300.com;

valid_referers 里多了“none blocked”

我们把“none blocked”删掉,改成

valid_referers *.it300.com it300.com;

nginx彻底地实现真正意义上的防盗链完整的代码应该是这样的:

location ~* .(gif|jpg|png|jpeg)$ {
    expires     30d;
    valid_referers *.hugao8.com www.hugao8.com m.hugao8.com *.baidu.com *.google.com;
    if ($invalid_referer) {
    rewrite ^/ http://ww4.sinaimg.cn/bmiddle/051bbed1gw1egjc4xl7srj20cm08aaa6.jpg;
    #return 404;
    }
    }

这样您在浏览器直接输入图片地址就不会再显示图片出来了,也不可能会再右键另存什么的。

第五行:rewrite ^/ http://www.it300.com/static/images/404.jpg;

这个是给图片防盗链设置的防盗链返回图片,如果我们是文件需要防盗链下载,把第五行:

rewrite ^/ http://www.it300.com/static/images/404.jpg;

改成一个链接,可以是您主站的链接,比如把第五行改成:

rewrite ^/ http://www.it300.com;

这样,当别人输入文件下载地址,由于防盗链下载的作用就会跳转到您设置的这个链接!

最后,配置文件设置完成别忘记重启nginx生效!

如何快速实现一个基于Nginx的网站监控场景—-需求篇

一切从应用服务监控说起

小明所在的一家小型互联网创业公司一直将应用运行在国内某A云上。该应用采用通用的分布式Nginx+App架构为用户提供电商数据统计的webservice 服务。应用运行至今除偶发各类Bug, 性能问题以外,情况还算良好。

未分类

最近,小明的老板给小明布置了一个任务,希望把应用服务监控起来,以提高应用运行质量。老板的需求有三点:

1、先以应用服务监控为抓手,能

a) 实时统计应用各类服务的调用次数

b) 基于a,实时统计各类服务各类返回值的次数,如200,404,500,等。

c) 基于b,如果某类返回值调用超限,进行实时报警。

2、提供历史查询功能,能返回任意时段任意服务任意返回值调用次数统计。

3、以后未来公司各类定制的业务监控能快速扩展到该系统上,如各接口响应统计时间,用户特征统计,等。

“方案尽量多快好省,而且搭建的监控平台最好就在A云上,数据不要外放在第三方云上,主要是为了公网流量成本和以后大数据分析作准备”,老板最后提到。

技术选项

小明接到任务以后开始着手进行技术选型。摆在他面前貌似可行的有三个选择,传统OLAP式处理方式,搜索引擎,以及实时计算方式。

未分类

在调研现状和众多技术后,他发现,

  1. 由于公司业务规模不小,白天峰段的平均qps已经上百,而且业务还在快速增长,因此将每秒上百次调用信息每次直接存放到数据库中再实时查询肯定不合适,成本太高且不适合扩展。

  2. A云提供搜索引擎服务,错误统计功能基本能满足老板需求。但是不确定因素有两个。一方面搜索引擎价格存储成本偏高(搜索引擎需要引入索引存储),而且各类聚合查询如接口响应时间统计等查询响应时间不太好保证,另一方面考虑到实时报警还需要编写API不停进行各类调用的错误次数的轮询,性能和成本都不太确定。

  3. 基于实时计算的架构,可以将线上所有日志通过服务,返回值错误类型,和时间等维度在内存中进行实时的聚合计算,然后再持久化到存储中。一方面实时计算效率高,聚合后的结果大小会比原始数据大大减少,因此持久化成本低,实时能保证;另一方面还可以在内存中实时校验报警策略,让报警的性能开销足够小。

综上考虑,基于实时计算的架构看来最能满足当前公司的需求。决定了以后,小明开始思考进一步架构设计。

架构设计

决定了基于实时计算的技术以后,小明开始进行架构设计。通过参考各类技术网站,他发现要架构一个靠谱的网站监控方案,需要的组件以下缺一不可。

  • 数据通道:负责将数据从Nginx拉取出来,传送到搜索引擎。数据通道同时肩负数据堆积和数据重算的任务。

  • 计算引擎:基于Nginx服务,错误码,时间的维度的聚合实时计算逻辑需要基于选定的引擎进行编写。计算引擎最好能同时负责一些报警的逻辑。

  • 存储:存放最终Nginx监控结果的地方。考虑到监控结果虽然表结构简单,但是各种维度查询比较多,最好是类似于OLAP的存储类型。

  • 展示门户:针对所有Nginx监控结果作各类维度的快速分析和展示。

未分类

好在针对前三个组件,A云提供了一些现成的产品组件,小明不需要自己手动一个个去搭建,因此入门门槛还不算高。

  • 数据通道这块,小明在阿里云上选取了一款类似于Kafka的数据通道,在支持性能和消息堆积等特性的同时,在数据接入上提供了一定的简便性。

  • 计算引擎上,小明为了简易入手,选择了一款基于spark-stream计算引擎组件,可以上面直接写SQL语句进行实时计算编排而不需要自己写流式计算程序。

  • 存储方面,由于没有太强事物需求,而且在容量上要求较高,小明选择了一款类似Hbase的云上存储产品。

  • 展示门户方面,没有直接对应产品。小明挠了挠头,决定还是只能自己突击一下前段编程技术,基于开源展示框架来编写一个简单的查询门户。

跟老板申请了预算以后,小明开始陆续开通各类产品进行开发测试。预计一个月完成任务,

漫漫开发路程

开通流程很简单。花了半天不到,kafka, storm, hbase的租户集群到手。可惜常言道,开发项目80%的时间花费在最终20%的坑上。项目过了一个月,但是功能尚未完成70%。小明在自己的技术博客上默默的记录下以下踩过的坑。

  • 集成故障排查成本

由于需要集成的组件包括数据通道,实时计算层,后台存储,并在代码中集成推送数据逻辑以及报警查询逻辑。每个环节稍有出错将造成整个链路阻塞,调试成本显得非常高。

  • 日志清洗

开发期间为了获取到相关应用为了调整对于日志的推送逻辑,需要在每台Nginx日志内容变更以后再在每个服务端变更API的推送逻辑,变更过程冗长且容易出错。

  • 持久化表设计

除了要针对监控项做出适合的表库设计,并尽量避免索引热点以外,还需要考虑当数据结果由于实时计算层不稳定重复计算时如何保证数据库写入幂等性,这对表结构设计是一个不小的挑战

  • 延迟数据合并

如果由于应用原因导致Nginx日志数据被延迟发送,如何保证比如晚到1个小时的数据能被实时计算引擎准确计算并将结果合并到之前的结果。

  • 报警

针对所有结果需要设置定时任务每分钟对数据进行遍历查询。比如针对任何返回500调用错误超过5%占比的服务,需要所有服务进行多次的调用结果进行遍历查询。如何不遗漏所有的服务错误检查的同时保证高效率查询也是个不小的挑战。

  • 报警准确性

有的时候由于日志延迟,上一分钟部分服务器正常日志还没采集全,导致局部500调用错误的服务暂时超过5%,类似错误是否需要报警?如果报警,有可能误报,不报警的话,可能漏报,怎么处理呢?

  • 如何统计UV, TopN

以UV为例。如果要跨任意时间度查询UV,则常规手段还需要在数据库中存入每单位时间(如分钟级别)的全量IP访问信息。这对于存储利用率来讲显然是无法接受的。有没有更优化的方案?

  • 针对错误场景的诊断方法

针对各类返回值500的调用错误,业务方提出希望出现500错误时能根据时间和调用服务维度查询到详细的调用入参和其他详情,其场景和日志搜索类似。对于类似新加入需求,貌似通过实时聚合计算和存储不能直接办到。需要对日志另辟蹊径另行处理。

  • 以上问题还不包括前段展示的各类问题。

掐指一算,两个月晃眼过了。项目还没弄完一半,小明有点急了。

另外一种新的思路

小明晚上约了自己的同门师兄老丹搓串。就着小酒,小明把自己最近的烦心事从头到尾跟老丹说了一遍。

老丹听了一拍大腿:“小明,你这就奥特了。其实在阿里云上有一款云产品, 叫做业务实时监控,简称ARMS,基本上你遇到的这些问题,在ARMS上已经提供了一站式的解决方案,你只需要快速接入即可。”。

“噢,是么?我们业务的监控逻辑很多都是基于Nginx日志定制,ARMS具备接入Nginx日志的能力,并允许让我定制业务监控能力么?“小明问道。

“当然。ARMS上不仅提供监控Nginx的任务模板,本身自带报警和监控报表,同时还全程开放定制能力。如果你要增加自己的业务监控逻辑,或者删除或修改自己不要的通用监控逻辑,直接在其平台上定制即可。”老丹答道。

未分类

“听起来不错。最终结果除了报表和报警外,公司的下游业务平台也能用么?”

“可以的,ARMS提供API, 下游系统直接对接数据API即可,跟你在云上直接读数据库没什么本质区别。”

“听起来不错,看来我的项目有救了,我赶紧去看看。”

未分类

赶紧来看看吧,看如何使用ARMS快速搭建Nginx监控任务。

nginx认证模块ngx_http_auth_basic_module

ngx_http_auth_basic_module模块基于“HTTP Basic Authentication“协议完成用户认证。

模块指令:

auth_basic 

auth_basic_user_file

这两个指令的应用范围:http,server,location,limit_except

示例:

location / {

    auth_basic           "closedsite";

    auth_basic_user_fileconf/htpasswd;

}

auth_basic指令:

语法:auth_basic string | off;

默认:auth_basic off;

开启/关闭基于“HTTP Basic Authentication”协议的用户/密码认证。

auth_basic_user_file指令:

语法:auth_basic_user_file file;

默认:–

用于指定保存用户名和密码的文件,注意文件权限。

文件格式为:

name1:password1

name2:password2:comment

name3:password3

支持的密码类型:

用crypt()函数加密,工具有htpasswd、openssl passwd

使用基于md5的密码算法的Apache变体(apr1)

使用htpasswd实现nginx的认证

1、安装htpasswd,htpasswd是apache提供的密码生成工具

yuminstall httpd-tools -y

2、htpasswd用法

$ htpasswd -h

htpasswd:illegal option -- h

Usage:

    htpasswd[-cimBdpsDv] [-C cost] passwordfile username

    htpasswd-b[cmBdpsDv] [-C cost] passwordfile username password

    htpasswd-n[imBdps] [-C cost] username

    htpasswd-nb[mBdps] [-C cost] username password

-c  Createa new file.

-n  Don'tupdate file; display results on stdout.

-b  Usethe password from the command line rather than prompting for it.

-i  Readpassword from stdin without verification (for script usage).

-m  ForceMD5 encryption of the password (default).

-B  Forcebcrypt encryption of the password (very secure).

-C  Setthe computing time used for the bcrypt algorithm

     (higheris more secure but slower, default: 5, valid: 4 to 31).

-d  ForceCRYPT encryption of the password (8 chars max, insecure).

-s  ForceSHA encryption of the password (insecure).

-p  Donot encrypt the password (plaintext, insecure).

-D  Deletethe specified user.

-v  Verifypassword for the specified user.

3、创建用户密码文件

[roger@test ~]$ htpasswd -c/etc/nginx/passwd.db xiaoming ###新创建密码文件

New password:

Re-type new password:

Adding password for user xiaoming

[roger@test ~]$ htpasswd/etc/nginx/passwd.db xiaoli ###添加新的用户

New password:

Re-type new password:

Adding password for user xiaoli

[roger@test ~]$ cat/etc/nginx/passwd.db        ###查看文件内容格式

xiaoming:$apr1$OlmGwtmd$kG6fmWrQzCWEJGT/uWXsJ.

xiaoli:$apr1$UNkIjCHM$5h6Gigl1q.IZbq6yODzAv1

4、配置nginx

location / {

    auth_basic           "welcome";

    auth_basic_user_file /etc/nginx/passwd.db;

}

访问相关内容的时候将会认证

650) this.width=650;" src="https://s5.51cto.com/wyfs02/M02/08/B3/wKiom1nl1oSDZw2SAAAZ63BET1Y888.png" title="TIM图片20171017180650.png" alt="wKiom1nl1oSDZw2SAAAZ63BET1Y888.png" />

使用对应的用户名密码可以登录访问。

端口映射+nginx对外请求控制

前几天接到个任务,要和另一家公司对接,具体就是我这开一个接口给对面调用.因为一开始在内网测试,那问题来了,怎么才能让对面访问到呢?

​ 当然是找运维大兄弟…..操作也很简单,就是用路由做一个端口映射,用公网ip做一个端口映射到我本机地址.这样外网就能访问到我的tomcat了.

比如说公网ip是192.168.1.0,我的ip是192.168.1.1,tomcat端口是8080.

那就在路由上配一个端口9876直接映射到本地tomcat 192.168.1.1:8080.那现在外网就可以通过http://192.168.1.0:9876/访问到本地http://192.168.1.1:8080/了.

就这样,做好了接口,问题又来了,因为这个接口是在核心系统里,那这样就会把所有的接口都暴露了,肯定不行..

怎么做呢,怎么才能拦截这些请求呢? 当然又去问了运维大兄弟,再查了些资料,得知用Nginx可以只允许访问指定的url,其他的都直接对外禁止访问.

那怎么做呢?

重新修改下映射规则,不直接映射到tomcat,先经过nginx,通过nginx再把请求发送到tomcat.

这里就重新映射一个端口8000,在nginx中监听这个端口,然后再配置访问规则,再代理到tomcat

在nginx.config中添加一段server

server {
#监听8080端口,这个8080是路由映射到本机的端口
listen 8000;
server_name 0.0.0.0;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
#阻止所有请求,这里将永远输出403错误
deny all;
}
#允许访问 /test/processe接口
location ~ /test/processe {
# 代理本地项目url
proxy_pass http://192.168.4.48:8080;
}
#如果还有其他接口,就再添加一个location
#location ~ /test/processe1 {
#proxy_pass http://192.168.4.48:8080;
#}
#location ~ /test/processe2 {
#proxy_pass http://192.168.4.48:8080;
#}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

这里的流程就是,外网通过访问公网ip+给定的端口,在路由根据映射规则,再访问到我这台电脑,这个时候请求不是直接去访问本机的接口,而是进入了Nginx,在这里,会去检查请求的url是否与配置允许的地址相同,不同的话就会403 Forbidden错误啦,当uri是/test/processe时,就能访问实际代理的http://192.168.4.48:8080/test/processe接口了

那这样就可以让对面只能访问指定的接口

配置laravel的nginx站点

server{}配置

server{
        #端口配置
        listen 80;
        #域名配置
        server_name laravel.cc;

        index index.php index.html index.htm;
        #站点配置到public
        root /data/wwwroot/laravel.cc/public;
      #日志记录
        access_log /data/logs/nginx.laravel.cc.log access;
        error_log /data/logs/nginx.laravel.cc.error debug;
     #静态文件配置
        location ~ .*.(jpg|jpeg|gif|png|bmp|css|js|swf|txt|ttf|woff|ico)$ {
                expires 7d;
                break;
        }

        location / {
         #重点区
                try_files $uri $uri/ /index.php?$query_string;
                index index.php index.html index.htm;
        }
        #静态文件配置
        location /logs {
                autoindex on;
                autoindex_exact_size off;
                autoindex_localtime on;
                break;
        }
        #处理php配置
        location ~ ".php$" {
                include fastcgi_params;
                fastcgi_index index.php;
                #在nginx.conf配置server_mango
                fastcgi_pass server_mango;
        }
}

http下的server_mango配置
  

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"';

    log_format access '$remote_addr [$time_local] "$http_host" "$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;
    server_tokens       off;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    gzip on;
    gzip_min_length  5k;
    gzip_buffers     4 16k;
    #gzip_http_version 1.0;
    gzip_comp_level 3;
    gzip_types       text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
    gzip_vary on;
    #重点区与server{}中的处理php应用到的
    upstream server_mango {
        server 127.0.0.1:9000;
    }
    #加载vhost下的.conf后缀所有文件
    include /usr/local/nginx/conf/vhost/*.conf;
}