最后更新于 .

不是第一次写nginx的自定义模块了,之前有写过根据POST数据转发请求的模块(参见nginx自定义模块编写-根据post参数路由到不同服务器),不过上次写的是处理模块,而这次写的是过滤模块,还是有一些区别的。 在正式开始前,先说一下写nginx自定义模块要注意的几个点:

  1. 上次的文章提到,在函数里用r-connection.log打印log会core,今天发现是ngx头文件和lua头文件引用顺序的问题,把ngx的头文件放在最前面即可解决
  2. nginx的一个字符串类型 ngx_str_t 有两个参数, len 和 data,这两个参数一定要一起使用,因为data的\0结尾,不一定是len的长度,这一点千万要注意
  3. 需要和cpp文件联合编译是,在ngx的编译参数里面加上--with-ld-opt="-lstdc++"

OK,废话不多说,开始正式说我这次写的统计模块吧 需求背景呢,就是现在已经在nginx后面挂了很多服务器,需要用nginx来统计成功率,响应时间等等参数,在网上翻了半天,大部分居然是用access_log,然后用程序扫描$request_time来实现的,这对一个每秒几千次访问的服务器是不可忍受的,所以最终没办法,那就自己写一个呗~ 重新看了nginx自定义模块的开发文档,整个调用过程如下:

1

但是实在是没找到请求整个结束时的回调函数,最接近的也就是用filter模块了(即过滤模块),当然这样统计出来的请求时间,可能会比实际时间短一些。 OK,定了要写那种模块后,我们来考虑一下具体的实现

  1. 为了性能最大话 ...

最后更新于 .

之前对bottle做过不少的介绍,也写过一些文章来说明bottle的缺点,最近发现其实之前有些地方说的不太公平,所以趁此机会也来更正一下。

  • bottle是支持类似flask url_for的语法的,具体使用方法在下文介绍
  • bottle的request.query之类的参数默认是str类型,也是有原因的,比如我在给google做代理的时候,编码就不一定是utf8的,如果强制转化utf8就会报错
  • 之前的bug也得到了修正,比如mount('/x',app)之后,/x/和/x都可以访问到

OK,现在正式进入主题,我们来介绍一些bottle的一些高级使用

一. 智能创建url

这部分在bottle的文档上是没有介绍的(其实bottle明明实现了很多贴心的功能,不知道为啥都不写在文档上)。 在Bottle类里,有一个成员函数:

def get_url(self, routename, **kargs):
    """ Return a string that matches a named route """
    scriptname = request.environ.get('SCRIPT_NAME', '' ...

最后更新于 .

还是和往常一样,没啥主题,就是记录下这段时间遇到的技术问题,分享一下。

1. 在javascript中实现简单的模板替换

最近搞了一下js,最不习惯的就是字符串生成都要用字符串拼装或者join的方式,所以尝试一下看能否实现简单的模板替换,效果还不错。

function str_format(str, obj) {
    return str.replace(/\{\s*(\w+)\s*\}/g, function(_i, _1) {
        return obj[_1] != null ? obj[_1] : '';
    });
};

很多朋友会说性能差一些,可能确实如此,不过对我来说,相比编写的舒适来说,这点性能差别实在无足轻重了。

2. uwsgi报readv() faild

用uwsgi+nginx搭建的server,发现当用post请求时,会返回数据超时。查了一下uwsgi的error.log:

9825#0: *745262 readv() failed (104: Connection reset by peer ...

最后更新于 .

前段时间有博友在群里问了一个关于vim排序的问题,因为时间问题一直没帮忙解决,今天时间正好空出来,就帮忙搞了一下。 原文的问题如下:

vimuser 说:
2012年03月1日 于 5:04 下午  (编辑)
今天折腾了一下午,研究vim的排序,看了教程和搜索了一些文档,还是没弄明白,vim的正则表达式跟一般的又不一样,来请教下博主。

|1 | 11 | 111| 1111|
|2 | 22 | 222| 2222|
要根据第3个|和第4个|之间的列进行排序该如何写命令呢?

其实之前也只是简单的用过vim的sort命令,没有想过vim是否能完成如此复杂的排序,不过抱着试试看的态度,我看了一下sort的描述(:h :sort),其中一段话如下:

:[range]sor[t][!] [i][u][r][n][x][o] [/{pattern}/]

When /{pattern}/ is specified and there is no ...

最后更新于 .

nginx可以轻松实现根据不同的url 或者 get参数来转发到不同的服务器,然而当我们需要根据http包体来进行请求路由时,nginx默认的配置规则就捉襟见肘了,但是没关系,nginx提供了强大的自定义模块功能,我们只要进行需要的扩展就行了。 我们来理一下思路,我们的需求是:

nginx根据http包体的参数,来选择合适的路由

在这之前,我们先来考虑另一个问题: 在nginx默认配置的支持下,能否实现服务器间的跳转呢?即类似于状态机,从一个服务器执行OK后,跳转到另一台服务器,按照规则依次传递下去。 答案是可以的,这也是我之前写bayonet之后,在nginx上特意尝试的功能。 一个示例的配置如下:
server {
    listen       8080;
    server_name  localhost;

    location / {
        proxy_pass http://localhost:8888;

        error_page 433 = @433;
        error_page 434 = @434;
    }
    location @433 {
        proxy_pass http://localhost:6788;
    }
    location @434 {
        proxy_pass http://localhost:6789;
    }

    error_page ...

最后更新于 .

其实之前就有写过关于python web开发框架选择的文章,之前最终选择了bottle,并给出了bottle开发的物理设计,详见之前的文章:回归简单,向Django说再见bottle做web开发的物理设计,然而经过最近两个星期的实践,又有了一些新的想法。

Bottle作为一个微框架,本身确实有些小型项目的缺点,尝试列举如下:


  • 没有原生支持unicode

  • 例如route('/')获取的name并不是unicode类型,get和post的参数也默认并非unicode类型,虽然作者后来在0.10版本中给query和forms加入attr方式来解决这个问题,但是还是有所限制
    而flask则是 unicode based,对unicode支持的非常好
  • 影响力小,与其他组件的结合比较差

  • 一个典型的例子就是wtforms不支持bottle的files字段,而flask虽然也不支持,但是flask的插件flask-wtforms则完美修正了这个问题
  • 功能太基本

  • 关于这一点,可以说是优点也可以说是缺点。绝对的纯粹看起来是件好事,但是真正开发起来又发现完全不是那么回事,自己要重新开发的轮子实在太多了。比如session的支持
  • bottle由个人开发,有些地方并不那么专业

  • 比如route的参数method=['GET','POST'],因为是数组,所以用methods更合适;request.forms其实用request.form更合适
    再比如static_file函数,必须要求传入一个root_path和一个filename;而flask则有两个函数一个send_file和send_from_directory,支持直接返回file内容

反观flask,不能说flask的一切都是好的,但是确实在这几点上要比bottle做的要好一些,而且flask还有一些很实用的功能,比如实时debug ...

最后更新于 .

前段时间家里的无线路由还没到,手机直接连电信的路由又没法拨号(万恶的电信),所以没办法只能尝试在windows7开启隐藏的虚拟wifi热点功能~~ OK,开始~

1. 以管理员身份运行命令提示符

“开始”---在搜索栏输入“cmd”----右键以“管理员身份运行”

2. 启用并设定虚拟WiFi网卡

运行命令:

netsh wlan set hostednetwork mode=allow ssid=dantezhu_wifi key=00000000

"ssid"后为网络名称,起个名字就行 "Key"后为密码,一般要求是8位 执行完之后,打开“网络和共享中心”--“更改适配器设置”看看是不是多了一项,若果有多出的这一项“Microsoft Virtual WiFi Miniport Adapter”,为方便区分,将其改名为“虚拟wifi”。

1

3.设置Internet连接共享

在“网络连接”窗口中,右键单击已连接到Internet的网络连接,选择“属性”→“共享”,勾上“允许其他······连接(N)”并选择“虚拟WiFi”。

1

这里要注意的是,如果像我一样采用宽带拨号,那么要更改的网络链接是那个“宽带链接”而不是“本地链接”

4.开启无线网络

继续在命令提示符中运行:

netsh wlan start ...

最后更新于 .

过年回来也一直没发博客,其实东西还是搞了不少的,挨个给大家分享一下吧 今年过年回家恶补了一下js和css,发现vim的 css.vim 在处理着色的时候有bug,描述如下: 如果是如下css代码:

#menu ul li { background: #eee; border-bottom: 1px solid #ccc;}

则原版的css.vim 无法在同一行上显示两种颜色(#eee和#ccc),所以笔者修改了css.vim的代码,放出下载如下: http://vimercode.googlecode.com/svn/trunk/css.vim/css.vim

最后更新于 .

从老家回来第一天,特向各位博友拜个晚年~
祝福大家新年快乐,龙年大吉!
家庭幸福美满,事业蒸蒸日上!
心想事成,万事如意!

最后更新于 .

前几天同事的程序有个很奇怪的bug,跟大家分享一下。 描述如下:一个http接口在测试环境下能够正常访问,在外网环境下就会直接超时,并且超时的消耗是建是0ms。 我strace了一下,libcurl在测试环境能正常发包,在外网环境却总是直接返回,连连接都没有尝试建立。 仔细研究了他的代码,发现并没有什么不合理之处,一筹莫展时发现有如下代码:

curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, (int)(timeout_sec*1000));                                                        
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, (int)(timeout_sec*1000)); 

突然想起之前有文章说curl只支持秒级的超时时间,而我们外网的超时配置的是0.5秒。 把超时时间改成1秒之后,果然一切正常了。 google上搜了一下,在如下链接找到了答案: http://stackoverflow.com/questions/1856473/why-would-curl-ignore-curlopt-timeout-ms-but-honor-curlopt-timeout

The version of curl I am using (7.15.5) doesn't support CURLOPT_TIMEOUT_MS. According to Greg I ...