项目

通用

个人资料

操作

开发问题与解决方案

本页面旨在列出lighttpd的开发挑战、问题以及(或许)已分析出的解决方案。
功能请求应发布到lighttpd 论坛进行讨论。

.htaccess-类功能

问题

支持 .htaccess-类功能

在单一的Apache服务器中,.htaccess是:
  • 健壮的,例如语法错误不会停止服务器
  • 动态加载的,即文件更新时(无需重启Apache)即可生效
  • 有限的配置设置(受限选项)
  • 有限地访问请求范围外的配置;虚拟主机用户无法损害其他用户

讨论

lighttpd 支持平滑服务器重启,并且可以在不暂停或等待现有请求完成的情况下重新加载其配置。在配置更改后重启lighttpd是一种罕见的事件,其性能远高于为每个HTTP请求在运行时动态重新加载和重新处理.htaccess(Apache)。

lighttpd 轻量,并且有更好的选项来隔离用户配置,例如使用在单独用户帐户下运行的独立 lighttpd 实例。

解决方案

  • 选项
    • mod_rewrite url.rewrite-if-not-file 是许多框架的简单解决方案
      例如,如果文件存在,让 lighttpd 提供静态文件(如 .js, .css, .jpg 等),否则重写以将请求发送到 /index.php
      url.rewrite-if-not-file = ( "" => "/index.php?path=${url.path}${qsa}" )
  • 选项
    • 配置独立的应用程序服务器,并让应用程序实现.htaccess策略
      例如,通过PHP-FPM和每个应用程序的php.ini PHP htscanner
  • 选项
    • 将 .htaccess 转换为包含在 lighttpd.conf 中的文件
    • 用户触发的即时平滑重启(在后台进程中继续处理现有请求的同时重新加载配置)
      server.feature-flags += ("server.graceful-restart-bg" => "enable") (server.feature-flags)
      server.systemd-socket-activation = "enable"
  • 选项
    • 将 .htaccess 转换为自定义 Lua 脚本,使用 mod_magnet 运行
      .htaccess 用于 URL 重写和访问控制的常见用法可以写入自定义 Lua 脚本中。
      $HTTP["url"] =~ "^/app(?:/|$)" { magnet.attract-raw-url-to = "/path/to/app/.htaccess.lua" }
      mod_magnet 脚本被缓存,并在修改时动态重新加载。

如果非管理员用户正在编写 lighttpd.conf 包含文件或 Lua 脚本,则应配置 lighttpd 前端,使用 mod_proxy 反向代理到每个应用程序(或每个用户)的 lighttpd 后端实例,例如运行 mod_magnet,并可能被授权让应用程序所有者(或用户)配置 lighttpd.conf 并触发每个应用程序(或每个用户)lighttpd 实例的重启。

单线程编码的困难

问题

Lighttpd 是 c10k 问题的一个概念验证,因此它被设计成单进程/单线程。
为什么是个问题:单线程很难编码,因为每当遇到会阻塞的系统调用时,都必须将其异步化。

讨论

将一些复杂任务转移
  1. 到一个新线程
  2. 到一个派生的子进程
  3. 作为后端(例如 fcgi 后端),这意味着它被构建成独立的 可执行文件。
规则和事情可以在另一个线程或进程中完成
  1. 静态文件请求/响应处理应保留在主 I/O 线程中
  2. 除非引起问题,否则大部分当前实现保持不变。
  3. 对于从文件自动重新加载配置、从 MySQL 加载虚拟主机设置等,我们应该在另一个线程中完成还是只使用 fam?
  4. fastcgi 化的 magnet,lua + FastCGI
  5. 移出 mod_rrdtool(在 1.5 中被 jan 废弃(已废弃),但我认为应该移出而不是移除)
    TODO:更多备注在此

原因:多线程/进程并非邪恶,fastcgi/php 已经成为独立/后端进程。
多线程/进程既不是关键问题,单线程也不是 c10k 的关键解决方案。
问题在于 1:1 模型(我说的不是线程调度模型):每 1 个连接必须由 1 个线程或进程来处理,同样地,1 个 php 实例至少打开 1 个到 mysql 的持久连接。
这会消耗大量内存并需要大量进程/线程,直到操作系统无法处理。
在 lighttpd 的当前实现中,使用 TCP 处理 HTTP,你仍然必须进行 1 对 1 的连接与文件句柄映射,这比过多的线程/进程要好得多,幸运的是我们有像 Linux epoll 这样 O(1) 的操作系统实现。

gstrauss 大约 4 年前 更新 · 19 次修订