Apache2 Module 开发后记

没有接触 Apache Module 开发的人可能觉得这是一个很深奥的事情,其实对于有一定经验的人来说还是挺简单的。当然最好是有这么一个环境,一些"SMTH系"的人的 blog 时常会提到什么什么时候又写了一个 Apache Module,语气犹如吃饭睡觉一样稀松平常;深受清华影响的 SOHU 也是如此,动辄就会有个人跳出来和你讨论某样业务如果用 Apache Module 来实现会如何如何,久而久之,就会在思维深处认为写 Apache Module 简直是天经地义。

1. 最通常的用法就是 ap_hook_handler. 这里是 http request 处理的最后时期。而且注册的所有的 handler 都会执行一遍。我做的模块的最核心的流程就是在某些条件下增加一个 HTTP Header 交给最终的内容处理引擎(比如JSP/PHP之类);以及设置一个 Response HTTP Header 项,当 Apache 开始向浏览器返回 Response 的时候,会把我这里添加的项目也输出出去。

2. ap_hook_handler 会应用于所有的请求,有些时候会显得效率有些低——比如对静态文件就没有必要执行额外的处理,这时候用 input_filter 可能会比较好。通过 AddInputFilter 可以设定对某些 Directory/Location 才执行对应的 filter 操作。不过据说 filter 应用也有一些效率问题,需要做详细的 benchmark 才能有结论。

input_filter 的另一个用途就是保持长连接,比如 webim 就可以通过这个方式来实现 Server 端的业务。

3. post_config 阶段可以用来检查运行模块所需要的参数是否都在 httpd.conf 里面被正确配置了。不知道 Apache 的人出于什么样阴暗的心理,post_config 会被执行两次!?这里有人提出了解决方案,如何确保自己的代码只运行一次,而不至于在 error_log 里面留下连续两行同样的LOG如同可笑的弱智bug。

由于我写的这个模块将会被部署到很多台很多台服务器上,万一哪天需要更换模块就需要找出所有部署的系统进行更新。于是每次 Apache 启动后会向一台中央服务器发送一条记录,通知该服务器维护人员的联系方式。这个流程也放在 post_config 阶段,此时 Apache 还没有 spawn 子进程,如果连接并发送记录花很长时间的话会影响 Apache 的正常服务。通常的思维是发 UDP 包出来,但这样的话需要额外写一个 UDP Server 接受它们,于是我在模块里面无耻的 fork 出一个子进程,利用 APR 提供的 socket 函数,大概 10 几行代码就搞定一次 HTTP 请求,然后马上 exit

Topic: 技术

评论

Write Apache Modules With Perl and C

国外alexa排名50左右的www.mixi.jp 还有排名71的livejournal都是采用mod_perl

试试提到的保证初始化一次的方法,这个对我很有帮助,谢谢!

由于我写的这个模块将会被部署到很多台很多台服务器上,万一哪天需要更换模块就需要找出所有部署的系统进行更新。.....
可以用一个rpm包替代,这样以后别人要更新维护项目,只要rpm -qa|grep apache
就知道里面装了多少模块子包,然后要升级或是删除都方便。
要考虑到系统管理员基本都是很不耐烦也很怕出故障之后找问题的。而且也要便于安装

自己定制RPM包不错的

我想写一个调整 http 代理 返回数据的模块。
就是 A => Apache => B =>Apache =>A

在 B=>Apache=>A 这个过程中调整一些东西

看了代码,好复杂啊