wadezhan / billfeller.github.io Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
作者:zhanhailiang 日期:2014-12-13
参考文章:
本文提供基于Sort Set进行活跃用户统计的PHP版本:
https://github.com/billfeller/billfeller.github.io/blob/master/code/UserTj.php
作者:zhanhailiang 日期:2014-12-14
twemproxy,也叫nutcraker,是twtter开源的Redis和Memcache代理服务器。
从官网下载安装包编译并安装:distribution tarball:
[root@~/software/nutcracker-0.3.0]# ./configure --prefix=/usr/local/nutcracker-0.3.0
[root@~/software/nutcracker-0.3.0]# make
[root@~/software/nutcracker-0.3.0]# make install
[root@~/software/nutcracker-0.3.0]# cp -R conf /usr/local/nutcracker-0.3.0
[root@~/software/nutcracker-0.3.0]# ln -s /usr/local/nutcracker-0.3.0 /usr/local/nutcracker
[root@~/software/nutcracker-0.3.0]# ln -s /usr/local/nutcracker/sbin/nutcracker /usr/local/bin/nutcracker
twemproxy支持通过YAML语法配置,其支持的指令集如下:
以本文为例,配置一个Redis代理和一个Memcache代理如下:
[root@~/software/nutcracker-0.3.0]# cat /usr/local/nutcracker/conf/nutcracker.yml
alpha:
listen: 127.0.0.1:22121
hash: fnv1a_64
hash_tag: "{}"
distribution: ketama
auto_eject_hosts: false
timeout: 400
redis: true
servers:
- 127.0.0.1:6379:1
beta:
listen: 127.0.0.1:22122
hash: fnv1a_64
distribution: ketama
timeout: 400
backlog: 1024
preconnect: true
auto_eject_hosts: true
server_retry_timeout: 2000
server_failure_limit: 3
servers:
- 127.0.0.1:11211:1
- 127.0.0.1:11212:1
其中,Redis实例 127.0.0.1:6379 和 Memcache实例 127.0.0.1:11211 127.0.0.1:11212 请预先启动好。
/etc/init.d/redis_6379 start
/usr/local/memcached-1.4.20/bin/memcached -d -m 64 -l 127.0.0.1 -p 11211 -u root
/usr/local/memcached-1.4.20/bin/memcached -d -m 64 -l 127.0.0.1 -p 11212 -u root
https://github.com/billfeller/billfeller.github.io/blob/master/code/twenproxyTest.php
启动服务:
[root@/usr/local/nutcracker/conf]# nutcracker -c nutcracker.yml
[Sun Dec 14 20:59:04 2014] nc.c:187 nutcracker-0.3.0 built for Linux 2.6.32-431.23.3.el6.x86_64 x86_64 started on pid 14359
[Sun Dec 14 20:59:04 2014] nc.c:192 run, rabbit run / dig that hole, forget the sun / and when at last the work is done / don't sit down / it's time to dig another one
执行测试脚本:
[root@~/wade/git/billfeller.github.io/code]# /usr/local/php/bin/php twenproxyTest.php
bool(true)
string(1) "1"
int(1)
bool(false)
bool(true)
int(2)
bool(true)
int(3)
bool(true)
bool(false)
作者:zhanhailiang 日期:2014-12-21
Bitmap 对于一些特定类型的计算非常有效。
假设现在我们希望记录自己网站上的用户的上线频率,比如说,计算用户A上线了多少天,用户B上
线了多少天,诸如此类,以此作为数据,从而决定让哪些用户参加beta测试等活动——这个模式可以使
用SETBIT和BITCOUNT来实现。
比如说,每当用户在某一天上线的时候,我们就使用SETBIT,以用户名作为key,将那天所代表的网站
的上线日作为offset 参数,并将这个offset 上的为设置为1。
举个例子,如果今天是网站上线的第100天,而用户(uid=10086)在今天阅览过网站,那么执行命令SETBIT sign:10086 100 1;如果明天用户(uid=10086)也继续阅览网站,那么执行命令SETBIT sign:10086 101 1,以此类推。
当要计算用户(uid=10086)总共以来的上线次数时,就使用BITCOUNT命令:执行BITCOUNT sign:10086,得出的结果就是用户(uid=10086)上线的总天数。
以上线次数统计例子,即使运行10年,占用的空间也只是每个用户10*365比特位(bit),也即是每个
用户456字节。对于这种大小的数据来说,BITCOUNT的处理速度就像GET和INCR这种O(1)复杂度的
操作一样快。
如果你的bitmap数据非常大,那么可以考虑使用以下两种方法:
1. 将一个大的bitmap分散到不同的key中,作为小的bitmap来处理。使用Lua脚本可以很方便地完成这一工作。
2. 使用BITCOUNT的start和end参数,每次只对所需的部分位进行计算,将位的累积工作(accumulating)放到客户端进行,并且对结果进行缓存(caching)。
https://github.com/billfeller/billfeller.github.io/blob/master/code/ISign.php
《Redis.pdf》
作者:zhanhailiang 日期:2015-01-07
直接使用命令行git pull操作正常,如下:
D:\vipshop\mstats\mstats-monitor>git pull
Updating 5050c42..e8b3bd9
Fast-forward
public/css/app.css | 30 ++++++++++++++++++
public/js/page.counts.js | 68 +++++++++++++++++++++++++++++++++--------
views/counts.html | 8 +++++
views/includes/module_list.html | 3 +-
4 files changed, 96 insertions(+), 13 deletions(-)
但是使用TortoiseGit pull时报错“/bin/sed: Bad file number”,详情如下:
git.exe pull -v --progress "origin"
/libexec/git-core/git-sh-setup: line 81: /bin/sed: Bad file number
From http://gitlab.tools.vipshop.com/wade.zhan/mstats-monitor
= [up to date] master -> origin/master
C:\Program Files (x86)\Git/libexec/git-core\git-pull: line 268: /bin/tr: Bad file number
Your configuration specifies to merge with the ref 'master'
from the remote, but no such ref was fetched.
git did not exit cleanly (exit code 1) (2090 ms @ 2015/1/7 10:08:05)
根据提示“Your configuration specifies to merge with the ref 'master' from the remote, but no such ref was fetched.”,指的是merge远端引用master,但是fetch不到该引用。
查了下git help pull命令详情:
git pull [options] [<repository> [<refspec>…]]
怀疑是因为缺少参数导致,尝试下手动执行完整命令,如下:
D:\vipshop\mstats\mstats-monitor>git.exe pull -v --progress "origin" master
From http://gitlab.tools.vipshop.com/wade.zhan/mstats-monitor
* branch master -> FETCH_HEAD
= [up to date] master -> origin/master
Already up-to-date.
这里就定位到问题,应该缺省参数导致,右键菜单 TortoiseGit->Settings->Git->Edit local .git/config,在[branch "master"]修改remote = origin master,如下图:
然后就可以正常使用TortoiseGit pull了:
git.exe pull -v --progress "origin" master
From http://gitlab.tools.vipshop.com/wade.zhan/mstats-monitor
* branch master -> FETCH_HEAD
= [up to date] master -> origin/master
Already up-to-date.
Success (2121 ms @ 2015/1/7 10:08:38)
参考文章:
作者:zhanhailiang 日期:2014-12-12
通常,缓存逻辑是设置一个过期时间,若缓存失效时,就请求后端读取数据并更新缓存。 但是该方案在高qps的场景下会出现问题——在[缓存失效,请求后端读取数并更新缓存)时间段内,所有的请求都会全部透传到后端,该场景对后端将会产生大量请求。所以我们的目标是希望减少这部分请求数。
代码如下:https://github.com/billfeller/billfeller.github.io/blob/master/code/cache.php
方案的选择依赖于数据支撑,需要后端团队提供当前相关接口的并发数再做方案评估。
两种方案都可行,看具体评估。
基于HTTP协议的轻量级开源简单队列服务:HTTPSQS
参考张宴的文章:http://zyan.cc/httpsqs/7/1/
内部分享使用方法
The C10K problem:http://blog.csdn.net/21aspnet/article/details/7003275
The C10K problem中文翻译:http://blog.csdn.net/21aspnet/article/details/7003275
作者:zhanhailiang 日期:2014-12-17
第一,通过配置fastcgi_param来添加服务器变量:
/usr/local/nginx/conf/fastcgi_params
fastcgi_param SERVER_FLAG test;
/usr/local/nginx/conf/nginx.conf
location ~ \.php$ {
root /usr/local/wwwroot/dokuwiki;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
第二,通过配置php-fpm.conf来添加服务器变量:
/usr/local/php/etc/php-fpm.conf
; 这里配置值"production"可以通过读取Linux环境变量来动态配置
env[SERVER_FLAG2]=production
env[SERVER_FLAG3]=$LINUX_EXPORT_VARIABLE
最后重启php-fpm,nginx:
[root@/usr/local/wwwroot/dokuwiki]# killall php-fpm;
[root@/usr/local/wwwroot/dokuwiki]# export LINUX_EXPORT_VARIABLE=test
[root@/usr/local/wwwroot/dokuwiki]# /usr/local/php/sbin/php-fpm
[root@/usr/local/nginx/conf]# /usr/local/nginx/sbin/nginx -s reload
打印$_SERVER:
{
"SERVER_FLAG": "test",
"SERVER_FLAG2": "production",
"SERVER_FLAG3": "test",
}
商品详情页(含美妆单品详情页)上报接口:
请求体:
GET http://m.vip.com/ajaxapi-addProductIdToBH.html?s=1417770095624&productId=39070878
其中,productId表示商品ID
响应体:
{
"msg": "成功",
"ret": 0
}
浏览历史列表接口
请求体:
GET http://m.vip.com/ajaxapi-queryBH.html?s=1417770095624&lsBHStr=39070878
其中,lsBHStr表示本地商品ID列表,用|分隔
响应体:直接读list字段即可;为空就展示"返回首页"
{
"list": [
{
"agio": "1.2折",
"brand_id": "292288",
"brand_name": "evona女装专场",
"detailurl": "user-history-product-292288-38988810.html",
"fav_price": "",
"market_price": "4190",
"pms_activetips": "",
"product_id": "38988810",
"product_name": "卡其啡色带帽休闲修身长袖长款羽绒服",
"ptype": "3",
"sale_out": 1,
"sell_time_from": "1418090400",
"sell_time_to": "1418486340",
"small_image": "http://pic1.vip.com/upload/merchandise/292288/EVONA-DE93341-630-30-5.jpg",
"small_image2": "http://a.vimage1.com/upload/merchandise/292288/EVONA-DE93341-630-30-5_304x384_80.jpg",
"special_price": "",
"stock": "3",
"type": "3",
"vipshop_price": "489"
}
],
"msg": "成功",
"ret": 0
}
作者:zhanhailiang 日期:2015-01-05
Robomongo是基于Shell的跨平台MongoDB管理工具。Robomongo与MongoDB之间的关系就相当于PHPMyAdmin与MySQL之间的关系。
Robomongo内置V8引擎来驱动mongo命令行工具,所以你通过mongo命令行工具的所有操作都可以通Robomongo来完成。其本身提供语法高亮,自动完成,并且支持不同的结果查询模式(文本,树,或表格),如下图:
注:可以通过按“Ctrl + Enter”只执行被选中部分查询代码。
可以在Robomongo打开多个命令行窗口。
注:可以通过按“Ctrl + T”复制命令行窗口。
Robomongo命令行可以通过编写多条查询语句来一次性获取多个查询结果集,如下图:
注:可以通过按“F10”改变结果集的展示方式,即水平和垂直方向的切换。
Robomongo支持对所有的对象和函数的自动完成功能。
注:可以通过输入函数名,然后按“Ctrl + Enter”来获取函数的具体定义,如下图:
https://github.com/billfeller/when#installation
理解Promise的概念
chemdemo/chemdemo.github.io#6
http://www.w3ctech.com/topic/721
https://promisesaplus.com/
https://www.npmjs.com/package/when
when.all与when.settle之间的区别
when.all = all; // Resolve a list of promises
when.settle = settle; // Settle a list of promises
作者:zhanhailiang 日期:2014-12-13
参考文章:
本文提供对应的PHP版本:
https://github.com/billfeller/billfeller.github.io/blob/master/code/FriendGraph.php
作者:zhanhailiang 日期:2014-12-19
Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3_8 = 4_6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。
第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符。
然后将第一个字符与0x03(00000011)进行与(&)操作并左移4位,接着第二个字符右移4位与前者相或(|),即获得第二个目标字符。
再将第二个字符与0x0f(00001111)进行与(&)操作并左移2位,接着第三个字符右移6位与前者相或(|),获得第三个目标字符。
最后将第三个字符与0x3f(00111111)进行与(&)操作即获得第四个目标字符。
在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。
剩余的字节根据编码规则继续单独转(1变2,2变3;不够的位数用0补全),再用=号补满4个字节。这就是为什么有些Base64编码会以一个或两个等号结束的原因,但等号最多只有两个。因为:
一个原字节至少会变成两个目标字节
所以余数任何情况下都只可能是0,1,2这三个数中的一个。如果余数是0的话,就表示原文字节数正好是3的倍数(最理想的情况)。如果是1的话,转成2个Base64编码字符,为了让Base64编码是4的倍数,就要补2个等号;同理,如果是2的话,就要补1个等号。
从PHP/ext/standard/base64.c中剥离出base64_encode的实现方法,代码如下:
https://github.com/billfeller/billfeller.github.io/tree/master/code/base64
[root@~/wade/git/billfeller.github.io/code/base64]# gcc -o base64 base64.c
[root@~/wade/git/billfeller.github.io/code/base64]# ./base64 "abcd*"
YWJjZCo=
[root@~/wade/git/billfeller.github.io/code/base64]# /usr/local/php/bin/php -r 'echo base64_encode("abcd*").PHP_EOL;'
YWJjZCo=
作者:zhanhailiang 日期:2014-12-27
SQLRelay 是一个持久化的数据库连接池,用来为 Unix 或者 Linux 提供数据库连接池、代理以及负载均衡的功能。
曾在2004淘宝架构迁移充当管理Oracle数据库链接的中间件,请见:
连接池示意图:
负载均衡示意图:
请见:http://sqlrelay.sourceforge.net/sqlrelay/
本文将讲解如何基于SQL Relay,使用PHP进行Mysql操作。
./configure
make && make install
./configure --with-mysql-prefix=/usr/local/mysql --with-php-prefix=/usr/local/php
make && make install
extension=sql_relay.so
[root@~]# cd /usr/local/firstworks/etc/
[root@/usr/local/firstworks/etc]# cp sqlrelay.conf.example sqlrelay.conf
其连接Mysql配置如下:
<?xml version="1.0"?>
<!DOCTYPE instances SYSTEM "sqlrelay.dtd">
<instances>
<!-- Regular SQL Relay Instance -->
<instance id="mysqlpool" port="12000" socket="/tmp/mysqlpool.socket" dbase="mysql" connections="3" maxconnections="5" maxqueuelength="0" growby="1" ttl="60" endofsession="commit" sessiontimeout="600" runasuser="nobody" runasgroup="nobody" cursors="5">
<users>
<user user="root" password="*****"/>
</users>
<connections>
<connection connectionid="mysqlpool" string="user=root;password=*****;db=test" metric="1" behindloadbalancer="no"/>
</connections>
</instance>
</instances>
sqlr-start -id mysqlpool
sqlr-start --trace -id mysqlpool // 跟踪调用详情
sqlr-stop
注:
1. 关于启动命令的使用,请见:http://sqlrelay.sourceforge.net/sqlrelay/admin/running.html
2. 安装SQL Relay后需要将firstworks/bin/目录添加到环境变量PATH中:
PATH="/usr/local/firstworks/bin/:$PATH"
启动SQL Relay后可以看到如下进程:
[root@/usr/local/firstworks/etc]# ps -ef|grep sqlrelay
nobody 26512 1 0 22:26 ? 00:00:00 sqlr-listener -id mysqlpool -config /usr/local/firstworks/etc/sqlrelay.conf
nobody 26519 1 0 22:26 ? 00:00:00 sqlr-scaler -id mysqlpool -config /usr/local/firstworks/etc/sqlrelay.conf
nobody 26520 1 0 22:26 ? 00:00:00 sqlr-connection -id mysqlpool -connectionid mysqlpool -config /usr/local/firstworks/etc/sqlrelay.conf
nobody 26521 1 0 22:26 ? 00:00:00 sqlr-connection -id mysqlpool -connectionid mysqlpool -config /usr/local/firstworks/etc/sqlrelay.conf
nobody 26522 1 0 22:26 ? 00:00:00 sqlr-connection -id mysqlpool -connectionid mysqlpool -config /usr/local/firstworks/etc/sqlrelay.conf
root 26579 18985 0 23:07 pts/3 00:00:00 grep sqlrelay
PHP测试脚本:
<?php
$con = sqlrcon_alloc('mysqlpool', 12000, '/tmp/mysqlpool.socket', 'root', '******', 0, 1);
var_dump(sqlrcon_errorNumber ($con));
var_dump(sqlrcon_dbHostName ($con));
var_dump(sqlrcon_dbIpAddress ($con));
$cur = sqlrcur_alloc($con);
sqlrcur_sendQuery($cur, 'select * from test');
var_dump(sqlrcur_totalRows ($cur));
for ($row=0; $row<sqlrcur_rowCount($cur); $row++) {
for ($col=0; $col<sqlrcur_colCount($cur); $col++) {
echo sqlrcur_getField($cur,$row,$col);
}
echo PHP_EOL;
}
sqlrcur_free($cur);
sqlrcon_free($con);
执行输出如下:
int(0)
string(9) "Localhost"
string(9) "127.0.0.1"
int(2)
1
2
未登录情况下添加购物车后跳转到登录页面,登录成功后跳回美妆单品列表页自动添加购物车:
// 自动添加购物车
var addCardProduct = {
"agio": "3.8折",
"brand_id": "319510",
"cat_id": "10501004",
"end_time": "1419782340",
"end_time_formated": "2天",
"image": null,
"img_pre_must": "MZZ-6956497900887",
"leavings": 11,
"market_price": "99",
"merchandise_sn": "6956497900887",
"num": 1,
"product_id": "41455743",
"product_name": "PF79 燕麦舒缓桑蚕丝面膜30g*5p",
"sale_count": 1246,
"sale_out": 0,
"size": 108018131,
"skuId": 108018131,
"small_image": "http://a.vimage1.com/upload/merchandise/319510/MZZ-6956497900887-14.jpg",
"small_image2": "http://a.vimage1.com/upload/merchandise/319510/MZZ-6956497900887-14_262x166_80.jpg",
"vipshop_price": "38"
};
美妆单品请求
http://m.vip.com/ajaxapi-getBeautyList.html?query=beauty-list-0-1-0-1-2-40&offset=0&limit=40
美妆单品响应体
{
"data": [
{
"agio": "3.8折",
"brand_id": "319510",
"cat_id": "10501004",
"end_time": "1419782340",
"end_time_formated": "2天",
"image": null,
"img_pre_must": "MZZ-6956497900887",
"leavings": 11,
"market_price": "99",
"merchandise_sn": "6956497900887",
"product_id": "41455743",
"product_name": "PF79 燕麦舒缓桑蚕丝面膜30g*5p",
"sale_count": 1245,
"sale_out": 0,
"size": 108018131,
"small_image": "http://a.vimage1.com/upload/merchandise/319510/MZZ-6956497900887-14.jpg",
"small_image2": "http://a.vimage1.com/upload/merchandise/319510/MZZ-6956497900887-14_262x166_80.jpg",
"vipshop_price": "38"
}
],
"msg": "成功",
"page": {
"limit": 40,
"offset": 0,
"total": 40
},
"result": true,
"warehouse": "VIP_NH"
}
作者:zhanhailiang 日期:2015-01-06
查看当前branch列表
[root@~/wade/git/billfeller.github.io]# git branch
gh-pages
* master
新建分支
[root@~/wade/git/billfeller.github.io]# git branch dev
切换分支
[root@~/wade/git/billfeller.github.io]# git checkout dev
Switched to branch 'dev'
切换到新建分支
[root@~/wade/git/billfeller.github.io]# git checkout -b dev2
Switched to a new branch 'dev2'
将提交的文件的信息添加到索引库中
[root@~/wade/git/billfeller.github.io]# git add test.log
将当前文件中所有修改的文件信息添加到索引库
[root@~/wade/git/billfeller.github.io]# git add .
将依据索引库中的内容来进行文件提交
[root@~/wade/git/billfeller.github.io]# git commit -m 'test'
[dev2 ce310ee] test
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test.log
查看commit的区别
[root@~/wade/git/billfeller.github.io]# git diff
合并其它分支到当前分支
[root@~/wade/git/billfeller.github.io]# git merge dev2
Updating d509c69..ce310ee
Fast-forward
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test.log
将branch push到远程分支
[root@~/wade/git/billfeller.github.io]# git push origin dev2
Counting objects: 4, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 260 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
To [email protected]:billfeller/billfeller.github.io.git
* [new branch] dev2 -> dev2
查看远程分支
[root@~/wade/git/billfeller.github.io]# git branch -r
origin/HEAD -> origin/master
origin/dev2
origin/master
查看本地和远程分支
[root@~/wade/git/billfeller.github.io]# git branch -a
dev
* dev2
gh-pages
master
remotes/origin/HEAD -> origin/master
remotes/origin/dev2
remotes/origin/master
修改branch名
[root@~/wade/git/billfeller.github.io]# git branch -m dev mdev
[root@~/wade/git/billfeller.github.io]# git branch -a
* dev2
gh-pages
master
mdev
remotes/origin/HEAD -> origin/master
remotes/origin/dev2
remotes/origin/master
删除远程分支
[root@~/wade/git/billfeller.github.io]# git push origin --delete dev2
To [email protected]:billfeller/billfeller.github.io.git
- [deleted] dev2
[root@~/wade/git/billfeller.github.io]# git branch -a
* dev2
gh-pages
master
mdev
remotes/origin/HEAD -> origin/master
remotes/origin/master
参考文章:
作者:zhanhailiang 日期:2015-01-21
Navicat for MySQL[是一款强大的 MySQL 数据库管理和开发工具,它为专业开发者提供了一套强大的足够尖端的工具。Navicat for MySQL 基于Windows平台,为 MySQL 量身订作,提供类似于 phpMyAdmin 的用户管理界面工具。
《MongoDB权威指南》P20
译者:zhanhailiang 日期:2015-01-21
原文链接:25 Tips for Intermediate Git Users
丢弃暂存区的所有操作:
$ git stash
# Do something...
$ git stash pop
$ git add -i
staged unstaged path
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now>
略.
查看最近提交的操作日志:
$ git log -p
只查看最近修改的文件列表:
$ git log --stat
查询指定作者的更新日志:
$ git log --author=Andy
通过搜索提交的注释关键字过滤日志:
$ git log --grep="Something in the message"
查询指定文件的修改日志:
$ git log lib/foo.rb
查看分支feature/132与分支feature/145,其各自与master分支的区别:
$ git log feature/132 feature/145 ^master
也可以查询指定时间段内(该时间格式支持ActiveSupport style)的操作日志:
$ git log --since=2.months.ago --until=1.day.ago
$ git show 12a86bc38 # By revision
$ git show v1.0.1 # By tag
$ git show feature132 # By branch name
$ git show 12a86bc38^ # Parent of a commit
$ git show 12a86bc38~2 # Grandparent of a commit
$ git show feature132@{yesterday} # Time relative
$ git show feature132@{2.hours.ago} # Time relative
查看本地仓库未推送的修改日志:
$ git log origin/master..new
# [old]..[new] - everything you haven't pushed yet
直接回滚到本地仓库最近的版本:(若你的修改未提交过)
$ git reset HEAD lib/foo.rb
回滚到本地仓库最近的版本:(若你的修改提交过)
如果你要回滚到最后一次提交之前的版本:
$ git commit --amend
如果你要回滚前已经提交多次代码:
$ git checkout feature132
$ git reset --hard HEAD~2
master提交了三次修改,现在希望将最近三次修改移动分支experimental,并取消master分支最近三次的修改:
$ git branch experimental # Creates a pointer to the current master state
$ git reset --hard master~3 # Moves the master branch pointer back to 3 revisions ago
$ git checkout experimental
略.
略.
$ git reflog
$ git log -g # Same as above, but shows in 'log' format
$ # Generate a changelog of Release 132
$ git shortlog release/132 ^release/131
$ # Tag this as v1.0.1
$ git tag v1.0.1 release/132
$ git blame FILE
略.
$ git branch experimental SHA1_OF_HASH
功能开发过程发现从细节上看,很多细节不够细腻:
优化目标:快速迭代,小步快跑;
缺乏后端数据层的支持;目前读取浏览历史列表时是通过遍历商品ID调用商品详情接口来获取相关商品信息,上限需要发20次HTTP请求才能完成调用;
优化目标:是否考虑在需求评审阶段就拉上后端团队共同完成评审和方案评估;
尝试Redis集成Lua方案,实现添加浏览历史记录功能;但是包括开发阶段发现的慢查询日志和DBA的建议,都否定掉使用该方案,其中原因如下:
前后端开发分离,包括异步上报浏览历史,异步读取浏览历史,对性能和体验都做了比较好的考虑;但是也间接增加了协作沟通的成本;
浏览历史是第一个尝试测试团队的性能测试方案的项目,从出发点来说,其实是很好的点,但在实际操作时遇到了很多问题(第一次,难免有点紧张):
性能测试标准不明确;产品提出性能测试需求时不知道是要做什么,包括实施性能测试需要实现模拟用户行为,如登录,选择分仓,浏览商品行为,到最终上报商品ID性能测试和浏览历史查询性能测试,其中涉及m域,mlogin域大量的业务逻辑,需要大量时间协助测试人员完成业务逻辑模拟实现;
优化目标:明确性能测试方案标准和各项指标。
因为配置WAP_REDIS_HOST,WAP_REDIS_PORT环境变量需要全域重启php-fpm,nginx,运维认为风险很高(特别是年终时期),所以暂时改成通过后台网站配置来实现配置。目前网站配置有很多人有操作权限(包括产品开发测试等),不能避免人为的失误操作。
优化目标:如果不可避免的情况下需要通过后台来实现配置,需要管理后台支持更细粒度的权限控制——比如针对不同的配置项支持不同权限级的配置,理想情况下,实现对不同角色的每个操作实现权限控制;
请求体:
http://m.vip.com/ajaxapi-bindCoupon.html?fCouponId=12082
其中,fCouponId参数通过data-fCouponId获取;
响应体:
{
"ret": 0,
"data": {
"coupon_id": 12082,
"coupon_name": "下载APP新会员专享券100-10",
"coupon_sn": "KXR9KDTRXK66QQE",
"begin_time": 1420771486,
"end_time": 1421030686,
"use_limit": "100",
"coupon_type": 2,
"coupon_field": 5,
"coupon_source": "站内活动页面领取",
"limit": 800000,
"active": 104,
"rest": 799896
}
}
其中:
ret 0 领券成功
-1 活动已过期
-2 用户未登录
-3 非新客用户AB
-4 已领券
-5 前端参数有误
-6 接口异常
-97 已领券
-98 券已领完
-99 接口异常
作者:zhanhailiang 日期:2015-01-23
本地环境:
系统版本:Microsoft Windows 6.1.7601
PHP版本:PHP 5.3.29
php_curl.dll扩展版本:7.35.0
Windows环境下遇到一个很奇怪的问题,使用PHP curl发送请求报错:
错误码:56
错误信息:Problem (2) in the Chunked-Encoded data
但是使用浏览器直接访问又正常,怀疑是php_curl.dll扩展本身的bug,解决方案如下:
在PHP curl头部添加HTTP版本信息即可解决:
curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
即可修复该问题。
作者:zhanhailiang 日期:2015-01-01
MySQL Native Driver简称mysqlnd,作为libmysqlclient替代品于PHP5.3.0版本引入。之前,MySQL数据库扩展mysql,mysqli,PDO MYSQL都是通过libmysqlclient实现与MySQL Server的通信。引入mysqlnd,这三个扩展都可以通过mysqlnd实现与MySQL Server的通信。
其较libmysqlclient的通信原理对比如下图:
./configure --prefix=/usr/local/php-5.3.29-production --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-openssl --with-pdo-mysql=mysqlnd --enable-fpm --enable-mysqlnd
make && make install
[root@/usr/local]# /usr/local/php-5.3.29-production/bin/php -ini|grep mysqlnd
Configure Command => './configure' '--prefix=/usr/local/php-5.3.29-production' '--with-pear' '--with-iconv=/usr/local/' '--with-mysql=mysqlnd' '--with-mysqli=mysqlnd' '--with-openssl' '--with-libxml-dir' '--with-curl' '--with-pdo-mysql=mysqlnd' '--disable-fileinfo' '--enable-fpm' '--enable-mysqlnd' '--with-mcrypt' '--enable-mbstring'
Client API version => mysqlnd 5.0.8-dev - 20102224 - $Id: 731e5b87ba42146a687c29995d2dfd8b4e40b325 $
Client API library version => mysqlnd 5.0.8-dev - 20102224 - $Id: 731e5b87ba42146a687c29995d2dfd8b4e40b325 $
mysqlnd
mysqlnd => enabled
Version => mysqlnd 5.0.8-dev - 20102224 - $Id: 731e5b87ba42146a687c29995d2dfd8b4e40b325 $
Client API version => mysqlnd 5.0.8-dev - 20102224 - $Id: 731e5b87ba42146a687c29995d2dfd8b4e40b325 $
译者:zhanhailiang 日期:2015-01-17
原文链接:25 Tips for Intermediate Git Users
$ git config --global user.name "Some One"
$ git config --global user.email "[email protected]"
git中的一切都以文件形式存储,举例:
在git中查看合并提交信息,你将看到Two Parents,其中第一个Parent指向当前分支,第二个Parent指向你想合并的分支。
和svn一样,当遇到合并冲突,需要手动修改<<<<, ====, >>>>部分的内容。
$ git diff --merge
diff --cc dummy.rb
index 5175dde,0c65895..4a00477
--- a/dummy.rb
+++ b/dummy.rb
@@@ -1,5 -1,5 +1,5 @@@
class MyFoo
def say
- puts "Bonjour"
- puts "Hello world"
++ puts "Annyong Haseyo"
end
end
git中最重要的特性之一是可以支持分布式仓库,从而避免SVN中心式的弊端。你可以在本地汪厍多个读远程服务器,也可以添加多个写远程服务器。
$ git remote add john [email protected]:johnsomeone/someproject.git
如果想获取远程服务器信息,如下:
# shows URLs of each remote server
$ git remote -v
# gives more details about each
$ git remote show name
也可以通过以下命令获取本地分支和远程分支的区别:
$ git diff master..john/master
也可以查看本地HEAD的修改:
$ git log remote/branch..
# Note: no final refspec after ..
git支持两种类型的标签:
一个指向某个提交的指针;
$ git tag to-be-tested
一个指向标签对象的指针,其包含自身信息和历史。
$ git tag -a v1.1.0 # Prompts for a tag message
$ git branch feature132
$ git checkout feature132
等价于:
$ git checkout -b feature132
$ git checkout master
$ git merge feature83 # Or...
$ git rebase feature83
合并分支分为merge和rebase两种方式:
可以通过以下命令查看哪些分支包含独立的修改:
# Shows branches that are all merged in to your current branch
$ git branch --merged
# Shows branches that are not merged in to your current branch
$ git branch --no-merged
提交本地当前分支修改到远程服务器:
$ git push origin twitter-experiment:refs/heads/twitter-experiment
# Where origin is our server name and twitter-experiment is the branch
删除远程服务器的分支:
$ git push origin :twitter-experiment
查看所有远程分支的信息:
$ git remote show origin
待续......
环境配置:
系统:CentOS release 5.8 (Final)
CPU:8核 Intel(R) Xeon(R) CPU E5-2430 0 @ 2.20GHz
内存:32GB
网卡:1000 Mbps
C:\Program Files (x86)\Apache Software Foundation\Apache2.2\bin>ab.exe -n 1000 -
c 10 -C "WAP[revision]=touch" -C "WAP[hd]=1" -C "WAP_product_preheating_referer=
http%3A%2F%2Fm.vip.com%2Fpreheating-brand-301810-0-0-0-0-0-1-40.html" -C "m_vipr
uid=58788556" -C "WAP_preheat_brand_return_url=a%3A0%3A%7B%7D" -C "WAP%5BremindS
how%5D=1" -C "m_vip_province=104104" -C "WAP[p_area]=%25E5%25B9%25BF%25E4%25B8%2
59C" -C "WAP[p_wh]=VIP_NH" -C "WAP[hide_wh_tip]=1" -C "time_offset=3" -C "wap_so
urce=wap" -C "warehouse=VIP_NH" -C "WAP_cart_history=1" -C "WAP_ID=9ff2476288ee0
4fcbffe2785f51b603b3b5ebdbe" -C "m_new_index=1" -C "WAP[show]=1" -C "WAP[brd_lst
_addtocart]=308297" -C "WAP_brand_return_url=a%3A5%3A%7Bi%3A0%3Bs%3A69%3A%22http
%3A%2F%2Fweibo.com%2Fbillfeller%2Fprofile%3Frightmod%3D1%26wvr%3D6%26mod%3Dperso
nnumber%22%3Bi%3A1%3Bs%3A27%3A%22http%3A%2F%2Fm.vip.com%2Findex.html%22%3Bi%3A2%
3Bs%3A17%3A%22http%3A%2F%2Fm.vip.com%2F%22%3Bi%3A3%3Bs%3A100%3A%22http%3A%2F%2Fm
.vip.com%2Findex.php%3Fm%3Dspecial%26p%3D%2Fte%2Fpermanent%2Fs8900_nh_index.php%
26h%3Dmzt.vip.com%26wapid%3Dmzt_8900%22%3Bi%3A4%3Bs%3A17%3A%22http%3A%2F%2Fm.vip
.com%2F%22%3B%7D" -C "WAP[back_act]=%2Fproduct-308297-40225817.html" -C "WAP_rec
_product_id=40225817" -C "WAP_rec_brand_id=308297" -C "WAP_referer_url=http%3A%2
F%2Fm.vip.com%2Fbrand-308297-0-0-0-1-0-1-20.html" -C "mars_pid=116" -C "mars_cid
=1418638667918_e0a48b526d042c1c682e5c440b10d3b0" -C "mars_sid=6ec2bbb831359468f4
64ba2ae0a63d39" -C "visit_id=4C43ACFB3D5E82D9D4552BB098E43692" -C "WAP_u_new=new
" -C "m_vipruid=58788556" -C "wap_consumer=C12" "http://m.vip.com/ajaxapi-addPro
ductIdToBH.html?s=1418696408150&productId=40225817"
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking m.vip.com (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.2.4
Server Hostname: m.vip.com
Server Port: 80
Document Path: /ajaxapi-addProductIdToBH.html?s=1418696408150&productId
=40225817
Document Length: 40 bytes
Concurrency Level: 10
Time taken for tests: 29.207 seconds
Complete requests: 1000
Failed requests: 2
(Connect: 0, Receive: 0, Length: 2, Exceptions: 0)
Write errors: 0
Non-2xx responses: 2
Total transferred: 985882 bytes
HTML transferred: 40240 bytes
Requests per second: 34.24 [#/sec] (mean)
Time per request: 292.071 [ms] (mean)
Time per request: 29.207 [ms] (mean, across all concurrent requests)
Transfer rate: 32.96 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 2.8 0 31
Processing: 63 279 673.3 118 8996
Waiting: 63 273 673.5 114 8996
Total: 63 280 673.3 118 8996
Percentage of the requests served within a certain time (ms)
50% 118
66% 132
75% 140
80% 146
90% 168
95% 2098
98% 2139
99% 3109
100% 8996 (longest request)
其中,各个参数表示:
作者:zhanhailiang 日期:2014-12-31
MySQL Proxy是介于MySQL Client端和MySQL Server端之间的中间件,可以监测、分析或改变它们的通信。由于其MySQL Proxy实现MySQL C/S通信协议,所以其对应用是透明,即应用把MySQL Proxy当成MySQL Server,只需要将原先直连的MySQL host:port修改成MySQL Proxy host:port即可;
其主要应用场景:
接下来介绍如何安装与使用MySQL Proxy。
下载源码包,获取Lua测试脚本
wget http://cdn.mysql.com/Downloads/MySQL-Proxy/mysql-proxy-0.8.5.tar.gz
tar zxvf mysql-proxy-0.8.5.tar.gz
下载二进制包,安装
wget http://cdn.mysql.com/Downloads/MySQL-Proxy/mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit.tar.gz
tar zxvf mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit.tar.gz
mv mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit /usr/local/
cd /usr/local/
ln -s mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit mysql-proxy
添加环境变量到~/.bashrc
PATH=/usr/local/mysql-proxy/bin:$PATH
创建MySQL Proxy配置文件 /usr/local/mysql-proxy/etc/master.conf, 注意将master.conf文件权限修改成0660
[mysql-proxy]
log-file = /var/log/mysql-proxy.log
log-level = message
proxy-backend-addresses = 127.0.0.1:3306
启动Mysql Proxy,添加--daemon将以守护进程方式运行,默认MySQL Proxy监听4040端口:
mysql-proxy --defaults-file=/usr/local/mysql-proxy/etc/master.conf --proxy-lua-script=/root/software/mysql-proxy-0.8.5/examples/tutorial-query-time.lua
通过MySQL客户端直连MySQL Proxy即可:
[root@~/software/mysql-proxy-0.8.5/examples]# /usr/local/mysql/bin/mysql --host=127.0.0.1 --port=4040 -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 65
Server version: 5.5.39-log MySQL Community Server (GPL)
Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
测试Lua脚本,测试脚本test.php如下:
$db = mysql_connect('127.0.0.1:4040', 'root', '******');
if (!$db) {
exit(-1);
}
mysql_select_db('test', $db);
$result = mysql_query('SELECT * FROM test.test', $db);
while ($row = mysql_fetch_assoc($result)) {
var_dump($row);
}
执行test.php:php test.php,其输出如下:
array(1) {
["id"]=>
string(1) "1"
}
array(1) {
["id"]=>
string(1) "2"
}
查看MySQL Proxy日志如下:
[root@/usr/local]# mysql-proxy --defaults-file=/usr/local/mysql-proxy/etc/master.conf --proxy-lua-script=/root/software/mysql-proxy-0.8.5/examples/tutorial-query-time.lua
we got a normal query: SELECT * FROM test.test
query-time: 0.3ms
response-time: 0.31ms
作者:zhanhailiang 日期:2014-12-17
默认 vim 的查找是区分大小写,可通过以下两种方式实现忽略大小写查找
set ic?
noignorecase
1 指令设定:
:set ic(ignorecase 的缩写) 忽略大小写
:set noic(noignorecase 的缩写) 不忽略大小写
输入以上指令, 此后每次查找都是按当前配查找,如果想一直有效,可以将其写入配置文件.vimrc
set ic
2 查找符号设定:
/\CREDIS_HOST 区分大小写的查找
/\credis_host 不区分大小写的查找
这个操作只针对当前的查找有效
作者:zhanhailiang 日期:2015-01-08
今天,测试发现在
https://mlogin.vip.com/user-login.html?back_act=http%3A%2F%2Fm.vip.com%2Fuser.html
下上报监控数据
http://mstats.vip.com/v1/timing/m?_t=1420647129290&p2=240&p4=377&t0=0&t1=63&t2=474&t3=642&t4=1&t6=411&t7=919&t8=3&t9=1059
老是报412:
GET http://mstats.vip.com/v1/timing/m?_t=1420647129290&p2=240&p4=377&t0=0&t1=63&t2=474&t3=642&t4=1&t6=411&t7=919&t8=3&t9=1059 412 (Precondition Failed)
看了监控平台的代码,返回状态码412是因为监控平台需要通过Referer头部来判断平台,但是该次请求却无Referer头部:
GET /v1/timing/m?_t=1420647129290&p2=240&p4=377&t0=0&t1=63&t2=474&t3=642&t4=1&t6=411&t7=919&t8=3&t9=1059 HTTP/1.1
Host: mstats.vip.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
DNT: 1
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Cookie: m_vip_province=104104; WAP[p_wh]=VIP_NH; warehouse=VIP_NH; wap_A1_sign=1; wap_consumer=A1; mars_pid=105; mars_cid=1420628456366_8d67e997a179843a61b1d3151d6bb9db; mars_sid=a4148eed668a36b75d29c288580f7099; visit_id=628ED24779611F6233FA107A22B83450
确实请求头没有Referer头部,原来是因为HTTP协议规定:
Clients SHOULD NOT include a Referer header field in a (non-secure) HTTP request if the referring page was transferred with a secure protocol.
参考文章:
系统
# uname -a # 查看内核/操作系统/CPU信息
# head -n 1 /etc/issue # 查看操作系统版本
# cat /proc/cpuinfo # 查看CPU信息
# hostname # 查看计算机名
# lspci -tv # 列出所有PCI设备
# lsusb -tv # 列出所有USB设备
# lsmod # 列出加载的内核模块
# env # 查看环境变量
资源
# free -m # 查看内存使用量和交换区使用量
# df -h # 查看各分区使用情况
# du -sh <目录名> # 查看指定目录的大小
# grep MemTotal /proc/meminfo # 查看内存总量
# grep MemFree /proc/meminfo # 查看空闲内存量
# uptime # 查看系统运行时间、用户数、负载
# cat /proc/loadavg # 查看系统负载
磁盘和分区
# mount | column -t # 查看挂接的分区状态
# fdisk -l # 查看所有分区
# swapon -s # 查看所有交换分区
# hdparm -i /dev/hda # 查看磁盘参数(仅适用于IDE设备)
# dmesg | grep IDE # 查看启动时IDE设备检测状况
网络
# ifconfig # 查看所有网络接口的属性
# iptables -L # 查看防火墙设置
# route -n # 查看路由表
# netstat -lntp # 查看所有监听端口
# netstat -antp # 查看所有已经建立的连接
# netstat -s # 查看网络统计信息
进程
# ps -ef # 查看所有进程
# top # 实时显示进程状态
用户
# w # 查看活动用户
# id <用户名> # 查看指定用户信息
# last # 查看用户登录日志
# cut -d: -f1 /etc/passwd # 查看系统所有用户
# cut -d: -f1 /etc/group # 查看系统所有组
# crontab -l # 查看当前用户的计划任务
服务
# chkconfig --list # 列出所有系统服务
# chkconfig --list | grep on # 列出所有启动的系统服务
程序
# rpm -qa # 查看所有安装的软件包
其他常用命令整理如下:
查看主板的序列号:dmidecode | grep -i 'serial number'
用硬件检测程序kuduz探测新硬件:service kudzu start ( or restart)
查看CPU信息:
cat /proc/cpuinfo
dmesg | grep -i 'cpu'
dmidecode -t processor
查看内存信息:
cat /proc/meminfo
free -m
vmstat
查看板卡信息:cat /proc/pci
查看显卡/声卡信息:
lspci |grep -i 'VGA'
dmesg | grep -i 'VGA'
查看网卡信息:
dmesg | grep -i 'eth'
cat /etc/sysconfig/hwconf | grep -i eth
lspci | grep -i 'eth'
查看PCI信息:lspci (相比cat /proc/pci更直观)
查看USB设备:cat /proc/bus/usb/devices
查看键盘和鼠标:cat /proc/bus/input/devices
查看系统硬盘信息和使用情况:fdisk & disk – l & df
查看各设备的中断请求(IRQ):cat /proc/interrupts
查看系统体系结构:uname -a
查看及启动系统的32位或64位内核模式:
isalist –v
isainfo –v
isainfo –b
查看硬件信息,包括bios、cpu、内存等信息:dmidecode
测定当前的显示器刷新频率:/usr/sbin/ffbconfig –rev \?
查看系统配置:/usr/platform/sun4u/sbin/prtdiag –v
查看当前系统中已经应用的补丁:showrev –p
显示当前的运行级别:who –rH
查看当前的bind版本信息:nslookup –class=chaos –q=txt version.bind
查看硬件信息:dmesg | more
显示外设信息, 如usb,网卡等信息:lspci
查看已加载的驱动:
lsnod
lshw
查看当前处理器的类型和速度(主频):psrinfo -v
打印当前的OBP版本号:prtconf -v
查看硬盘物理信息(vendor, RPM, Capacity):iostat –E
查看磁盘的几何参数和分区信息:prtvtoc /dev/rdsk/c0t0d0s
显示已经使用和未使用的i-node数目:
df –F ufs –o i
isalist –v
对于“/proc”中文件可使用文件查看命令浏览其内容,文件中包含系统特定信息:
主机CPU信息:Cpuinfo
主机DMA通道信息:Dma
文件系统信息:Filesystems
主机中断信息:Interrupts
主机I/O端口号信息:Ioprots
主机内存信息:Meninfo
Linux内存版本信息:Version
备注: proc – process information pseudo-filesystem 进程信息伪装文件系统
作者:zhanhailiang 日期:2015-01-24
一个有限状态机是一个设备,或是一个设备模型,具有有限数量的状态,它可以在任何给定的时间根据输入进行操作,使其从一个状态变换到另一个状态,或者是促使一个输出或者一种行为的发生。一个有限状态机在任何瞬间只能处在一个状态。
即有限状态机背后的概念是要把一个对象的行为分解成为易于处理的“块”或状态。典型的例子,墙上的灯是一个非常简单的有限状态机,它有两种状态:开或关。状态之间的变换是通过你手指的输入产生的。向上按开关,产生从开到关的状态变换,向下按开关,产生从开到关的状态变换。
关闭状态:没有相应的输出或行动(除非考虑灯泡不亮也是一种行动);
开启状态:允许电流流过开关并通过灯泡丝点亮你的房间。
使用switch语句来表达状态的代码如下:
switch ($state) {
case STATE_RUNAWAY : // 逃跑状态
// 躲避敌人
// 若安全,进入巡逻状态
break;
case STATE_PATROL : // 巡逻状态
// 巡逻
// 若遇到比自己强的敌人,进入逃跑状态
// 若遇到比自己弱的敌人,进入攻击状态
break;
case STATE_ATTACK : // 攻击状态
// 若攻击比自己强的敌人,进入逃跑状态
// 否则取其首级
break;
// etc...
}
使用switch实现的有限状态机,随着更多的状态和条件的加入,将导致代码流程象意大利面条一样难以理解并且产生调试恶梦。
接下来使用状态变换表表示以上示例状态变换关系
当前状态 | 条件 | 状态变换 |
---|---|---|
逃跑 | 安全 | 巡逻 |
攻击 | 比故人弱 | 逃跑 |
巡逻 | 受到威胁并比敌人强 | 攻击 |
巡逻 | 受到威胁并比敌人弱 | 逃跑 |
接下来使用状态设计模式实现以上的有限状态机。它提供了一种优雅的方式来实现状态驱动行为。
请见:
<?php
// vim: set expandtab cindent tabstop=4 shiftwidth=4 fdm=marker:
/**
* @file RunnerTest.php
* @version 1.0
* @author wade
* @date 2015-01-24 19:57:53
*/
/**
* 有限状态机实现demo
*/
interface State {
public function execute(Troll $troll);
}
class Troll {
private $uid;
private $_curState = NULL;
public function __construct($uid) {
$this->uid = $uid;
}
public function Update() {
if ($this->_curState instanceof State) {
$this->_curState->execute($this);
}
}
public function changeState(State $state) {
$this->_curState = $state;
}
public function isPatrolState() {
return TRUE;
}
public function patrol() {
echo sprintf("%d is patroling!\n", $this->uid);
}
public function isAttackState() {
return TRUE;
}
public function attack() {
echo sprintf("%d is attacking!\n", $this->uid);
}
public function isRunawayState() {
return TRUE;
}
public function runaway() {
echo sprintf("%d is running away!\n", $this->uid);
}
}
class PatrolState implements State {
public function execute(Troll $troll) {
if ($troll->isPatrolState()) {
$troll->patrol();
} else {
// todo
}
}
}
class AttackState implements State {
public function execute(Troll $troll) {
if ($troll->isAttackState()) {
$troll->attack();
} else {
// todo
}
}
}
class RunawayState implements State {
public function execute(Troll $troll) {
if ($troll->isRunawayState()) {
$troll->runaway();
} else {
// todo
}
}
}
$uid = 10001;
$troll = new Troll($uid);
$PatrolState = new PatrolState();
$troll->changeState($PatrolState);
$troll->Update();
$AttackState = new AttackState();
$troll->changeState($AttackState);
$troll->Update();
$RunawayState = new RunawayState();
$troll->changeState($RunawayState);
$troll->Update();
查看输出如下:
[root@~/wade/git/billfeller.github.io/code]# /usr/local/php/bin/php RunnerTest.php
10001 is patroling!
10001 is attacking!
10001 is running away!
https://github.com/Qihoo360/phptrace
phptrace.dotrace => 0 => 0
phptrace.enabled => 1 => 1
phptrace.logdir => no value => no value
phptrace.logsize => 52428800 => 52428800
请求体:
GET http://m.vip.com/ajaxapi-queryAdList.html?s=1418038239498&zoneId=75&f=channel
其中,
zoneId参数通过$('#wrapper_banner').data('zoneid');读取;
f参数通过$('#wrapper_banner').data('f');读取;
响应体:判断list即可;
{
"list": [
{
"url": "product-292734-39355252.html"
}
],
"msg": "成功",
"ret": 0
}
作者:zhanhailiang 日期:2014-12-14
Alt+Enter 全屏切换
Ctrl+Inset 复制
Shift+Insert 粘贴
Alt+Insert 粘贴所选择的文本
请求体:
GET ajaxapi-getPreheatingProducts.html?query=308698-0-0-0-1-0-2-40&offset=40&limit=40
其中,
query参数通过location.href截断preheating-brand-(.*?).html获取即可;
offset参数,略;
limit参数,略;
响应体:
{
"data": [
{
"agio": "7.1折",
"brand_id": "308698",
"cat_id": "10501012",
"fav_price": "",
"icons": [],
"is_warmup": "1",
"m_mobile_show": "0",
"market_price": "3627",
"max": -1,
"min": -1,
"product_id": "39885370",
"product_name": "精研祛斑大礼盒",
"ptype": -1,
"sale_out": "0",
"saled": -1,
"sequence": "43",
"small_image": "http://sp.vip.com/upload/merchandise/259398/sk2-2014091907-5.jpg",
"small_image2": "http://a.vimage1.com/upload/merchandise/259398/sk2-2014091907-5_304x384_80.jpg",
"special_price": "",
"standard": "0",
"stock": -1,
"vipshop_price": "2580"
},
...
],
"msg": "成功",
"page": {
"limit": 40,
"offset": 40,
"total": 24
},
"result": true
}
作者:zhanhailiang 日期:2015-01-06
使用TortoiseGit Push时每次都需要输入用户名密码,如图:
machine gitlab.tools.vipshop.com
login wade.zhan
password ******
参考文章:
http://zipperary.com/2013/05/26/ssh-errors-with-github/
如果你熟悉mongodb操作,native mongodb driver比较适合你;
如果你以前玩过ORM,ibatis,hernate,JPI,那么弄弄mongoose可能比较容易上手;
当然如果你要深入node对mongodb的操作,建议你看看How to wire BSON protocol 之类的文档;
https://cnodejs.org/topic/54afdd42ce87bace2444ce7d
http://segmentfault.com/q/1010000002403717
mongoosejs getting started:http://mongoosejs.com/
作者:zhanhailiang 日期:2014-12-11
本文主要介绍常见的数据存储方案及相应选型的评估标准的介绍。
Guideline:针对不同应用场景,针对性选择存储方式。
SQL:
MySQL 5.5/5.6/MariaDB(对于Dev绝大多数场景下透明);
Oracle|MS SQL暂不考虑;
NoSQL:
Memcached 1.4.21;
Redis 2.8;
MongoDB 2.6.6;
Hbase 0.96/0.98;
#2. 评估标准
RDBMS:(MySQL):
典型场景:
以电商网站为例,
所有后端子系统(比如ERP,物流,财务,仓储,人事,VIS等);
网站核心数据存储(比如用户,商品,库存,购物车,订单);
KV(Memcache/Redis):
典型场景:
各类计数器;
各类cache层(商品列表页,各类配置信息,商品描述信息等);
Analytics Platform:
Hadoop:ETL;科学分析;
GP:BI分析;各类报表;
Hbase:在线系统;OLAP分析;
DocDB:应用相对简单,数据结构相对复杂,支持快速开发,非事务类处理的信息处理系统。如知识问答、社区等;
#3. 性能优化
已有系统碰到性能瓶颈时,优化次序依次为:
尝试使用github.com issues工具写博客,挺爽的!
对应github.com链接:#4
作者:zhanhailiang 日期:2014-12-21
SETBIT key offset value
对key所储存的字符串值,设置或清除指定偏移量上的位(bit)。
位的设置或清除取决于value参数,可以是0也可以是1。
当key不存在时,自动生成一个新的字符串值。
字符串会进行伸展(grown)以确保它可以将value保存在指定的偏移量上。
当字符串值进行伸展时,空白位置以0填充。
offset参数必须大于或等于0,小于2^32(bit映射被限制在512MB之内)。
返回值: 指定偏移量原来储存的位。
Warning: 对使用大的offset的SETBIT操作来说,内存分配可能造成Redis服务器被阻塞。
Warning: 当生成一个很长的字符串时,Redis 需要分配内存空间,该操作有时候可能会
造成服务器阻塞(block)。在2010年的Macbook Pro上,设置偏移量为536870911(512MB内
存分配),耗费约300毫秒,设置偏移量为134217728(128MB内存分配),耗费约80毫秒,
设置偏移量33554432(32MB内存分配),耗费约30毫秒,设置偏移量为8388608(8MB内存分配),
耗费约8毫秒。GETBIT key offset
对key 所储存的字符串值,获取指定偏移量上的位(bit)。
当offset比字符串值的长度大,或者key不存在时,返回0。
返回值:字符串值指定偏移量上的位(bit)。
在很多业务场景中,我们都需要针对很多功能实现配置,比如以下场景:
https://github.com/billfeller/billfeller.github.io/blob/master/code/IBit.php
作者:zhanhailiang 日期:2015-01-05
LivePool 是一个基于 NodeJS,类似 Fiddler 支持抓包和本地替换的 Web 开发调试工具,是 Tencent AlloyTeam 在开发实践过程总结出的一套的便捷的 WorkFlow 以及调试方案。
D:\Users\wade.zhan>npm install livepool -g
D:\Users\wade.zhan>livepool
=========================================
livepool is running, port: 8090
liveapp ui is ready, port: 8002
connect:t5k2_rmpy1DZIMReAAAA
disconnect:t5k2_rmpy1DZIMReAAAA
connect:DqzEMagEAF5bxCcoAAAB
[https connect error]: accounts.google.com:443
[https connect error]: accounts.google.com:443
disconnect:DqzEMagEAF5bxCcoAAAB
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.