写给运维的Nginx秘籍
zhezhongyun 2025-05-11 19:40 22 浏览
要说Web服务器、代理服务器和调度服务器层面,目前使用最大的要数Nginx。对于一个运维工程师日常不可避免要和Nginx打交道。为了更好地使用和管理Nginx,本文就给大家介绍几个虫虫日常常用的秘籍。
限制访问
当Nginx开放到公网上以后,就会有大量的非正常访问,这不光耗费服务器资源,而且有可能是某种信息探索,然后攻击的前奏,有对针对性的限制这些访问很有必要。在Nginx中可以通过一些内置的变量来进行限制访问。
限制客户端代理
在nginx可以使用$http_user_agent变量匹配客户类型,然后对对匹配的访问return 4.3来限制器访问。
在Nginx配置的server部分,直接用if语句实现:
if ($http_user_agent ~ (Go-http-client/1.1|curl)) {
return 403;
}
但是如果要匹配的客户端代理比较多时候,直接这样拼写就比较繁琐也不好管理。这种情况下给大家一个技巧就是用Map函数。
Map函数在Nginx ngx_http_map_module中实现的。利用Map函数可以创建一个变量,并将其与其他变量(比如内置的$http_user_agent)关联起来,可以同时关联多个值到多个不同值并储存到一个变量。其基本语法为:
map $var1 $var2 { ... }
其作用于为http模块,这样可以在开头映射后,然后在具体的server部分进行封禁。
对应本例子中
map $http_user_agent:$arg_key $ban {
~*spider* 1;
~Go-http-client/1.1 1;
~curl;
default 0;
}
这样在后续if封禁语句中就可以使用新建的$ban变量进行封禁了。
if ($ban = 1) {
return 403;
}
IP限制
有时候对一些恶意来源的IP封禁则更为直接简单有效。Nginx进行IP封禁的方法也很简单,直接用deny语句,他是Nginx内置模块ngx_http_access_module,支持allow和deny两个语句,基本语法为:
deny address | CIDR | unix: | all;
可以在http或者server块直接使用:
deny 135.125.180.235;
如果要封闭的IP很多,可以直接在nginx配置文件中include一个封禁文件专管理封禁的IP。
include banip.conf;
在banip.conf文件中用:
deny 135.125.180.235;
deny 135.125.180.1/24;
…
这样语句即可,当然也可以用allow和deny all搞成实时上的白名单限制模式:
allow 127.0.0.1;
allow 192.168.0.0/18;
allow 110.242.68.66;
…
deny all;
这样除了本机、18位的内网段和110.242.68.66外其他IP都会禁止访问。
速率限制
除了直接限制访问外很多时候,不能直接限制其访问,但是需要针对特定请求限制访问的速率(频率)。在Nginx速率限制通过limit_req_zone和limit_req两个指令实现。
limit_req_zone用来定义请求限制区域。区域包含有关如何分类的配置请求速率限制和实际限制。
limit_req将区域应用于特定http上下文对于全局限制,server每个虚拟服务器,以及location对于虚拟中的特定位置服务器。
为了说明这一点,假设要实现速率限制配置:
全局速率限制100 RPS
由User-Agent来限制特定来源(搜索蜘蛛)请求为1RPM。
通过API令牌将来自某些可以客户端的请求限制为1RPS。
要对请求进行分类,需要提供索引到 limit_req_zone。键通常是一些变量,要么由nginx预定义,要么由通过map定义。
要通过IP设置全局速率限制,需要以IP作为键。
limit_req_zone $binary_remote_addr zone=global:100m rate=100r/s;
现在,通过以下方式限制搜索蜘蛛的User-Agent,此处我们使用map函数:
map $http_user_agent $crawler {
~*.*( Baiduspider|bot|spider|slurp).* $http_user_agent;
default "";
}
limit_req_zone $crawler zone=crawlers:1M rate=1r/m;
上面配置中通过map设置$crawler变量作为limit_req_zone的键。limit_req_zone对于不同的客户端必须有不同的值才能正确计算请求计数。如果请求不是来自crawler,使用一个空字符串来禁用速率限制。
对API令牌限制请求,使用map创建一个多个键,对应其速率限制区域:
map $http_authorization $eclients {
~.*6d96270004515a0486bb7f76196a72b40c55a47f.* 6d96270004515a0486bb7f76196a72b40c55a47f;
~.*956f7fd1ae68fecb2b32186415a49c316f769d75.* 956f7fd1ae68fecb2b32186415a49c316f769d75;
default "";
}
limit_req_zone $eclients zone=eclients:1M rate=1r/s;
下面我们来看看 AuthorizationAPI 令牌的标头,如 Authorization: Bearer 1234567890. 如果我们匹配一些已知的标记,我们使用该值$eclients为了变量,然后其作为键引入到limit_req_zone。
server {
listen 80;
server_name test.show;
limit_req zone=crawlers;
limit_req zone=global;
# ...
}
server {
listen 80;
server_name api.test.show;
# ...
location /heavy/method {
# ...
limit_req zone=eclients;
limit_req zone=global;
# ...
}
# ...
}
请注意,配置中必须添加globa区域作为后备,非匹配的情况。
最后总结一下速率限制的流程:
创建保存速率限制的变量的键。不同键值对应于不同的速率限制区域。
空键表示禁用速率限制。
使用带限速键的变量来配置限速区域配置。
在需要的地方应用速率限制区域limit_req。
速率限制将有助于保持系统稳定。
除了速率限制,Nginx也有一个请求频率限制方法limit_conn_zone和对应的 limit_conn用来限制请求的频次。其使用方法,具体和limit_req_zone以及limit_req的方法也类似,下面是一个例子:
http {
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server {
location / {
limit_conn perip 10;
limit_conn perserver 1000;
}
}
}
缓存
Nginx 最大的用途是作为代理缓存服务器。假设请求代理到某个后端应用服务器,后端服务器返回请求数据的成本很高。则可以通过缓存它来减少后端的负载。
http {
# ...
proxy_cache_path /var/cache/nginx/test keys_zone=test:500m max_size=1000m inactive=1d;
# ...
server {
# ...
location /test {
proxy_pass test.show_backend;
proxy_cache test;
proxy_cache_key "$scheme$proxy_host$request_uri $http_customer_token";
proxy_cache_valid 200 302 1d;
proxy_cache_valid 404 400 10m;
}
}
}
在此示例中,通过添加 $http_customer_token保存值的变Customer-Token HTTP 标题。然后,与速率限制一样,定义缓存区域应用于服务器、位置或全局使用 proxy_cache指示。另外还要配置缓存失效。 默认情况下,仅对200、301 和 302 HTTP状态码响应缓存,超过10分钟更新一次缓存内容。另外对于后端服务器Nginx会遵守其指示性的Http头,例如Cache-Control标头。如果标头包含类似no-store,must-revalidate,nginx则不会对其缓存响应。可以在Nginx配置
proxy_ignore_headers "Cache-Control";
来覆盖该行为。
因此,要配置 nginx 缓存失效,请执行以下操作:
设置max_size在 proxy_cache_path限制磁盘的占用。如果nginx需要缓存超过max_size,将从缓存中移除最近最少使用的值
设置inactive参数输入proxy_cache_path配置TTL整个缓存区。可以用 proxy_cache_valid指示。
最后,添加proxy_cache_valid将指示TTL的指令在给定位置或服务器中缓存项目,这将为缓存设置TTL条目。
结构化日志
从Nginx访问日志是个大宝藏,我们可以通过其挖掘当前Web服务的在线状态,使用状态和用户信息。但是其默认访问日志有点太简陋,需要对其进行配置增加必须的字段,调整其位置,使其更加格式化。Nginx日志的配置需要用 log_format语句。一个典型的配置如下:
log_format main '$remote_addr - $remote_user [$time_iso8601] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent - $ssl_client_s_dn $ssl_client_serial $ssl_client_verify" "$http_x_forwarded_for"';
上述配置中,除了常见的各种字段外,另外增加了$ssl_client_s_dn $ssl_client_serial和$ssl_client_verify,用于在https双向认证时候客户的端用CA签发dn信息,用户证书序列号用来记录合法认证的用户信息。
另外为了和ELK或者其他日志系统的集成使用json格式的结构化日志很有必要,可以使用graylog将文本日志转化,也可以直接在Nginx配置生成:
http {
# ...
log_format json escape=json '{'
'"server_name": "test.show",'
'"ts":"$time_iso8601",'
'"remote_addr":"$remote_addr","host":"$host","origin":"$http_origin","url":"$request_uri",'
'"request_id":"$request_id","upstream":"$upstream_addr",'
'"response_size":"$body_bytes_sent","upstream_response_time":"$upstream_response_time","request_time":"$request_time",'
'"status":"$status"'
'"$https_info": "$ssl_client_s_dn $ssl_client_serial $ssl_client_verify"'
'}';
# ...
}
escape=json选项将替换不可打印的字符,如换行符和转义值,例如\n. 引号和反斜杠也将被转义。
如果是K8S容器云节点的服务可以,直接用filter用来指定:
filter {
json {
source => "log"
remove_field => ["log"]
}
}
灰度发布(A/B测试)
运维部门为了保证服务升级,往往会采用灰度发布的方式,逐步将用户切换到新的版本中。
在Nginx 可以用split_client模块实现提供逐步升级的功能。他有点类似像map函数,但不是通过某种模式设置变量,而是创建来自源变量分布的变量。下面一个例子:
http {
upstream current {
server backend1;
serverbackend2;
}
upstream new {
server dev.show max_fails=0;
}
split_clients $arg_key $new_api {
5% 1;
* 0;
}
map $new_api:$cookie_app_switch $destination {
~.*:1 new;
~0:.* current;
~1:.* new;
}
server {
# ...
location /api {
proxy_pass $destination/;
}
}
}
在此示例中,app_switch和split_clients cookie 值结合生成调度键。如果 cookie设置为设置$destination调度到上游的new为1。 否则,从 split_clients调度。这是在生产一种用于测试新系统的功能标志:拥有cookie集用户都将始终请求到new。
键的分布是一致的。如果已将API键用于split_clients那么具有相同API键的用户将始终被放入同一组。
使用此配置,可以将流量分流到新系统,从小百分比开始并逐渐增加。当然修改百分比参数后,不需要reload才能生效。
结论
本文我们介绍一些日常运维中Nginx的管理秘籍,当然密不密不是绝对只是个人看法,希望以此抛砖引玉,如果你有任何建议和建议补充,可以回复说明。
相关推荐
- 一篇文章带你了解SVG 渐变知识(svg动画效果)
-
渐变是一种从一种颜色到另一种颜色的平滑过渡。另外,可以把多个颜色的过渡应用到同一个元素上。SVG渐变主要有两种类型:(Linear,Radial)。一、SVG线性渐变<linearGradie...
- Vue3 实战指南:15 个高效组件开发技巧解析
-
Vue.js作为一款流行的JavaScript框架,在前端开发领域占据着重要地位。Vue3的发布,更是带来了诸多令人兴奋的新特性和改进,让开发者能够更高效地构建应用程序。今天,我们就来深入探讨...
- CSS渲染性能优化(低阻抗喷油器阻值一般为多少欧)
-
在当今快节奏的互联网环境中,网页加载速度直接影响用户体验和业务转化率。页面加载时间每增加100毫秒,就会导致显著的流量和收入损失。作为前端开发的重要组成部分,CSS的渲染性能优化不容忽视。为什么CSS...
- 前端面试题-Vue 项目中,你做过哪些性能优化?
-
在Vue项目中,以下是我在生产环境中实践过且用户反馈较好的性能优化方案,整理为分类要点:一、代码层面优化1.代码分割与懒加载路由懒加载:使用`()=>import()`动态导入组件,结...
- 如何通过JavaScript判断Web页面按钮是否置灰?
-
在JavaScript语言中判断Web页面按钮是否置灰(禁用状态),可以通过以下几种方式实现,其具体情形取决于按钮的禁用方式(原生disabled属性或CSS样式控制):一、检查原生dis...
- 「图片显示移植-1」 尝试用opengl/GLFW显示图片
-
GLFW【https://www.glfw.org】调用了opengl来做图形的显示。我最近需要用opengl来显示图像,不能使用opencv等库。看了一个glfw的官网,里面有github:http...
- 大模型实战:Flask+H5三件套实现大模型基础聊天界面
-
本文使用Flask和H5三件套(HTML+JS+CSS)实现大模型聊天应用的基本方式话不多说,先贴上实现效果:流式输出:思考输出:聊天界面模型设置:模型设置会话切换:前言大模型的聊天应用从功能...
- ae基础知识(二)(ae必学知识)
-
hi,大家好,我今天要给大家继续分享的还是ae的基础知识,今天主要分享的就是关于ae的路径文字制作步骤(时间关系没有截图)、动态文字的制作知识、以及ae特效的扭曲的一些基本操作。最后再次复习一下ae的...
- YSLOW性能测试前端调优23大规则(二十一)---避免过滤器
-
AlphalmageLoader过滤器是IE浏览器专有的一个关于图片的属性,主要是为了解决半透明真彩色的PNG显示问题。AlphalmageLoader的语法如下:filter:progid:DX...
- Chrome浏览器的渲染流程详解(chrome预览)
-
我们来详细介绍一下浏览器的**渲染流程**。渲染流程是浏览器将从网络获取到的HTML、CSS和JavaScript文件,最终转化为用户屏幕上可见的、可交互的像素画面的过程。它是一个复杂但高度优...
- 在 WordPress 中如何设置背景色透明度?
-
最近开始写一些WordPress专业的知识,阅读数奇低,然后我发一些微信昵称技巧,又说我天天发这些小学生爱玩的玩意,写点文章真不容易。那我两天发点专业的东西,两天发点小学生的东西,剩下三天我看着办...
- manim 数学动画之旅--图形样式(数学图形绘制)
-
manim绘制图形时,除了上一节提到的那些必需的参数,还有一些可选的参数,这些参数可以控制图形显示的样式。绘制各类基本图形(点,线,圆,多边形等)时,每个图形都有自己的默认的样式,比如上一节的图形,...
- Web页面如此耗电!到了某种程度,会是大损失
-
现在用户上网大多使用移动设备或者笔记本电脑。对这两者来说,电池寿命都很重要。在这篇文章里,我们将讨论影响电池寿命的因素,以及作为一个web开发者,我们如何让网页耗电更少,以便用户有更多时间来关注我们的...
- 11.mxGraph的mxCell和Styles样式(graph style)
-
3.1.3mxCell[翻译]mxCell是顶点和边的单元对象。mxCell复制了模型中可用的许多功能。使用上的关键区别是,使用模型方法会创建适当的事件通知和撤销,而使用单元进行更改时没有更改记...
- 按钮重复点击:这“简单”问题,为何难住大半面试者与开发者?
-
在前端开发中,按钮重复点击是一个看似不起眼,实则非常普遍且容易引发线上事故的问题。想象一下:提交表单时,因为网络卡顿或手抖,重复点击导致后端创建了多条冗余数据…这些场景不仅影响用户体验,更可能造成实...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 教程 (33)
- HTML 简介 (35)
- HTML 实例/测验 (32)
- HTML 测验 (32)
- JavaScript 和 HTML DOM 参考手册 (32)
- HTML 拓展阅读 (30)
- HTML文本框样式 (31)
- HTML滚动条样式 (34)
- HTML5 浏览器支持 (33)
- HTML5 新元素 (33)
- HTML5 WebSocket (30)
- HTML5 代码规范 (32)
- HTML5 标签 (717)
- HTML5 标签 (已废弃) (75)
- HTML5电子书 (32)
- HTML5开发工具 (34)
- HTML5小游戏源码 (34)
- HTML5模板下载 (30)
- HTTP 状态消息 (33)
- HTTP 方法:GET 对比 POST (33)
- 键盘快捷键 (35)
- 标签 (226)
- HTML button formtarget 属性 (30)
- CSS 水平对齐 (Horizontal Align) (30)
- opacity 属性 (32)