大头龙仔Blog

A strong man can save himself. A great man can save another.

[‘PHP 5’ => ‘PHP 7’]

| Comments

一、背景介绍

  • 目前所维护的项目服务框架组成: Windows + C#, Linux + PHP + Python, MongoDB
  • 由于历史原因而存在两个操作系统平台,C#部分的代码逻辑耦合很强,拆分非常困难
  • 我们后端的人员储备基本上都是PHP的应用开发
  • 考虑未来迭代维护,我们需要去C#化
  • PHP 7带来了不错的性能提升,提前升级为C#改写为PHP做准备

二、PHP 7的一些变化

  • PHP 7 Release Note

  • ZVAL的变化

  • 结构体内存占用对比

我们可以看到,数据结构的变化还是非常大的,所以release note里的的关于大幅降低内存占用的那个item应该也不是吹的。

三、PHP 7为系统带来的提升

  • 一些经典的开源项目升级前后对比

  • ulabox.com升级PHP 7

  • 升级PHP 7后CPU与内存占用都大幅降低,为某公司年节省100w刀

四、升级PHP 7

(上面都在吹别人的,现在到我们自己折腾了)

1)PHP EXT之变

  • 在PHP7开始, 我们移除了MAKE_STD_ZVAL / ALLOC_ZVAL宏, 不再支持存堆内存上申请zval. 函数内部使用的zval要么来自外面输入, 要么使用在栈上分配的临时zval
  • 所以PHP 5的扩展模块是不能直接兼容PHP 7

2)MongoDB Driver For PHP 7

  • 当前使用的MongoDB扩展并不支持PHP 7

  • 发了邮件问作者 – –!!!

  • github上提的issue

  • PHPC-286

  • 看了源码,的确工作量巨大(mongo.so),而官方推荐使用的是这个 mongodb.so

  • 不幸的是,mongodb.so与mongo.so的接口调用方式还是有挺多不一样的,并且官方推荐使用mongo-php-library,所以有下面关系: PHP 5: mongo.so PHP 7: mongo-php-library(PHP) –> mongodb.so

  • 到这里,我只想说

3)升级后部分接口性能对比

  • PHP 7 VS PHP 5 (OPcache Enable, ms, less is better)

  • 我们发现get_raw_data_list接口性能大幅下降

4)XDebug + WinCacheGrind

  • 对get_raw_data_list进行调试

  • php中间层mongo-php-library加入,提升数据访问接口灵活性,但也导致了性能的降低,我们可以从上图中发现大量的bson对象的转换。

  • [‘typeMap’=>[‘root’=>‘array’,‘document’=>‘array’]],这个参数可以让该库不转换成bson对象,重新优化了代码后,耗时从922ms下降到398ms

5)升级后性能下降了?

  • 因为MongoDB的扩展驱动换了,所以这里不能做最直接的比较,但像get_raw_data_list这样的接口几乎是db的直接读取接口,所以驱动对其影响是最大的。

  • 我们也能注意到像get_summary, get_reputation_word_freq这样的接口性能提升了30%,这些接口主要是进行了数据的计算

  • C#的接口正在迁移中,所以暂时还没有实际的对比数据,但考虑到除7带来的提升外,相对老接口还会多引用多进程、多线程的处理,这里的优化数据还是非常值得期待

6)其它

  • 目前使用的是pcntl,后续会多加入pthreads以提高并行处理效率

  • 注意DEPRECATED in PHP 5.x, and REMOVED in PHP 7.0.0.的接口

  • 多了个php-cli.ini,cli下默认就用这个配置文件了

  • OPcache记得用上

五、结论

  • 新项目上PHP 7

  • 旧项目先评估PHP扩展模块的兼容性(包括公司内部的……)

  • PHP5与7可以共存一段时间,对比调试

  • 引入非官方扩展(自己写)时要慎重考虑,能用php语言自身解决的(socket, pack, unpack等),基决不用扩展。Less is more.

六、Reference

DRouter路由篇

| Comments

早些入手了一个华硕AC88U,一星期左右就闲鱼出去了,之后入了网件R7000,一直用网件,非常稳定。 前段时间又想着买个NAS玩玩,随便看看感觉都不便宜,于是决定自己DIY一个,那不如也带上路由的功能吧,于是就有了drouter的计划,本篇先从主机组装、Linux和基本路由功能说起吧。

硬件列表

  • 技嘉J1900主板(低功耗, ITX,有PCI预防网卡坏掉,板载双网卡)
  • 4G笔试本内存
  • 两个2T日立企业盘,后面要组软RAID 1(企业盘就是贵,预算多的这里上SSD做系统盘感觉爽好多)
  • JONSBO C2机箱(装得下两个3.5硬盘,又小巧的,只找到了这个)
  • 全汉400W服务器电源(买上了档次的电源我都选择全汉,本来想试试新巨的)

系统安装

我选的是slackware 14.1,这个自己喜欢就好,但安装过程因为要组RAID 1,slackware还是说得很详细,大体上是:

  • 使用cfdisk分区,我是分了root 100G,swap 8G
  • 分区同步: sfdisk -d /dev/sda | sfdisk --Linux /dev/sdb
  • root: mdadm --create /dev/md0 --level 1 --raid-devices 2 /dev/sda1 /dev/sdb1 --metadata=0.90
  • swap: mdadm --create /dev/md1 --name=1 --level 1 --raid-devices 2 /dev/sda2 /dev/sdb2
  • mkswap: mkswap /dev/md1
  • 开始常规的slackware setup,lilo那里会失败,不用管先安装完
  • chroot /mnt,修改lilo.conf,加入raid-extra-boot = mbr-only,root和boot设为/dev/md0,执行lilo
  • mdadm -Es > /etc/mdadm.conf以记录软raid的信息,如果不执行这个,有可能会reboot失败

PPPOE拨号

  • pppoe-setup
  • 填入账号密码等
  • FIREWALL=MASQUERADE
  • pppoe-start,应该就可以拨上去了,使用网口eth1,ifconfig应该出现ppp0
  • 如果要让系统访问外网,要加iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT,可以看看/etc/ppp/firewall-masq
  • /etc/resolv.conf,我用的是119.29.29.29114.114.114.114

DHCPD(动态分配IP)

  • /etc/dhcpd.conf
1
2
3
4
5
6
7
8
9
default-lease-time 600;
max-lease-time 7200;
subnet 192.168.1.0 netmask 255.255.255.0{
  range 192.168.1.100 192.168.1.200;
  option routers 192.168.1.1;
  option domain-name-servers 119.29.29.29;
  option ip-forwarding off;
  option broadcast-address 192.168.1.255;
}

最后

eth0是对内网的,所以接到交换机,PC, AP等接入交换机,自动获取IP后,就可以上网啦,至此完成一台有基本路由功能的server。下面几个是为了增强稳定性的。

  • 断线自动重连/etc/cron.d/pppoe-keep.sh
1
2
3
4
5
6
7
8
9
#!/bin/sh

while true; do
    /sbin/ifconfig ppp0 > /dev/null
    if [ $? -ne 0 ]; then
        /usr/sbin/pppoe-start
    fi
    sleep 5
done
  • 断线自动重连watch dog/etc/cron.d/pppoe-keep_watchdog.sh
1
2
3
4
5
6
#!/bin/sh

ps uax | grep 'pppoe-keep.sh' | grep  -v grep
if [ $? -ne 0 ]; then
    /bin/sh /etc/cron.d/pppoe-keep.sh &
fi
1
2
# keep pppoe connecting
* * * * * /bin/sh /etc/cron.d/pppoe-keep_watchdog.sh
  • 每天自动断线一次 /etc/cron.daily/pppoe-stop
1
2
3
#!/bin/sh

/usr/sbin/pppoe-stop
  • 每周机器自动重启一次 /etc/cron.weekly/reboot
1
2
3
#!/bin/sh

/sbin/reboot

NOT THE END

一些脚本和配置都在这里https://github.com/imlcl/DRouter/。后面会有DDNS, NAS等续篇 : )

A Little SCNUCrew

| Comments

那天偶然和bbin一起找回以前的一些视频看,然后哈哈大笑,接着我去SCNUCrew Blog寻宝,找了一些,放在这里做一个纪念吧(blog图片区:P)

视频系列

随笔系列

其它

人生总有一次不懂,生活总有一次茫然,突然发现,自己的身边已经走失了那么多人,有些人,不知不觉,就淡了关系,有些人,无声无息,就远离视线,时间一天天过,好像什么也没改变,但当你回头看,每个人都变了,有的从眼前走到了天边,有的从陪伴进入了心间,明明入心的人,转身就变的陌生,明明不在意的情,有时瞬间让你感动,缘分这东西,不经意会错过,太认真会难过,落花有意水无情,有缘无份空叹息,相识相知本不易,人走茶凉奈何兮,不怕身隔南北,只怕心在天涯,不畏暖心多年,只恐心凉一瞬,唯有时间能看清真心,鉴别真情,曲终人散后依然为你而留的,才叫陪伴,物是人非中依旧拿心而守的,才是珍惜。

国庆在家刷个票

| Comments

刷票什么鬼的已经不是一个什么新鲜话题了。放假期间受朋友所托去刷个票,整个过程还是有些东东可以分享的。

一、为什么可以刷票

基于HTTP协议是处于应用层,所以HTTP包是很容易可以构造出来的,也就是说,人通过浏览器去投票发出的HTTP请求包,机器是可以模拟构造出来的。

二、刷票前我们要了解什么

1、投票时是否绑定session

2、投票时是否识别ip

3、投票时是否需要验证码

4、投票时需要提交什么数据到什么目标地址(这里包括是否要带上特定的cookie字段,是否要识别终端等HTTP头信息)

所以,针对不同的投票网站,可能会有不一样的变通方案,但都不会离开上面四点。 这次投票的网站,经过分析,1、2是yes,3是no,不用验证码哦,这个刷票门槛马上低了n个层次,不过发现是识别ip的,一个ip投一票,请空cookie后可以继续投。 一个ip经测试,一般可以投20-30票,如果速度不快的话。

三、来来来,开刷了

感觉没上代码不舒服,先上个代码先

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php
include_once('ip.php');

$url     = URL;
$timeout = TIMEOUT;

# USER AGENT哦, 多搞几个是好事
$user_agents = array(
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
    'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36'
    );

while (1)
{
    # 通过代理API获取IP
    $ret        = file_get_contents(IP);
    $ret        = json_decode($ret, true);
    $proxy_list = $ret['data']['proxy_list'];
    print_r($proxy_list);

    foreach ( $proxy_list as $proxy ) {
A:
        $ua = $user_agents[array_rand($user_agents)];
        $options = " -v
                     -A \"$ua\"
                     -m $timeout
                     -x $proxy
                     -H \"Content-Type: application/x-www-form-urlencoded; charset=UTF-8\"
                     -H \"X-Requested-With: XMLHttpRequest\"
                     -H \"Origin: http://abc.com\"
                     --referer \"http://abc.com/vote.html\"";
        $cmd = "/usr/bin/curl $options -d \"i=xxx\" \"$url\"";
        # 用的是cmd, 用php curl也可以
        $output = exec($cmd);
        echo $cmd;
        echo "\n*******************\n$output\n******************\n";

        $ret = json_decode($output, true);
        print_r($ret);
        if ( $ret['success'] == '1' ) {
            echo $proxy . "\n";
            # 模拟停一秒, 感觉可以停久一些
            sleep(1);
            # 神奇的goto
            goto A;
        }
    }
}
?>

因为是和IP相关的投票,所以只能通过代理了,这里就只能去买代理啦,只用高匿的,因为这样server那边是不知道你是用了代理的,这个请自行google了。 另外curl需要给个user agent,这样就不需显示curl了,更加真实一点,多点user agent随机会比较靠谱。

四、这次刷票遇到的其它问题

1、估计大家都用代理嘛,代理资源可能有很多是重复的,你会发现很多取回来的代理已经不能投票了(别人已经用这个代理投过票,并且该代理IP已入黑名单), 或者说投一到两票就不能投了,所以这样刷票是有点不稳定的,如果有一手的代理资源这个问题就可以解决。

2、大家都在刷,大家都在抢占资源,所以我们可以多开些进程去刷,这里要考虑代理获取IP的API调用频率限制问题了,太快的也是不行的。

3、代理也分布在不同网络,电信、移动、网通、铁通之类,所以刷票机在多个网络会更好一些。

4、刷票的时间最好和人正常的作息时间对应,也就是说要更智能一点,更像人在投票一点。

5、因为朋友说不想名次太高,所以我另外也写了一个程序来判定是否在前几名之外,如果不在前几名,就开始刷。这些边边角角的代码就不好意思贴出来了,写得比较快,所以比较粗烂……

五、如果有验证怎么办

这个比较恶心,因为验证码要涉及图形识别,不同图形验证码的识别率也不一样,这一块我没有深入研究过,但知道Tesseract Open Source OCR Engine可以通过不断学习来提高图形验证码的识别率。当然也可以自己写识别算法来处理,图形学是博大精深,小弟只懂个皮毛,不过有时间还是想试试这个东东。

刷票软件什么的也很厉害,以前好像有用过,大家都可以找找看吧。我这里只是分享其中一种方法与思路,应该算是刷票的基本功吧,因为软件什么的也是基于这个思路来写的,不过功能更多强大和自动化而已。

话说刷票不便, 这种无验证码的淘宝也要四毛一票呢,我这帮朋友刷了4w多票,Just a joke : )

EOF

Less Is Less

| Comments

想了很久,很不情愿地用了这个标题。

这一年里,无论从个人情感上、心理上还是行动上,都发生了巨大的变化,甚至可以说是有生以来最大的一次巨变: 放弃公办教师来到腾讯CDC,与家庭磨合分隔两地的工作生活, 从小影响着我并深爱着我的老爸中风半身偏瘫,一下子打破了家里平静小幸福的生活状态, 妈妈全职照顾老爸,爱人辞职带小孩,也突然感觉得生活艰难了好几分。 没有把这事情诉说给什么人去听,因为除非对方的家庭也有相似的经历,否则根本没有办法理解的。

偶尔静下心来想想,真的说不出这一年来,我真正收获了什么东西。 可能收获的都是无形的,我看不到,但有这样的感觉,我就会觉得是件很恐怖的事情。 在一个设计师的团队里做一名死开发,感觉这就是我的现状,同时感觉内部这样的开发环境和氛围,对于专业的提升真的是非常有限,可能是因为一定程度的封闭。 然后,需求淹满了一些想法,直到变成让自己都讨厌的习惯。 而我也努力在寻找某种提升的方法与动力,抑或是针对我个人,抑或是“团队”。

一年前的改变,然后发现自己在某些东西上依旧没什么变化,甚至渐行渐远,在这样的压力下并不是一件好事。

可是这就是生活,这就是现实,收拾一下心情,不在沉默中死亡,就是沉默中爆发。