2010年7月26日星期一

Nginx的Module中使用X-Accel-Redirect的问题

再前面的一篇blog中,提到了在做一个持久配置中心。当时为了提升效率,在同事用tomcat实现的同时,我在尝试直接用nginx来完成。想通过完成一个nginx的模块,进行逻辑处理,然后把需要的数据返回回去。
    在tomcat中,是重定向请求到一个具体的文件。而我在nginx中,也是这么干的。
    在nginx的module中,我想通过 X-Accel-Redirect 这么一个header来完成,但是死活都不行,而给出的例子,都是在nginx后端所连接的系统中设置这个header,就可以起作用。比如后面挂一个tomcat,或者搞一个fastcgi去连php,都行的。按照我的理解,我觉得在nginx的模块中,直接设置这个header也应该工作的,不过事实告诉我,确实不行,这个得去问问公司这方面的专家,看看为啥是不能工作的。找个解释。

      晚上邮件咨询了下同事,同事告诉我:“这个feature是给后端服务器用的(在Nginx里面,后端服务器称为upstream,比如FastCGI、Proxy、memcached等)。在Nginx模块里是不能用这个的,可以使用internal redirect机制,就是调用ngx_http_internal_redirect”。我这下知道怎么回事儿了,不过暂时这个模块的尝试hold了,今后如果继续,就能够用这个方式了。

框架对性能的影响

  首先声明,这里提到框架对性能的影响,只是针对非常特定的场景。
    这篇博客还是源于之前的一个项目--持久配置中心。当时在压测的时候,我对并发去读配置的性能不是很满意。 
    看了代码,发现在Get的时候,还是处理了一些逻辑,之前一直以为是一个synchronized引起的,这个同步块中,是对一个计数的变量做操作,这个计数是用于判断,是否告诉当前请求的客户端,换一个服务器(为了降低本机压力)。把这个地方改为用Atomic的操作后,发现性能没有太多的提升,索性注释掉了所有的逻辑,直接返回数据。发现,好像还是不够快。我们是采用Spring MVC来完成的服务,后来直接用写了一个Servlet来提供服务,就快多了,开始用SpringMVC的响应时间平均在20ms左右,换成了Servlet后,就变为5-6ms了。
    这里不是说框架不好,其实框架对开发是带来了很多的帮助,加快了速度,降低了开发成本,这里只是想提醒大家一下,对于特别关键性能相关的地方,还是要考虑下框架是否会可能带来性能的影响。对于特别关注性能的地方,是可以用看起来不那么优雅,设置可能有些ugly的方法来实现。

一个内部简单系统-持久配置中心的经验

公司内部有一个配置中心,采用推送的方式来推送配置到客户端,对于Runtime的数据和持久的数据,都采用同样的方式处理。整个系统是一个集群。持久的数据也都是存在每个节点上,节点之间的数据会复制。
    我总觉得,持久的数据的特性和非持久(Runtime)的会有所不同,一般Runtime的数据的特点是需要非常快的更新到客户端,让客户端感知到数据的变化。而持久的数据,需要的是客户端启动时的可靠获取,以及配置数据持久保存的安全性等。
    后来主导,起了一个新的产品,专门用于管理持久配置数据的,提供了Get的高可用性,采用数据库并且主备的方式,保证数据本身的安全。
    产品出来后,发现了几个问题,
        第一个,内部有了两个配置中心,一个是管理持久数据的,一个是Runtime数据的,但是,对于内部的开发人员来说,复杂了
第二个,原来都是使用一个客户端,现在迁移的时候,有一定的迁移成本,而不是完全透明的
第三个,对于运维的同事和线下的配置管理员来说,多了一套系统
第四个,其实之前没有仔细分析清楚,就是对于持久的配置数据,一般是不会改动的,但是真的改动的时候,也是需要能够立即通知到客户端的。而这个地方,确实新的持久配置中心没有解决好的。
    在开始这个产品之前,觉得是尽量把持久的配置中心做到很简单,做到可以应对意外情况(比如意外的时候,可以读取本地配置;配置是文本的,可以方便的人工介入),可以,还是有不少的地方没有想清楚。这个真是教训啊。
    对于一个看似简单的产品,
         1 还是需要想清楚真实的使用场景
 2 考虑对现有的影响,包括但不限于使用这个产品的人;运维人员;配管人员;测试人员等等。
 3 类似概念的产品,最好只有一个。对于Runtime的配置,持久的配置,其实都是配置,虽然特性上可能会有很大的差别,但是对于使用者,还是隐藏一些使用上的细节比较好。