尝试优化Nginx正则表达式是否值得?

3
在一个Nginx虚拟主机中,我添加了这些位置信息,其中两个使用正则表达式:
    location ~ /-/pubsub/subscribe/(.*)$ {
      # subscribe to websocket
    }
    location ~ /-/pubsub/publish/(.*)$ {
      # websocket publish endpoint
    }
    location / {
      # reverse proxy to the application server
    }

但是我可以像这样做,来“隐藏”正则表达式吗?
    location /-/pubsub/ {       <-- can be tested without any regex matching
      location ~ subscribe/(.*)$ { ... }
      location ~ publish/(.*)$ { ... }
    }

    location / {
      # reverse proxy
    }

我认为这样可以避免解析任何正则表达式,用于匹配请求的location /,因为它们将与location /-/pubsub/(无正则表达式)进行比较,而不是与location ~ /-/pubsub/whatever/(.*)$(有正则表达式)进行比较,对吗?
同样,我已将视频上传与其他上传分开,因为视频上传使用了一个正则表达式:
  location /-/uploads/public/video/ {
    location ~ \.(mp4|m4v|m4a)$ {   <-- regex matching for videos only
      mp4;
    }
  }

  location /-/uploads/public/ {
    # all other files: no regex matching needed
  }

但我不确定为了避免正则表达式而进行这种有点复杂的配置是否有意义。将视频保存在另一个文件夹中,只是为了避免使用正则表达式。这样做会更快吗?值得这么做吗?


如果模式搜索经常发生,那么速度会更快;通常来说,开销越小越好,特别是在Web服务器上。即使是优化过的正则表达式也可以在效率方面产生很大的差异。 - l'L'l
为什么如果搜索发生得越频繁,速度就会更快?难道Nginx会因为它经常使用而进行额外的优化吗?无论如何,每个访问网站的用户都会下载大约100个微小的25x25用户头像图像(Web应用程序是论坛软件,主题列表页面显示最近主题中用户的头像)。CDN是有意义的,但即使没有CDN,我也希望这个过程也相当快。 - KajMagnus
例如考虑你的模式.(mp4|m4v|m4a),每次对于每个文件,它都需要大约68步骤来执行正则表达式引擎;在高流量的服务器上,这可能会累加(主要是CPU开销)。正则表达式模式匹配很好,但是如果有更直接的方法,请采用。 - l'L'l
如果可以用简单明了的方式完成,那就去做,否则就别费心了,我敢打赌你的应用程序会更加低效。我认为你的示例非常简单,值得借鉴。 - Alexey Ten
1
顺便提一下,location ~ /-/pubsub/subscribe/(.*)$ 应该完全替换为无正则表达式的 location /-/pubsub/subscribe/ - Alexey Ten
2个回答

3
这取决于你的使用情况。由于nginx使用pcre,最终你正在问“pcre是否使用CPU”,显然是肯定的。但是,如果nginx所做的大部分工作是提供文件对象和管理远程tcp套接字,则您不会看到影响。如果您在nginx中进行极快的代理工作(考虑50k +连接),我的经验是您绝对会从正则表达式优化中受到重大性能影响。
要确定你的瓶颈究竟在哪里,你需要使用像tcpdump这样的工具,并查找时间到第一个数据字节。此外,apache bench是单线程的,因此在高容量Web服务器上非常有限。如果你必须使用那个工具,我建议制作一个ab实例的集群并将结果相加。

1

我使用ab (https://httpd.apache.org/docs/2.4/programs/ab.html) 进行了一些快速测试,发现使用下面的简单正则表达式和不使用正则表达式,在性能上没有任何区别。

我测试了以下内容:

location /-/uploads/public/ {
  access_log off;
  alias /opt/debiki/uploads/public/;  <-- serving one 1.4 kb avatar image from here
  autoindex off;
  sendfile on;
  sendfile_max_chunk 2m;
  tcp_nopush on;
  expires 31d;  # later:  expires 365d;

  location ~ \.(mp4|m4v|m4a)$ {   <-- regex
    mp4;
  }
}

注释掉正则表达式并没有让我注意到有什么更快的变化。(使用了5或10个带有正则表达式的样本和5或10个不带正则表达式的样本, 每个样本都是ab -n50000 -c10. 结果在14500和15500 req/seq之间,随机波动,无论是否使用正则表达式。)
所以我的结论是,如果可以避免使用location正则表达式而不产生任何成本,则是的。但如果避免像上面的location ~ \.(mp4|m4v|m4a)$这样的简单正则表达式有点复杂,比如将某些文件移动到另一个目录中,那么就不要这样做。这不值得。(更复杂的正则表达式?那我就不知道了。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接