类别归档:Web开发

RSS feed of Web开发

最后更新于 .

不是第一次写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 ...

最后更新于 .

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 ...

最后更新于 .

前几天同事的程序有个很奇怪的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 ...

最后更新于 .

前段时间一直没写博客,昨天更新了一篇,今天突然又来了兴致,那就再更新一篇吧(所以说啊,治疗拖延症最好的方法就是现在开始做) 这篇还是一些技术的整理,主要是用于备忘,大家如果觉得太简单就一笑而过啦~

一. python通过图片内容判断图片类型

前段时间写了一个小站练手,http://xiangshuguo.com,一个支持自由上传的图片小站。 因为要限制上传图片的格式,所以要做文件类型检测,代码如下:

def get_image_type(pd, is_path=True):
    '''
    获取图片的类型,支持传入路径和文件内容
    '''
    if is_path:
        f = file(pd, 'rb')
        data = f.read(10).encode('hex')
    else:
        data = pd.encode('hex')

    ftype = None

    if data.startswith('ffd8'):
        ftype = 'jpeg'
    if data ...

最后更新于 .

几年之前刚玩wordpress的时候,还是用apache+wordpress,而后来虽然自己成了nginx粉,却也只是用来做nginx+python的开发,没有把nginx+php配合起来。这次趁这要搭建wordpress的调试环境,所以重新梳理了一遍。 PS:网上很多盛传的版本,基本都不太准,我这里算是亲身试验了,给大家个准的 PS2:这次就在windows下来搞了,其实在linux也是一样 OK,我们正式开始 一. php安装部署

  1. php windows下载页面下载zip包,而不是安装包
  2. 解压,我是解压到 D:\program\php5
  3. 重命名php.ini-production为php.ini
  4. 修改php.ini
  5. 将如下代码去掉注释来支持mysql
    extension=php_mysql.dll
        
    将如下代码去掉注释,来指明ext的路径
    extension_dir = "ext"
        

二. mysql安装部署

  1. http://www.mysql.com/downloads/mysql/下载windows版MySQL ...

最后更新于 .

接着回归简单,向Django说再见,继续来聊用bottle做web开发。 其实上一篇文章已经讲的比较清楚了,这一次主要从另一个角度来分享一下:物理设计 干脆直接贴出来吧:

bottle_site_tpl/
|~conf/
|~depend/
| |+autumn/
| |+jinja2/
| |+wtforms/
| |-__init__.py
| `-bottle.py
|~log/
| `-site.log
|~module/
| |-__init__.py
| |-forms.py
| |-models.py
| |-mysession.py
| `-web_func.py
|+static/
|~views/
| `-test.html
|~web/
| |-__init__.py
| `-test.py
|-myapp.py
`-setting.py

可以看出,最外层有两个文件,分别是setting.py 和 myapp.py。 setting ...