Redis内存分析方法
一般会采用 bgsave 生成 dump.rdb 文件,再结合 redis-rdb-tools 和 sqlite 来进行静态分析。
BGSAVE:在后台异步(Asynchronously)保存当前数据库的数据到磁盘。
BGSAVE 命令执行之后立即返回 OK
,然后 Redis fork 出一个新子进程,原来的 Redis 进程(父进程)继续处理客户端请求,而子进程则负责将数据保存到磁盘,然后退出。
生成内存快照:redis-rdb-tools 是一个 python 的解析 rdb 文件的工具,在分析内存的时候,主要用它生成内存快照。
redis-rdb-tools 安装:
使用 PYPI 安装:
pip install rdbtools
使用 源码安装:
git clone https://github.com/sripathikrishnan/redis-rdb-tools cd redis-rdb-tools sudo python setup.py install
使用 redis-rdb-tools 生成内存快照:
rdb -c memory dump.rdb > memory.csv
生成 CSV 格式的内存报告。包含的列有:数据库 ID,数据类型,key,内存使用量(byte),编码。内存使用量包含 key、value 和其他值。
内存使用量是理论上的近似值,在一般情况下,略低于实际值。
[ares:~/Desktop$head memory.csv database,type,key,size_in_bytes,encoding,num_elements,len_largest_element 0,string,trade.coupon.id:653601465,112,string,8,8 0,string,trade.coupon.id:631354838,112,string,8,8 0,string,trade.coupon.id:632477800,112,string,8,8 0,string,trade.coupon.id:620802294,112,string,8,8 0,string,trade.coupon.id:631432959,112,string,8,8 0,string,trade.coupon.id:632933399,112,string,8,8 0,string,trade.coupon.id:632117725,112,string,8,8 0,string,trade.coupon.id:634240609,112,string,8,8 0,string,trade.coupon.id:646317603,112,string,8,8
注:若csv文件不大,可直接用相关软件打开,以size_in_bytes列排序,可以看到大致内存使用。
使用SQLite分析内存快照:
SQLite版本必须是3.16.0以上。
导入memory.csv数据库:
$sqlite3 memory.db SQLite version 3.19.3 2017-06-27 16:48:08 Enter ".help" for usage hints. sqlite> create table memory(database int,type varchar(128),key varchar(128),size_in_bytes int,encoding varchar(128),num_elements int,len_largest_element varchar(128)); sqlite> .mode csv memory sqlite> .import memory.csv memory 数据导入后,可以随处理:
查询key总数:
sqlite> select count(*) from memory; 31143847
查询key总占用内存:
sqlite> select sum(size_in_bytes) from memory; 17391950414.0
查询内容占用最高的几个key:
sqlite> select key,size_in_bytes from memory order by size_in_bytes desc limit 10; key,size_in_bytes public.xx.xx:xx,7860169636 public.xx.xx:xx,3043206524 public.xx.xx:xx,1866022916 public.xx.xx:xx,420931316 public.xx.xx:idxx171118172 xx,162984940 xx,133443892 public.xx.xx:xx,80925132 public.xx.xx:xx,28340356
PHP生成随机红包高级方法
/** 传输数字必须为正整数,需要小数通过$bonus_float传值进行换算
* @param $bonus_total (必填) 红包总额
* @param $bonus_count (必填) 红包个数
* @param $bonus_max (选填) 每个小红包的最大额 最大值要大于平均值
* @param $bonus_min (选填) 每个小红包的最小额
* @param $bonus_float (选填 Y元J角F分) 红包传入单位
* @return 存放生成的每个小红包的值的一维数组
*/
function getBonus($bonus_total, $bonus_count=20, $bonus_max=0, $bonus_min=1, $bonus_float='Y') {
$total_money = 0;
$arr1 = array();
$arr2 = array();
$res = array();
// 转换传入金额单位 Y元 J角 F分
$tmp_float = $bonus_float;
if($bonus_float=='Y'){ $bonus_float = 1; $num_fmt = 0;}
if($bonus_float=='J'){ $bonus_float = 10; $num_fmt = 1;}
if($bonus_float=='F'){ $bonus_float = 100; $num_fmt = 2;}
// 每人红包平均值
$average = $bonus_total / $bonus_count;
// 防止传入参数越界
if($average > $bonus_max){ echo $bonus_max = round(($bonus_total-$average)/$bonus_count,0)+round($average,0); }
if($average < $bonus_min){ echo $bonus_min = 1; }
$range1 = ($average - $bonus_min)*($average - $bonus_min);
$range2 = ($bonus_max - $average)*($bonus_max - $average);
// 生成随机红包逻辑
for ( $i = 0; $i < $bonus_count; $i++) { if (rand($bonus_min, $bonus_max) > $average) {
$temp = $bonus_min + intval(sqrt(rand(0, (intval($range1)-1))));
$arr1[$i] = $temp;
$bonus_total -= $temp;
} else {
$temp = $bonus_max - intval(sqrt(rand(0, (intval($range2)-1))));
$arr1[$i] = $temp;
$bonus_total -= $temp;
}
}
while ($bonus_total > 0) {
for ($i = 0; $i < $bonus_count; $i++) { if ($bonus_total > 0 && $arr1[$i] < $bonus_max) {
$arr1[$i]++;
$bonus_total--;
}
}
}
while ($bonus_total < 0) {
for ($i = 0; $i < $bonus_count; $i++) {
if ($bonus_total < 0 && $arr1[$i] > $bonus_min) {
$arr1[$i]--;
$bonus_total++;
}
}
}
// 输出格式化数据结果
for ($i = 0; $i < $bonus_count; $i++) {
$arr1[$i] = number_format($arr1[$i]/$bonus_float,$num_fmt,'.','');
//统计每个钱数的红包数量,检查是否接近正态分布
$total_money += $arr1[$i];
if(isset($arr2[$arr1[$i]])){ $arr2[$arr1[$i]] += 1; }else{ $arr2[$arr1[$i]] = 1; }
}
ksort($arr2);
$res["total"] = $total_money."(Y)";
$res["bnmax"] = $bonus_max."(".$tmp_float.")";
$res["bnmin"] = $bonus_min."(".$tmp_float.")";
$res["money"] = $arr1;
$res["count"] = $arr2;
return $res;
}
$bonus_total = 2000;
$bonus_count = 30;
$bonus_max = 90; //最大值要大于平均值
$bonus_min = 1;
$bonus_float = "Y"; //
$result_bonus = getBonus($bonus_total, $bonus_count,$bonus_max);
echo "
"; print_r($result_bonus); Array ( [total] => 2000(Y) [bnmax] => 90(Y) [bnmin] => 1(Y) [money] => Array ( [0] => 74 [1] => 24 [2] => 67 [3] => 73 [4] => 67 [5] => 47 [6] => 69 [7] => 75 [8] => 63 [9] => 44 [10] => 77 [11] => 76 [12] => 70 [13] => 76 [14] => 76 [15] => 72 [16] => 73 [17] => 85 [18] => 68 [19] => 72 [20] => 76 [21] => 68 [22] => 55 [23] => 67 [24] => 65 [25] => 75 [26] => 70 [27] => 71 [28] => 65 [29] => 40 ) [count] => Array ( [24] => 1 [40] => 1 [44] => 1 [47] => 1 [55] => 1 [63] => 1 [65] => 2 [67] => 3 [68] => 2 [69] => 1 [70] => 2 [71] => 1 [72] => 2 [73] => 2 [74] => 1 [75] => 2 [76] => 4 [77] => 1 [85] => 1 ) )
PHP下SSL加密解密、验证、签名方法(很简单)
RSA超级简单,依赖于OpenSSL扩展,这里就不多废话了,直接奉上代码
签名:
function sign($data) {
//读取私钥文件(签名一定是商户自己本地生成的私钥)
$priKey = file_get_contents('key/rsa_private_key.pem');
//转换为openssl密钥,必须是没有经过pkcs8转换的私钥(不要使用这个私钥rsa_private_key_pkcs8.pem)
$res = openssl_get_privatekey($priKey);
//调用openssl内置签名方法,生成签名$sign
openssl_sign($data, $sign, $res);
//释放资源
openssl_free_key($res);
return $sign;
}
验证:
function verify($data, $sign) {
//读取支付宝公钥文件(一定是阿里后台生成提供的公钥)
$pubKey = file_get_contents('key/alipay_public_key.pem');
//转换为openssl格式密钥
$res = openssl_get_publickey($pubKey);
//调用openssl内置方法验签,返回bool值
$result = (bool)openssl_verify($data, $sign, $res);
//释放资源
openssl_free_key($res);
return $result;
解密
function decrypt($content) {
//读取商户私钥(商户自己生成的私钥)
$priKey = file_get_contents('key/rsa_private_key.pem');
//转换为openssl密钥,必须是没有经过pkcs8转换的私钥
$res = openssl_get_privatekey($priKey);
//声明明文字符串变量
$result = '';
//循环按照128位解密
for($i = 0; $i < strlen($content)/128; $i++ ) {
$data = substr($content, $i * 128, 128);
//拆分开长度为128的字符串片段通过私钥进行解密,返回$decrypt解析后的明文
openssl_private_decrypt($data, $decrypt, $res);
//明文片段拼接
$result .= $decrypt;
}
//释放资源
openssl_free_key($res);
//返回明文
return $result;
}
AES密钥是什么
高级加密标准(英语:Advanced Encryption Standard,缩写:AES),是目前对称密钥加密中比较通用的一种加密方式。
AES密钥有什么用
支付宝开放平台所有OpenAPI均支持对接口的请求内容和响应内容进行AES加密,部分OpenAPI(芝麻信用等)强制要求AES加密。加密后,在网络上传输的接口报文内容将会由明文内容变为密文内容,可以大大提升接口内容传输的安全性。
AES密钥与RSA密钥的关系
- AES密钥是对接口请求和响应内容进行加密,密文无法被第三方识别,从而防止接口传输数据泄露。
- RSA密钥是对接口请求和响应内容进行签名,开发者和支付宝开放平台分别加签验签,以确认接口传输的内容没有被篡改。不论接口内容是明文还是密文,RSA均可正常签名。
- 开发者可对请求参数先做AES加密,然后对密文进行RSA签名。
Bootstrap表单验证插件bootstrapValidator使用方法整理
文档首页 :
http://bv.doc.javake.cn/api/
$(document).ready(function() {
// 原价、现价同时双验证
$("#original_price").blur(function () {
$("#form_yanzheng").data('bootstrapValidator').resetForm().validateField('price');
});
$("#price").blur(function () {
$("#form_yanzheng").data('bootstrapValidator').resetForm().validateField('original_price');
});
//表单验证
$('#form_yanzheng').bootstrapValidator({
message: '值没有被验证',
feedbackIcons: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
subject: {
message: 'The username is not valid',
trigger: 'blur', //失去焦点就会触发
validators: {
notEmpty: {
message: '商品名称不能为空'
},
stringLength: {
min: 2,
max: 15,
message: '输入字符数量错误'
},
callback: {
message: '商品名称有非法内容',
callback: function () {
var filter = true;
var subject = $("#subject").val();
if (subject.indexOf("储值卡") >= 0) {
filter = false;
}
if (subject.indexOf("充值卡") >= 0) {
filter = false;
}
if (subject.indexOf("会员卡") >= 0) {
filter = false;
}
if (subject.indexOf("vip卡") >= 0) {
filter = false;
}
if (subject.indexOf("打折卡") >= 0) {
filter = false;
}
if (subject.indexOf("年卡") >= 0) {
filter = false;
}
if (subject.indexOf("美容卡") >= 0) {
filter = false;
}
if (subject.indexOf("健身卡") >= 0) {
filter = false;
}
return filter;
}
}
}
},
original_price: {
trigger: 'blur', //失去焦点就会触发
message: 'The username is not valid',
validators: {
notEmpty: {
message: '输入整数或者2位小数'
},
regexp: {
regexp: /^(\d+\.\d{1,2}|\d+)$/,
message: '输入整数或者2位小数'
},
callback: {
message: '原价要大于等于现价',
callback: function () {
var op = $('#original_price').val();
var pp = $('#price').val();
return parseFloat(op) >= parseFloat(pp);
}
}
}
},
price: {
trigger: 'blur', //失去焦点就会触发
message: 'The username is not valid',
validators: {
notEmpty: {
message: '输入整数或者2位小数'
},
regexp: {
regexp: /^(\d+\.\d{1,2}|\d+)$/,
message: '输入整数或者2位小数'
},
callback: {
message: '原价要大于等于现价',
callback: function () {
var op = $('#original_price').val();
var pp = $('#price').val();
return parseFloat(op) >= parseFloat(pp);
}
}
}
},
inventory: {
trigger: 'blur', //失去焦点就会触发
message: 'The username is not valid',
validators: {
notEmpty: {
message: '输入整数或者2位小数'
},
between: {
min: 0,
max: 999999,
message: '输入有效库存数量'
}
}
},
validity_period: {
trigger: 'blur', //失去焦点就会触发
message: 'The username is not valid',
validators: {
notEmpty: {
message: '请正确填写有效天数7-360天'
},
between: {
min: 7,
max: 360,
message: '请合理输入使用有效期'
}
}
}
}
}).on('success.form.bv', function (e) {
var refertype = $('#refertype').val();
var urlpath = "{:U('Index/" + refertype + "')}";
$.ajax({
type: "POST",
url: urlpath,
data: $('#form_yanzheng').serialize(),
dataType: 'json',
success: function (data, statusText, xhr, $form) {
if (data.type == 'true') {
swal({
title: data.info,
text: "",
type: "success",
}, function () {
self.location = "{:U('Index/index')}";
});
} else {
swal(data.info, "", "error");
return false;
}
}
});
});
});
微信开发常见报错及解决方法
小技巧:可能过ctrl+f 进行查找您遇到的问题。
支付方式 | 报错提示 | 解决方法 | |
热点问题 | 支付返回签名错误 | 注意签名参数的大小写,支付密钥key要到商户平台设置,设置的规则是32位数字与字母大小写的组合。以下链接为签名过程。 (https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=3_1) |
|
支付回调 | 认证后的服务号之间支持跨号支付。 | ||
支付失败 | 请检查商户号是否错误或支付密钥key设置错误。 | ||
redirect——uri参数错误 | 请进入公众平台-开发者中心,找到填写商户的支付授权域名,填写的就是商户支付授权目录上的域名。 | ||
paysinkey如何获取? | 新版的微信支付是没有这个paysignkey参数的,具体的参数请查看文档 | ||
(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=3_1) | |||
mchid是指什么? | MCHID参数指的是商户号 | ||
openid的获取请参考文档 | openid的获取请参考文档详细介绍 | ||
(http://mp.weixin.qq.com/wiki/14/bb5031008f1494a59c6f71fa0f319c66.html) | |||
openid如何获取? | openid的获取请参考文档查看详细介绍: | ||
(http://mp.weixin.qq.com/wiki/14/bb5031008f1494a59c6f71fa0f319c66.html) | |||
Appsecret如何获取? | APPsecret参数可进入公众平台(https://mp.weixin.qq.com)开发者中心查看。 | ||
调用报错 get_brand_wcpay_request:fail |
签名错误,请仔细检查签名。 | ||
spbill_create_ip 是指什么? | spbill_create_ip 指的是终端ip,在APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。 | ||
网页支付(JSAPI) | “当前公众号没有权限支付本次交易“ | 检查该公众帐号是否已经获取了支付资格。 | |
“公众帐号支付使用了无效的商户号,无法发起该笔交易” | 检查商户号使用错误。 | ||
“该公众号支付签名无效,无法发起该笔交易” | 调起支付MD5签名的MD5签名错误,请检查相关签名。 | ||
“Args Error” | 提交JS时,josn传递参数必须与文档中名字一致,大小写匹配。 | ||
“access:not_allow” | 未设置白名单,添加位置:微信公众平台=》微信支付=》开发配置 | ||
点击支付无反应 | 支付授权目录是否正确,如果使用的是支付测试目录,是否设置了白名单,需白名单帐号进行支付测试。 | ||
ios系统可以正常支付,android系统支付失败 | timestamp字段值需要加上“”,传递数据必须为字符串类型。 | ||
调用报错 get_brand_wcpay_request:fail |
签名错误,请仔细检查签名。 | ||
调用报错: zhgj-2014+中涵国际分销商城及“订单满送红包无法送” |
商户设置有问题。 | ||
IOS系统调用支付JSAPI报错 缺少参数:$key0$,android 没问题 |
提交的参数有问题,注意全部参数都得是字符串类型。 | ||
支付验证签名失败 | 签名错误,仔细检查签名。 | ||
jsapi 缺少参数 key0 | 问题出在网页端调起支付API接口中timeStamp参数,必须是string类型,但是php默认生成的时间戳是int类型。 解决方法:修改下lib/Wxpay.Data.php约2731行处SetTimeStamp方法,修改为$this->values['timestamp'] = (string)$value; |
||
安卓手机可以收到满送红包 苹果的不行 红包虽然已经显示发送了红包但是实质资金流水没有扣除资金 | 参数错误,请仔细检查。 | ||
调用报错: 传输参数错误 |
推测为提交的支付请求参数不正确;以下文档有详细的参考。https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7 | ||
调用报错: 没有获取到微信支付预支付ID,请管理员检查微信支付配置项 |
需要按照文档要求 ,先获取prepay_id。 | ||
支付权限检查失败 | 商户所用的参数对应的APPID是APP支付;如果商户想要JSAPI支付,需要在公众平台申请公众号,公众号支付中才有此参数。 | ||
原生支付(扫码支付) | “获取商户数据失败” | 请检查申请native支付时的回调URL地址是否正确,是否可以外网访问获取数据。 | |
“商户返回数据错误” | native回调返回数据格式错误,非XML格式数据。 | ||
“签名错误” | 检查MD5签名中参数格式及值是否正确。 | ||
调用报错: 获取商户订单信息超时或商户返回httpcode非200 |
签名错误,请仔细检查签名。 | ||
错误返回:错误码:60 | 错误通过修改文件:WxPay.Api.php解决,具体如下: 第537行 curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TURE); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,2);//严格校验 to curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);//严格校验2 微信支付错误两个问题的解决:curl出错,错误码:60 |
||
APP支付 | 错误返回“-1” | 开放平台配置的报名和应用签名是否一致:(android);确认是否使用正式的keystore打包apk并安装调试;(android);提交订单部分需要在服务器端完成。 | |
下单报{"errcode":62621014,"errmsg":""} | Package数据MD5签名错误,请参照文档检查。 | ||
下单报"1001"错误 | package里缺少必要参数;金额类型为证书,单位是分。 | ||
android签名正常,ios签名错误 | 需要注意body如果是中文,需要编码,编码格式统一为“UTF-8”。 | ||
支付授权地址没有经过ICP验证 | 域名需要是英文备案域名方可。(此情况针对备案域名中包含中文字符或其他) | ||
ios系统:订单成功,无法跳转到支付界面 | 请仔细查阅参考开发文档步骤。 | ||
支付结果报错:errStr=null,code=-1 | 请检查开放平台配置的包名和签名是否跟APK安装后的包名签名一致,一致才会调用的。 | ||
支付无法调起 | 请检查开放平台配置的包名和签名是否跟你的APK安装后的包名签名一致,一致才会调用的。 | ||
需要V3版的app支付服务端demo,因获取prepayId失败,找不到app_key | 新版的微信支付是没有这个参数的,请查看最新版文档。 | ||
请求prepayid发生错误: errcode":268497023,"errmsg |
请将商户的APPID和商户号以及报错截图发送至wepayTS@tencent.com,进行深入了解。 | ||
支付返回报错: :"errcode":268497023,"errmsg":"您已完成交易接口升级,老接口交易权限已关闭,请使用新接口进行交易。如有疑问请联系微信支付客服咨询" |
请将商户的APPID和商户号以及报错截图发送至wepayTS@tencent.com,进行深入了解。 | ||
请求prepayid发生错误: 信息[{"errcode":268497023,"errmsg":"鎮ㄥ凡瀹屾垚浜ゆ槗鎺ュ彛鍗囩骇锛岃 鎺ュ彛浜ゆ槗鏉冮檺宸插叧闂紝璇蜂娇鐢ㄦ柊鎺ュ彛杩涜浜ゆ槗銆傚鏈夌枒闂鑱旂郴寰俊鏀粯瀹㈡湇鍜ㄨ"}] |
请将商户的APPID和商户号以及报错截图发送至wepayTS@tencent.com,进行深入了解。 | ||
根据文档下订单,调用微信支付失败。调用微信支付的时候,微信为登录状态则无反应;微信未登录状态,会调用微信登录界面。 | 请将商户的APPID和商户号以及报错截图+请求参数详情,发送至wepayTS@tencent.com,进行深入了解。 | ||
常见问题 | 申请正在审核中,如何可以提前调试测试? | 只需要资料审核通过,收到通知邮件即可通过配置测试目录进行联调测试。未审核通过可下载文档进行开发,但不能联调测试。 | |
支付授权目录是什么? | 支付授权目录是支付功能正式上线后,商户后台发起支付请求的页面所在的目录。 | ||
支付测试目录是什么? | 支付测试目录提供给开发者,在开发测试期间使用的临时目录。 | ||
支付测试目录和授权目录有何区别? | 支付授权目录将会在产品上线审核时,以及上线后长期使用的正式目录;测试目录只能配置白名单,才可以在公众号内发起支付。 | ||
如何配置支付目录(授权、测试)? | 登录微信公众平台-微信支付-开发配置-修改 | ||
支付目录有什么规则? | 头部需要包含http或https,须细化到二级或三级目录,字母小写,以左斜杠“/”结尾。 | ||
如何配置授权回调页面域名? | 登录微信公众平台=》开发者中心=》网页授权获取用户基本信息=》修改 | ||
微信支付接口的签名规则是如何的? | MD5签名,订单数据签名,所有传输的字段均需要参与签名,使用商户密钥key在签名字段排序后放入在最后组包签名。 | ||
“订单数据签名验证失败”如何解决? | 检查参数是否一致;是否含有特殊字符;中文编码类型是否与所传参数一致;body参数是否含空格,若有空格URLencode的时需要转为%20。 | ||
报40001错误,如何解决? | accesstoken失效或者过期,accesstoken有效期为2小时,如果有系统或者人为重新获取,前一个accesstoken也会自动消失。请保证accesstoken为全局管理,避免重复获取。 | ||
签名正常,却提示fail_invalid appid | 查看支付授权目录是否设置正确,所支付页面路径是否在支付授权目录下。 | ||
公众号是否可以跨号支付? | 两个具有支付权限的服务号之间可以跨号支付,但不可混淆appid。 | ||
支付完成,Notify URL无法接收回调通知 | 需要绝对路径,外网可访问,不支持非80端口,同时注意不要被防火墙拦截;可自行用fiddler模拟post访问是否正常。 | ||
查询订单接口报“errcode":49001,"errmsg": | 检查accesstoken是否为同一APPID获取;POST数据必须为JSON格式, | ||
"not same appid with appid of access_token"错误如何解决? | 避免格式不对导致获取APPID不一致。 | ||
支付提示“系统繁忙,请稍后再试” | 检查签名及传入参数是否与文档要求一致;尤其是MD5签名部门的正确性。 | ||
调用支付报错【特殊】 | 调用报错: “chooseWXPay:fail” |
此情况需要商户将提交的签名过程发送至邮箱:wepayTS@tencent.com,进行深入了解。 | |
调用报错: “{return_msg=支付权限检查失败, return_code=FAIL}” |
此情况需要将提交的xml发送至邮箱:wepayTS@tencent.com,进行深入了解。 | ||
zhgj-2014+中涵国际分销商城及“订单满送红包无法送” | 请将商户的APPID和商户号以及报错截图发送至wepayTS@tencent.com,进行深入了解。 | ||
微信支付完成后不能执行回调 | 请将商户的APPID和商户号以及报错截图发送至wepayTS@tencent.com,进行深入了解。 | ||
报错:不允许跨号支付 ios上没这个问题,android上有些商品有这个问题 |
是否通过订阅号发出此请求,请将APPID,商户号,报错截图及请求参数发送至wepayTS@tencent.com,进行深入了解。 |
file_get_contents(“php://input”)的使用方法
$data = file_get_contents("php://input");
php://input 是个可以访问请求的原始数据的只读流。 POST 请求的情况下,最好使用 php://input 来代替 $HTTP_RAW_POST_DATA,因为它不依赖于特定的 php.ini 指令。 而且,这样的情况下 $HTTP_RAW_POST_DATA 默认没有填充, 比激活 always_populate_raw_post_data 潜在需要更少的内存。 enctype="multipart/form-data" 的时候 php://input 是无效的。
1, php://input 可以读取http entity body中指定长度的值,由Content-Length指定长度,不管是POST方式或者GET方法提交过来的数据。但是,一般GET方法提交数据 时,http request entity body部分都为空。
2,php://input 与$HTTP_RAW_POST_DATA读取的数据是一样的,都只读取Content-Type不为multipart/form-data的数据。
学习笔记
1,Coentent-Type仅在取值为application/x-www-data-urlencoded和multipart/form-data两种情况下,PHP才会将http请求数据包中相应的数据填入全局变量$_POST
2,PHP不能识别的Content-Type类型的时候,会将http请求包中相应的数据填入变量$HTTP_RAW_POST_DATA
3, 只有Coentent-Type为multipart/form-data的时候,PHP不会将http请求数据包中的相应数据填入php://input,否则其它情况都会。填入的长度,由Coentent-Length指定。
4,只有Content-Type为application/x-www-data-urlencoded时,php://input数据才跟$_POST数据相一致。
5,php://input数据总是跟$HTTP_RAW_POST_DATA相同,但是php://input比$HTTP_RAW_POST_DATA更凑效,且不需要特殊设置php.ini
6,PHP会将PATH字段的query_path部分,填入全局变量$_GET。通常情况下,GET方法提交的http请求,body为空。
例子
1.php用file_get_contents("php://input")或者$HTTP_RAW_POST_DATA可以接收xml数据
比如:
getXML.php;//接收XML地址
<?php
$xmldata = file_get_contents("php://input");
$data = (array)simplexml_load_string($xmldata);
?>
这里的$data就是包含xml数据的数组,具体php解析xml数据更新详细的方法
sendXML.php
<?php
$xml = '<xml>xmldata</xml>';//要发送的xml
$url = 'http://localhost/test/getXML.php';//接收XML地址
$header = 'Content-type: text/xml';//定义content-type为xml
$ch = curl_init(); //初始化curl
curl_setopt($ch, CURLOPT_URL, $url);//设置链接
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//设置是否返回信息
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);//设置HTTP头
curl_setopt($ch, CURLOPT_POST, 1);//设置为POST方式
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);//POST数据
$response = curl_exec($ch);//接收返回信息
if(curl_errno($ch)){//出错则显示错误信息
print curl_error($ch);
}
curl_close($ch); //关闭curl链接
echo $response;//显示返回信息
?>
2.一个手机上传图片到服务器的小程序
上传文件
<?php
//@file phpinput_post.php
$data=file_get_contents('btn.png');
$http_entity_body = $data;
$http_entity_type = 'application/x-www-form-urlencoded';
$http_entity_length = strlen($http_entity_body);
$host = '127.0.0.1';
$port = 80;
$path = '/image.php';
$fp = fsockopen($host, $port, $error_no, $error_desc, 30);
if ($fp){
fputs($fp, "POST {$path} HTTP/1.1\r\n");
fputs($fp, "Host: {$host}\r\n");
fputs($fp, "Content-Type: {$http_entity_type}\r\n");
fputs($fp, "Content-Length: {$http_entity_length}\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $http_entity_body . "\r\n\r\n");
while (!feof($fp)) {
$d .= fgets($fp, 4096);
}
fclose($fp);
echo $d;
}
?>
接收文件
<?php
/**
*Recieve image data
**/
error_reporting(E_ALL);
function get_contents() {
$xmlstr= file_get_contents("php://input");
$filename=time().'.png';
if(file_put_contents($filename,$xmlstr)){
echo 'success';
}else{
echo 'failed';
}
}
get_contents();
?>
3.获取HTTP请求原文
/**
* 获取HTTP请求原文
* @return string
*/
function get_http_raw() {
$raw = '';
// (1) 请求行
$raw .= $_SERVER['REQUEST_METHOD'].' '.$_SERVER['REQUEST_URI'].' '.$_SERVER['SERVER_PROTOCOL']."\r\n";
// (2) 请求Headers
foreach($_SERVER as $key => $value) {
if(substr($key, 0, 5) === 'HTTP_') {
$key = substr($key, 5);
$key = str_replace('_', '-', $key);
$raw .= $key.': '.$value."\r\n";
}
}
// (3) 空行
$raw .= "\r\n";
// (4) 请求Body
$raw .= file_get_contents('php://input');
return $raw;
}
web页面快速生成二维码的两种实用方法
二维码是桌面和移动端快速分享的高效手段之一,这里介绍两个不错的快速开发二维码的方法,和大家分享一下~~
方法1:使用新浪提供的服务
这种方式简单快速,在服务端生成一个二维码的图片,兼容性比较好,你无需自己处理任何相关二维码的生成,只需要提供一端文字或者url即可,方法如下:
生成效果如下:
大家扫一扫就可以访问极客标签主站了~~
方法2: 使用jQuery插件qrcode
QRcode是一个jQuery插件,可以使用javascript快速帮助你生成相关的二维码
相关代码如下:
- var qrcode = new QRCode("qrcode", {
- text: "http://www.gbtags.com",
- width: 260,
- height: 260,
- colorDark: '#efb73e',
- colorLight: "#ffffff"
- });
生成效果如下:
如果对这个插件有兴趣,推荐阅读这节课程: QRcode的使用
以上是两种比较实用的生成二维码的方法, 懒人推荐使用第一种, 简单快速, 如果需要深度自定义的话,推荐自己使用JS来实现相关的二维码,具体看大家需求, 极客标签的代码分享使用的是第一种,大家可以参考一下,如下:
linux下mysql的root密码忘记解决方法
1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库。
因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的
状态下,其他的用户也可以任意地登录和修改MySQL的信息。可以采用将MySQL对
外的端口封闭,并且停止Apache以及所有的用户进程的方法实现服务器的准安全
状态。最安全的状态是到服务器的Console上面操作,并且拔掉网线。
2.修改MySQL的登录设置:
# vi /etc/my.cnf
在[mysqld]的段中加上一句:skip-grant-tables
例如:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
skip-grant-tables
保存并且退出vi。
3.重新启动mysqld
# /etc/init.d/mysqld restart
Stopping MySQL: [ OK ]
Starting MySQL: [ OK ]
4.登录并修改MySQL的root密码
# /usr/bin/mysql
Welcome to the MySQL monitor. Commands end with ; or g.
Your MySQL connection id is 3 to server version: 3.23.56
Type 'help;' or 'h' for help. Type 'c' to clear the buffer.
mysql> USE mysql ;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> UPDATE user SET Password = password ( 'new-password' ) WHERE User = 'root' ;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 2 Changed: 0 Warnings: 0
mysql> flush privileges ;
Query OK, 0 rows affected (0.01 sec)
mysql> quit
Bye
5.将MySQL的登录设置修改回来
# vi /etc/my.cnf
将刚才在[mysqld]的段中加上的skip-grant-tables删除
保存并且退出vi。
6.重新启动mysqld
# /etc/init.d/mysqld restart
Stopping MySQL: [ OK ]
Starting MySQL: [ OK ]
skip-networking #注释掉 因为它是屏蔽掉一切TCP/IP连接
bind-address = 127.0.0.1 #它和上一个选项是异曲同工,要想远程连接,也得注释掉
2.如果以上工作都做过还是出现:
ERROR 2003 (HY000): Can't connect to MySQL server on '*.*.*.*' (113),那就得考虑防火墙的问题了,关掉防火墙/etc/rc.d/init.d/iptables stop
修改完后需要 restart mysql (/etc/init.d/mysql restart)
寻找纳什均衡点的方法
相对于那本《写给中国人的经济学》,这本《妙趣横生博弈论》对纳什均衡的介绍显然更清楚,自然也更容易理解。原书第4章——美丽的均衡中第85页开始如此写到:“如果有这样的博弈结果,即,给定关于对方行动的信念,每个参与者的行动是其对其他人行动的最优反应,而且每个参与者的行动与对方关于其行动的信念是一致的,那么这类博弈结果就可以巧妙地解开‘我认为他认为’的循环。这样的结果有一个非常好的名号,叫参与人思维过程的静止点,或者叫做博弈的均衡。是的,这正是纳什均衡的定义。”
嗯,只看这段话根本不知道什么是纳什均衡,更具体的例子才能让人理解。这里不纠结什么是纳什均衡,只针对书中一例,说说怎么寻找纳什均衡点,因为我对于后文所介绍的“逐步剔除法”不是很理解,我喜欢的方法和再后面99页的连续数值的方法更相似一些。
原例如下(简化):
两个存在竞争关系的衬衫生产公司彩虹之巅(RE)和比比里恩(BB)要为自己生产的衬衫定价,他们生产一件衬衫的成本都是20元,当两家公司都定价42元时,分别可以销售出1960件,于是,他们分别可以获得的利润为(42-20)×1960=43120元。
现在开始,一家公司每降低1元,如果另外一家公司维持原价,降价的公司就可以多获得100个新客户,其中,20个是新增加的边际顾客,另外80个顾客是从维持原价的公司争取过来的;但是,如果另外一个公司也降低了1元,先降价的公司就没法争取到那80个顾客,取而代之的是,两家公司都分别增加20个边际顾客。
将两个公司的衬衫定价按照1元的减少量,从42元变动到38元,他们的博弈组合如下图所示:
如上图所示,每个单元格中,右上角是BB公司的利润,左下角是RE公司的利润。
其中填充蓝色的单元格就是纳什均衡点,在这里,两家公司的利润都是40000元,对两家公司而言都是一个稳定的结果,从这个点向四周改变,或者对两家公司或者都不利,或者对其中一家不利,只要有一方感觉不划算,就会调整价格,那个点就不会稳定,而只有这个点是很稳定的。
寻找的方法:
这里对纳什均衡点说不出更高深的解释,只是根据对纳什均衡点的理解,说说寻找它的方法吧,至少我试过几个例子,都没有发现错误。步骤如下:
- 1.从BB的定价开始,在其定价确定的前提下,分别从每一列中寻找对RE公司而言,利润最高的单元格,然后将这些单元格连接起来,就是图中的紫色曲线;
- 2.从RE的定价开始,在其定价确定的前提下,分别从每一行中寻找对BB公司而言,利润最高的单元格,然后将这些单元格连接起来,就是图中的黄色曲线;
- 3.两条曲线的交点就是纳什均衡点。
最后,两条曲线的交点有多少个,该博弈就有多少个纳什均衡点,本章所介绍的石器时代猎人狩猎会合的博弈被称为“确信博弈”,按照书中的介绍,这不同于前章的“囚徒困境”博弈:因为“囚徒困境”对一方而言,无论对方的选择如何,自己始终存在“优势策略”;而“确定博弈”只有双方选择相同才是“优势策略”。
看上去,“囚徒困境”好像是“确信博弈”的特例,但是将博弈表列举出来才会发现,仅仅因为某些数字的变化,两者还是有着很大的区别。例如:对比58页“囚徒困境”案例中,同样是上述两家公司的处境,由于在对手公司不降价的前提下作出降价选择,会让降价公司获取巨大的利益,所以,追求利益的公司几乎不可能会对手保持不降价的一致选择。
结果,在“囚徒困境”中,按照上述寻找纳什均衡点的方法操作,同样会发现这样一个点(按照我的理解,这个点应该也是纳什均衡点!),一个双方都选择背叛后沦落的全部失利的下场,对于“确信博弈”而言,只有双方选择一直,哪怕是所谓的“背叛”,大家仍然可以获得最好的结果,唯一的区别恐怕只是,当存在多个纳什均衡点时,哪个才是“聚焦点”的问题。
————————
继续阅读本书发现,回味纳什均衡,其中“同时行动”的意味深长,倘若换成“序贯行动”,即后者可以根据前者的选择再决定行动,而前者无法针对后者的选择重新调整,这种情况下去找出的纳什均衡点,可并不是个好的选择(参见原书第6章策略行动中,晚上的自己设定闹钟叫醒清晨的自己,本应该用博弈树分析的例子换成博弈表之后,作者分析的过程和结果。)~甚至,我怀疑这种博弈是否存在纳什均衡点……继续读下去吧~
项目经理问:我怎么有做不完的事情 – 事件篮方法
如何管理好自己的时间
原创文章,如有转载,请注明出处:http://blog.csdn.net/yihui823/article/details/6826353
时间管理,本身就是一门艺术。时间是最公平的,每个人的时间都是一样的。如何在相同的时间里,做出不同的事业,这就是个人水平的体现。
一、 故事
这里先讲一个故事。故事是抄来的,我修改了其中的一部分,使其更贴近我要说的主题。
有两个和尚他们分别住在相邻的两座山上的庙里。左边的山上住着瘦和尚,右边山上住着胖和尚。这两座山之间有一条溪,于是这两个和尚每天都会在同一时间下山去溪边挑水,久而久之他么变成为了好朋友。两个和尚都喜欢游泳。胖和尚经常在挑水的时候,顺便游上那么一会儿,而瘦和尚却极少在溪水里游泳。
不知不觉五年过去了。有一天,瘦和尚竟然没有带扁担来挑水,而是直接在溪里面游泳。胖和尚很纳闷,就问瘦和尚,你今天不挑水,怎么有水喝啊。瘦和尚说,这五年来,我每天做完功课后都会抽空在庙后面挖一口井,即使有时很忙,能挖多少就算多少。如今终于让我挖出井水,我就不用再下山挑水。现在我终于可以放心的游泳了。
于是,每天瘦和尚都可以自在的游泳,而胖和尚还是只能游一会儿就得挑水回庙里。突然有一天,两座庙同时失火了。瘦和尚很快就用井水把火扑灭了。而胖和尚还得跑到溪里面去挑水灭火,结果火灭的时候,庙已经烧掉了一大半了。
接下来,胖和尚每天除了要安排时间挑水,还得花大部分时间去修补破庙。而瘦和尚在游泳之余,还潜心书画。故事完毕。
二、 重要度/紧急度
故事说完了,我们再来重头分析做事情的顺序。
根据重要度和紧急度来区分事件,是一个非常常用的方法。但是,到底什么叫重要,什么叫紧急呢?
重要的事情:对以后的工作生活、对以后的发展等,会产生明显的影响的事情,对目标的达成有显著推动的事情。
紧急的事情:需要立即处理的事情。
我们按照以上的象限图,来说一下事件的重要度和紧急度。
4:即不重要,又不紧急的事情。
即不对以后会产生重要的影响,又不是立即需要处理的事情。类似于和尚的游泳事情。此类事情,一般都是些兴趣爱好,或者受人之托,或者偶然的想法。
3:紧急不重要的事情
只是立即需要处理,但是并不会对将来产生重要影响的事情。类似于和尚的挑水,每天必须做,不做不行,但是做了也就是解决当前问题
2:重要不紧急的事情
不是当前必须要立即处理的,但是对以后会产生深远影响的事情。类似于瘦和尚的挖井,不挖也没事,但是一旦挖成功了,后面就可以不挑水了。如果当前有明确的目标,这类事情可以是对目标达成有明显帮助的事情。
1:重要紧急的事情
当前必须处理,不处理会立刻造成很严重的后果。类似于和尚们的庙失火,不立刻救火,就没有住的地方了。
三、 分类处理
以上的四类事件,该如何分别处理呢?
很显然,最优先做的,是做重要紧急的事情,我想这谁都知道。而且这类事件,一般都是很容易标识出来的,也是非做不可的,人们一般都不会忘掉。
但是,并不是所有的事件都是重要紧急的。重要紧急的事件,一般都是救火类的事件,也就是说,是因为工作不好,或者一些意外造成的。那么,我们的正常工作中,充满了其他三种类型的事件,又应该如何各自的时间分配呢?
同样很显然,不紧急不重要的事情,尽量不要做。但是这个说起来容易,做起来却不容易。因为这类事件既然列出来了,就会有其诱惑性。例如很多人喜欢看电视,喜欢打游戏,喜欢看小说等等。就算在工作中,这类事情也是每个人都喜欢做的事情。很多项目经理会安排自己去编码,就是因为技术出身的,往往就喜欢去编码。所以说,这类事情,需要克制住,一定要克制住自己去做不重要不紧急的事情的冲动。
那么,剩下的2和3,需要怎么处理呢?
一个很普遍也很正常的理解,就是先做紧急不重要的,再做重要不紧急的。
坦率来说,这个想法也很正常。既然事情很紧急,那么我当然需要马上处理。重要不紧急的事情,等有空再说吧。
其实,很不然!
紧急不重要的事情,往往都是些日常的工作,都是或者都是些助人为乐的工作,容易做,周期又短,对将来不会造成多大的影响。也就是说,做了最好,不做也影响不大。但是,重要不紧急的事情,一般都是对将来会造成影响的事情,这类事情,往往都是不愿意做、周期长、难做的事情。
打个比方吧。项目组的新人比较多。项目经理需要整理一份技术培训资料,给新人们集中培训。这个就是重要不紧急的。而新人们有时候碰到问题,就直接跑来找项目经理求助,项目经理需要去帮他们解决问题,这就是紧急不重要。
如果项目经理频繁的打断手头上的事情,去帮新人们解决问题,则技术培训资料迟迟无法做出来,那么新人们的问题就会层出不穷,绵绵不断。这个就是个恶性循环。
如果项目经理能够果断的先出培训资料,争取早日把培训做起来,则问题会逐渐减少,这就是个良性循环。
还有一个更生动的例子。假如你在洗澡,满身都是泡泡,这个时候听到来了一个电话。接电话就是紧急不重要的事情,如果你去做了,结果就是满地的肥皂泡泡要打扫,就造成了一堆的紧急不重要事件。
所以说,要想把时间控制在自己手上,最需要做的事情就是:
重要不紧急
这类事件,周期长,难度大,所以需要日积月累的去坚持。这才是解决问题的王道。
四、 疑点分析
很多人都会说,说起来容易做起来难。我们来分析几个疑点的地方。
1. 紧急不重要的事情层出不穷,怎么办?
还是用刚才那个例子,如果新人们的问题不断,我总不能放任不管吧。
其实,就算你不立即去帮他们解决问题,他们也只是郁闷一阵子而已。这种时候,可以让他们先把问题都整理出来,整理清楚,并尝试着自己解决。然后在某个固定的时间段内(例如每天下午2点到3点之间),你集中帮他们解决即可。或者可以把解决问题的事情分摊在项目的其他几个技术高手身上。
2. 一下子又做不完的事情,总是没有动力去做。
这类事件,一般都不是立马见效的。需要制定一个长期的计划,每天都安排固定的时间去做。不管多少,要保证每天都有进展。
3. 我喜欢做的事情,就没时间做了啊。
相信我,只有把重要不紧急的事情做完备了,才会有更多的时间去做你喜欢做的事情。瘦和尚挖井成功了,就会有更多的时间游泳了。
4. 不做重要不紧急的事情,不也是一样的嘛。
防火和救火的概念。如果只是做好当前的事情,每天做好紧急不重要的事情,那么一旦出现意外,则会造成更严重的后果,以后的事情都会变成重要紧急的。如果不把时间掌握在自己手上,那么就是每天都在救火状态。
五、 处理流程
以前有一种做法,是每天上午,把要做的事情都列出来,然后每天晚上再把工作都整理一下,看看哪些做了,哪些没做。现在信息化社会,每天都会面临大量临时发生的事情。所以,现在可以用“事件篮”的方式来做。
现在开始,你准备一个“篮子”。这个篮子,可以是一个便签,也可以是一个小软件。作者用的是outlook的“任务”工具,这个可以和windows mobile手机同步。其他的工具也一样,只要能随身带着就行。
一旦你接受到一个任务,或者发现要处理的事件,先扔进“事件篮”里面。这个就像编码的时候发送消息到消息队列一样,不是同步处理的,也就是说,不是立即处理,再紧急也不是立即处理。
扔进去之后,判断这个事件是不是“重要紧急”。如果是老板喊你,或者工厂失火等重要紧急的事件,那么立即放下自己手上的活,去处理。
如果不是“重要紧急”的事情,那么就先让它在“事件篮”里呆上一会儿吧,专心把你自己当前在处理的事情做完。
做完了当前的事件,回顾你的事件篮。如果还有未识别的事件,则识别一下,按重要度很紧急度标识上。然后,看看你今天的重要不紧急的事件有没有处理,如果没有处理,则优先处理重要不紧急的事情。
经常性的,例如每周,都回顾一下自己的事件篮,把各个事件的重要紧急度重新识别一下。
六、 经验
好记性不如烂笔头
不要以为自己的大脑有多狠,事情一多肯定会乱掉。设置合理的提醒机制,提醒你开会等定时的事情,会让你少很多心理负担。
不要同时做两件事情
不要把自己当作CPU。同时做两件事情,结果是没有一件能做好。完整的做完一件事情之后,再去找其他事情做吧。不要总是被打断工作,有些事情不立即处理,是不会有什么坏处的。
要找出“重要不紧急”的事情
很多需要被人推着走的人,是找不到“重要不紧急”的事情的。对于项目来说,经常的去识别风险,经常去想想项目可能会碰到的问题,提前预防,这都是“重要不紧急”的事情。千万不能任其自然发展,等到出事的时候,就是到处“重要紧急”的事件了,就疲于奔命了。
认准目标
识别“重要不紧急”的事件,最重要的标志,就是对终极目标是否有利。远大的目标,永远是大于眼前目标的。如果只是看准眼前目标,那么永远找不到“重要不紧急”的事情,或者永远找不对。