有没有办法让 Nginx 在来自推荐人的点击量超过阈值时通知我?
例如,如果我的网站在 Slashdot 上有特色,并且突然间我在一小时内有 2K 的点击量,我想在一小时的点击量超过 1K 时收到通知。
是否可以在 Nginx 中执行此操作?可能没有lua?(因为我的产品不是lua编译的)
有没有办法让 Nginx 在来自推荐人的点击量超过阈值时通知我?
例如,如果我的网站在 Slashdot 上有特色,并且突然间我在一小时内有 2K 的点击量,我想在一小时的点击量超过 1K 时收到通知。
是否可以在 Nginx 中执行此操作?可能没有lua?(因为我的产品不是lua编译的)
我认为使用 logtail 和 grep 会更好。即使可以使用 lua 内联,您也不希望每个请求都有这样的开销,尤其是当您被 Slashdotted 时,您更不希望这样做。
这是一个 5 秒的版本。将其粘贴到脚本中并在其周围放置一些更具可读性的文本,您就成功了。
当然,这完全忽略了 reddit.com 和 facebook.com 以及所有其他可以为您带来大量流量的网站。更不用说 100 个不同的站点,每个站点都会向您发送 20 个访问者。您可能应该只有一个普通的旧流量阈值,它会导致向您发送电子邮件,而不管引荐来源。
nginx limit_req_zone指令可以将其区域基于任何变量,包括 $http_referrer。
不过,您还需要做一些事情来限制 Web 服务器上所需的状态量,因为引荐来源标头可能非常长且多种多样,您可能会看到无穷无尽的变化。您可以使用 nginx split_clients功能为所有基于 referrer 标头哈希的请求设置一个变量。下面的示例仅使用 10 美元,但您可以同样轻松地使用 1000 美元。因此,如果您被 slashdotted,其引荐来源恰好哈希到与 slashdot URL 相同的存储桶中的人也会被阻止,但您可以通过在 split_clients 中使用 1000 个存储桶来将其限制为 0.1% 的访问者。
它看起来像这样(完全未经测试,但方向正确):
最有效的解决方案可能是编写一个守护程序来跟踪该
tail -f
字段。access.log
$http_referer
然而,一个快速而肮脏的解决方案是添加一个额外的
access_log
文件,只记录$http_referer
带有自定义的变量log_format
,并每 X 分钟自动轮换一次日志。这可以在标准 logrotate 脚本的帮助下完成,它可能需要正常重启 nginx 以便重新打开文件(例如,标准程序,看一下SO 上的 /a/15183322一段时间-基于脚本)…
或者,通过在 中使用变量,可能通过在或指令的帮助下
access_log
获取分钟规范(取决于您想要放置 的位置)。$time_iso8601
map
if
access_log
因此,对于上面的内容,您可能有 6 个日志文件,每个日志文件涵盖 10 分钟的时间段
http_referer.Txx{0,1,2,3,4,5}x.log
,例如,通过获取分钟的第一位数字来区分每个文件。现在,您所要做的就是拥有一个可以每 10 分钟运行一次的简单 shell 脚本,
cat
将上述所有文件放在一起,通过管道传输到sort
,通过管道传输到uniq -c
,到sort -rn
,到head -16
,然后您就有了 16 种最常见Referer
变体的列表— 自由决定数字和字段的任何组合是否超出您的标准,并执行通知。随后,在一次成功通知后,您可以删除所有这 6 个文件,并且在后续运行中,除非所有六个文件都存在(和/或您认为合适的某个其他数量),否则不会发出任何通知。
是的,在 NGINX 中当然可以!
您可以做的是实施以下DFA:
基于 实施速率限制,
$http_referer
可能通过 a 使用一些正则表达式map
来规范化值。当超过限制时,将引发内部错误页面,您可以根据相关问题error_page
通过处理程序捕获该页面,将其作为内部重定向转到新的内部位置(客户端不可见)。在上述超出限制的位置,您执行警报请求,让外部逻辑执行通知;该请求随后被缓存,确保您在每个给定时间窗口只会收到 1 个唯一请求。
捕获先前请求的 HTTP 状态代码(通过返回状态代码 ≥ 300 并使用
proxy_intercept_errors on
,或者,使用默认未构建auth_request
或add_after_body
发出“免费”子请求),并完成原始请求,就好像不涉及先前的步骤。请注意,我们需要启用递归error_page
处理才能使其工作。这是我的 PoC 和 MVP,也在https://github.com/cnst/StackOverflow.cnst.nginx.conf/blob/master/sf.432636.detecting-slashdot-effect-in-nginx.conf:
请注意,这按预期工作:
您可以看到第一个请求导致一个前端和一个后端命中,正如预期的那样(我不得不向具有 的位置添加一个虚拟后端
limit_req
,因为 areturn 200
会优先于限制,所以不需要真正的后端其余的处理)。第二个请求超出了限制,所以,我们发送警报(getting
200
),并缓存它,返回429
(这是必要的,因为前面提到的限制不能捕获低于 300 的请求),随后被前端捕获,现在是免费的,可以自由地做任何想做的事。第三个请求仍然超出限制,但我们已经发送了警报,因此不会发送新的警报。
完毕! 不要忘记在 GitHub 上分叉它!