Django 初体验

本来没准备去了解python+django,但是工作需要还是了解了一下;从执行效率上来讲,python和PHP基本是同一个级别的语言,我没指望python能有多么好的执行效率,鉴于django是python界赫赫有名的web开发框架,于是就测了一下。

2核8G的cpu下测试django的hello world,大概也就500+的qps。什么?fastcgi?是的,用fastcgi的方式也做了测试,真心没明显变化,fastcgi就真的fast吗?只是相对cgi来讲确实fast了不少,但不是神器。尤其:django的fastcgi实现用的是flup  ; flup是纯python实现的,从这一点来讲,还不如PHP,赖好PHP的fastcgi还是C实现的。

django说 1.9 之后不再使用fastcgi了

关于mysql锁的学习

锁的类型: 表锁、页锁、行锁、间隙锁【读锁(共享锁)、写锁(排他锁)】、乐观锁、悲观锁(晕,其实没这么多东西)

mysql.INNODB_LOCKS 这张表记录了发生了锁争用的信息;虽然一个事务正在加了一些锁,如果没有其它session等待这些锁的话,这个表里面也是查不到的哦

但是,A表正在事务中被更新时,如果:

lock tables A write;

虽然被阻塞,但是 mysql.INNODB_LOCKS里面却查不到任何记录!  (why: lock tables 不是存储引擎级别的锁)

 

实例分析:

表结构:

sql语句1:

sql语句2:

如果简单认为innodb的锁都是行锁(尤其是select和insert操作的压根儿也不是一行),怎么可能发生死锁呢?

让我们模拟一下,分别在两个session中一行一行地交替执行两个事务,我们发现,确实在insert的时候死锁了

session 1:

 

session 2:

 

如果我们不着急去执行session 2中的insert的语句,而是查询一下存在哪些锁,发现如下:

什么是supremum pseudo-record?

supremum pseudo-record :相当于比索引中所有值都大,但却不存在索引中,相当于最后一行之后的间隙锁

解决办法:

 

参看: http://blog.itpub.net/26250550/viewspace-1070422/

 

问题: 两个select … for update ; 加的是共享锁?否则不能同时两个select语句都能成功执行。还如何查证?

不能简单地说 select … for update 加的是共享锁还是排他锁; 如果select有结果,则加行锁,此时为排他锁; 如果没有结果,则加间隙锁,此时为共享锁(和间隙大小没有关系); 如果没有在事务中,则select for update是不加锁的;

参看: Enabling InnoDB Monitors: https://dev.mysql.com/doc/refman/5.6/en/innodb-enabling-monitors.html

可以查看当前被设置的锁的信息:

部分信息如下:

 

下面是insert 语句等待时的锁情况:

 

学习资料:

http://hedengcheng.com/?p=771    非常不错

nginx 配置之read_timeout

nginx配置文件中有各种timeout,比如:fastcgi_read_timeout ;如果没有一些经验,很可能会认为该配置会限制fastcgi请求的时常,其实不然,不过,很多情况下确实是这样的。

比如,我们将fastcgi_read_timeout 设置为5s,并非fastcgi最大允许执行5s,而是:

当nginx发送完请求,开始从fastcgi读取数据时,当然,这时候fpm一般还没能立即处理完,没法立即返回响应数据,则nginx读不到数据,则开始计时,如果fpm能在5s内响应点儿数据(即使不全也没关系),则nginx就可以读取到该数据,继续尝试读取时,发现又需要等待,则重新开始5s的计时,如果fpm总是能保证5s内响应一部分数据,则nginx愿意一直候着,一旦超过5s读不到数据,nginx就不干了

PHP测试代码:

 

欧了

ftp proxy

ftp协议包含控制链路和数据链路以及主动模式和被动模式,使得ftp协议的代理变得复杂。而且ftp协议设计上没有考虑代理情况(协议上无法知道要连接的真实地址),包括ftp的client也多不支持代理,尤其是透明代理不方便实现,大概是没有一种标准的代理方式。常见的标识真实目标地址的方法是在用户名后面@server来实现

  1. https://github.com/fredbcode/ftpproxy
  2. apache mod_ftp_proxy
  3. http://www.ftpproxy.org/
    1. 似乎默认只能和xinetd一起工作
  4. squid

 

VPN/auth/encrypt/pptp/l2tp/openvpn

VPN就安全吗?

vpn从概念上来讲只是“虚拟私有网络”,不意味着安全;如果需要auth,就安全了吗?也不一定,就如同web上的http服务,用户一般也需要登录,但是传输层都是明文;所以,还需要加密;最近使用pptp的时候就发现pptp是没有加密功能的,这样的vpn其实是不安全的。vpn设计的时候都会考虑到安全问题,而采用加密方式的。(原来在vpn的虚拟网卡上抓包看到了明文,就怀疑没有加密,其实应该在真实网卡上抓包来验证是否vpn通道是加密的)

killall 之困

缘起

多个相同名字的进程要全部杀死,很自然会用killall; 但是,如果没杀死,将会很郁闷;

结论:

killall参考的是 /proc/pid/comm ;而我们看到的一般是/proc/pid/cmdline ;

如:php-fpm进程显示为:

而我们killall时,写法为:

killall php-fpm

为什么不需要 pool www ? (因为killall 默认不是精确匹配的,-e选项可以精确匹配,man killall)

另外,我们执行top命令时,‘c’键可以切换命令行列的“短格式”和“长格式”;其实不是什么“短格式”和“长格式”,‘f’ 键可以看到,其实就是comm和cmdline的切换:

pptp 协议学习

缘起

今天要从阿里金融云pptp 到外部的vpn服务器,未能成功,tcpdump抓包结果为:开始几次tcp包交换之后,似乎变成了非tcp的ip协议了,只是开始不再回包,于是开始了解pptp协议。

后测试,发现阿里非金融云是可以pptp到外部服务器的。

 

分析结论:

阿里金融云不允许GRE;  (阿里的弹性公网IP相关文档中有明确描述不支持GRE的,虽然我们用的不是弹性公网IP,或许实现是相同的)

GRE有什么安全问题吗?稍后再研究

 

PPTP: Point to Point Tunneling Protocol  点对点隧道协议

GRE:  Generic Routing Encapsulation 通用路由封装

PPTP 的连接过程如下图:

 

参考资料:

http://blog.csdn.net/yu_xiang/article/details/9204211

http://blog.csdn.net/msptop/article/details/2451138

http://baike.baidu.com/link?url=KuQHEpUftD_nfw3KdWl-HhZMBxxI7uPHu3c0LQHhwBFfMYicwwiHvAd_oFitKks8wDN9LeaR1Wk3tDXU9HI_Uq

PHP 如何做文件上传下载服务

或许你会问:刚开始学习PHP的时候都会做文件的上传下载,难道这还有什么要研究的吗?

呃….有

为了方便讨论,这里基于nginx+fpm来讨论。

默认情况下:

对于文件上传下载服务,请求从开始到结束,需要全程有一个fpm进程来伺候的,如果同时有1000个文件上传的请求,则需要有1000个fpm进程来伺候;一般来讲,上传或下载文件都需要持续较长的时间,用一个进程来伺候一个请求不是浪费,是非常浪费

 

 

参考资料:

http://www.jb51.net/article/51854.htm

http://www.ttlsa.com/nginx/nginx-modules-upload-module/

强大的SO_REUSEPORT

一般来讲,一个(服务)进程listen了一个端口,如果重复启动,则会报端口被占用的错误,听起来也很合理。突然发现linux上出现了SO_REUSEPORT,似乎多个进程可以同时listen同一个端口。

测试脚本 server.php:

注意:

  1. centos7上如果是yum安装的php,则posix模块的安装方式是: yum install -y php-process  (这个名字不叫posix)
  2. 启动之后,如果用yum安装的nc来测试,会出现连接被refused的情况,这是因为centos7上的nc默认用的是tcp6(socket_create时使用AF_INET6),一个服务确定的是连接的3要素:协议、IP、端口;切记,tcp和tcp6是两种不同的协议 ; 解决办法:添加 -4选项,即: nc -4 localhost 2345

执行:

php server.php &

既然设置了SO_REUSEPORT,则应该可以再启动一个吧?结果,同时启动两个,则两个进程都被stop了

再看: 去掉 ‘&’ 来执行 php server.php   ,不放打开多个terminal,我这里打开了两个,发现两个进程都没有再停止了

再打开一个terminal,执行:

while :; do echo “hello”|nc -4 localhost 2345;done

输出里面混杂出现两个进程的pid,证明:两个进程在同时提供服务了;

注意: 即使是多个进程在提供服务,netstat中看到的却只有一个进程在listen

(mac下测试相同脚本,结果是: netstat中可以看到多个进程在listen,但是实际测试却只有一个进程在提供服务,反正我也不同mac来提供线上服务,这里就不研究mac了)

问题: 为什么我这个脚本不能推到后台执行????????

strace 跟踪发现,可能和标准输出有关系(这个应该也是centos7和前面版本的差异),把标准输出重定向走:

php server.php >/dev/null &

 

这样就不会停止了,之于标准错误、标准输入是否会有其他的影响,这个这里就不再研究了

 

总结:

SO_REUSEPORT 真心不错

 

参考资料:

http://www.blogjava.net/yongboy/archive/2015/02/04/422732.html

https://my.oschina.net/miffa/blog/390931