curl与file_get_contents访问远程接口慢的解决

  这几天在协调处理短信接口调用失败的问题,处理完后发现发送短信很耗时,要5秒左右,是PHP调用 file_get_contents访问远程接口的的,而我前面处理调用失败问题时最后测试短信接口时是直接用的Linux命令curl调用,速度是非常快的。

  先从代码入手,刚开始以为是file_get_contents比curl慢,虽然觉得也不至于慢到这种程度,但是总得试试看,于是换成curl,依旧很慢。

  难道是域名解析问题?于是在hosts文件里写好本地解析,再试,果真正常了,秒发。看来真是域名解析问题,但又不知为何Shell里没问题,独独PHP里有问题。虽然把域名写死在hosts里能解决问题,但是总不是办法。

  上网查,有人说是PHP缓存了域名解析,重启PHP即可。我马上去重启PHP,还真好了。但是有一点我不明白,既然是缓存,那应该是速度更快才对。在一个技术群里讨论时我突然想起来昨天测试接口时发现服务器设置的首选DNS是不能用的,然后我改了。难道PHP缓存的不是域名解析,而是域名解析服务器(DNS)?看来只有这个解释了,有空可以做个测试验证一下。

PHP中Notice: iconv(): Unknown error (84) 的解决办法

   今天在写一个导出数据到csv的功能,为了防止中文乱码,需要将utf8转码,我使用了这样的语句:

#这里先是把csv文件的内容生成,然后下面转码
$csv=iconv('utf-8','gb2312',$csv);

结果报Notice: iconv(): Unknown error (22)的错误,想起来$csv里带有换行,所以没办法转换,于是在各个数据项串成csv文件内容前转换,这时报了两个iconv(): Unknown error (84)的错误,输出内容,发现报错时有一个是处理汉字“密菓”,第二个字不认得,生僻,我突然想到,难道是字符集不支持,于是换成gbk:

$csv .= iconv('utf-8','gbk',$val)

再运行,没报错了。

微信大文件的清理

   最近手机可用空间越来越小了,新软件都没办法安装。前几天都是用手机自带的垃圾清理软件清理一些缓存之类的才能安装新软件,老是这样,太麻烦了。

  今天决定动手解决这个问题。用软件分析过文件占用后发现微信APP的文件夹里有几个文件异常的大,其中85f22adb…(很长就不抄完了)/sfs文件夹下有一个文件名叫sns.block.00001,大小达到1.3G。不知道这文件是干什么用的,删除怕聊天记录也没了,上网搜索了下,也没有人能说出个所以然。看这文件名,带有sns,我猜测与朋友圈有关系,于是退出微信,先重命名备份这个文件,然后再打开微信,发现聊天记录正常,没丢,通讯录也正常。再进入sfs文件夹,发现微信已经新建了一个文件sns.block.00000,为了验证我的想法,我刷了下朋友圈,再去看这个文件,发现变大了一些,再往下拉,加载更多的朋友圈内容,每加载一些内容,这个文件就会变大,观看朋友圈视频后也一样会增加此文件大小。由此可见此文件是保存朋友圈信息用的。

  总结:类似sns.block.00000,sns.block.00001这样的文件是保存朋友圈信息用的,以便回看历史信息能快速加载,少耗费流量。所以可以大胆放心地删除,最多是查看近日朋友圈内容的时候再下载一次而已。

博客貌似被黑了,有空换PHP的

   由于近来工作比较忙,所以有大半年没关注我这个博客站了。

  前两天发现站点打不开了,于是找朋友要了个小地方,放上去,今天发现一堆的垃圾评论与留言,想登录后台管理,结果发现登录不上,提示密码错误。以为自己记错了,试了几个可能的密码,都不行,于量拿出很早已经写的重置用户密码的代码,重置,再登录,也不行,傻眼了,难道管理员用户有另外的表,记得没有啊,查看数据库确认表,才发现我的用户名被改了。看来是已经被黑了。

  这个博客站是8年前架的,那时用的是ASP,现在早就改行做PHP了,正好可以抽空把这个站也改成PHP的。

  除了用户名被改,还有恶意注册与留言,得抓紧时间换了。

使用socket方式连接Nginx优化php-fpm性能

Nginx连接fastcgi的方式有2种:TCP和unix domain socket

什么是Unix domain socket?—— 维基百科
Unix domain socket 或者 IPC socket是一种终端,可以使同一台操作系统上的两个或多个进程进行数据通信。与管道相比,Unix domain sockets 既可以使用字节流和数据队列,而管道通信则只能通过字节流。Unix domain sockets的接口和Internet socket很像,但它不使用网络底层协议来通信。Unix domain socket 的功能是POSIX操作系统里的一种组件。

Unix domain sockets 使用系统文件的地址来作为自己的身份。它可以被系统进程引用。所以两个进程可以同时打开一个Unix domain sockets来进行通信。不过这种通信方式是发生在系统内核里而不会在网络里传播。

TCP和unix domain socket方式对比
TCP是使用TCP端口连接127.0.0.1:9000
Socket是使用unix domain socket连接套接字/dev/shm/php-cgi.sock(很多教程使用路径/tmp,而路径/dev/shm是个tmpfs,速度比磁盘快得多

测试机是个1核的centos5.4,2用户并发时系统资源消耗50%左右,10用户资源就跑得很满了。

 
    2users 10users
nginx/1.2.9 + PHP 5.2.5 tcp 1060 1294
nginx/1.2.9 + PHP 5.2.5 socket 997 1487
nginx/1.2.9 + PHP 5.3.10 tcp 906 1082
nginx/1.2.9 + PHP 5.3.10 socket 880 1247

结论是在服务器压力不大的情况下,tcp和socket差别不大,但在压力比较满的时候,用套接字方式,效果确实比较好。

下面是php 5.3以上版本将TCP改成socket方式的配置方法:

修改php-fpm.conf(/usr/local/php/etc/php-fpm.conf)

XML/HTML代码
  1. ;listen = 127.0.0.1:9000  
  2. listen = /dev/shm/php-cgi.sock  

修改nginx配置文件server段的配置,将http的方式改为socket方式

XML/HTML代码
  1. location ~ .php$ {  
  2.     #fastcgi_pass   127.0.0.1:9000;  
  3.     fastcgi_pass unix:/dev/shm/php-cgi.sock;  
  4.     fastcgi_index  index.php;  
  5.     fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;  
  6.     include        fastcgi_params;  
  7. }  

重启php-fpm与nginx

service nginx restart
service php-fpm restart

然后
ls -al /dev/shm
可以看到php-cgi.sock文件unix套接字类型

参考:http://zh.wikipedia.org/wiki/Unix_domain_socket

 

转载后记:我根据上文配置完后,访问PHP页面出现502,查看Nginx日志,有错误信息:nginx error connect to php-cgi.sock failed (13: Permission denied)

编辑配置文件/usr/local/php/etc/php-fpm.conf

;listen.owner = nobody
;listen.group = nobody
;listen.mode = 0660
改为
listen.owner = nobody
listen.group = nobody
listen.mode = 0666

保存,重启PHP-FPM即可

 

xhprof与Xdebug的奇怪问题

  为了查找项目中比较耗性能的PHP代码,这两天在装xhprof用来跟踪代码,结果遇到了一个很奇怪的问题。安装配置好xhprof后,用来跟踪简单的代码没一点问题,但是在项目中一跟踪,PHP-FPM进程直接就挂了,查看各种日志,并且开了内核转储,折腾了半天也没找到挂了的原因。

  没办法,只好换Xdebug。安装,配置,很快就搞定了。

  在使用Xdebug前我突发奇想,不知道Xdebug能不能跟踪到xhprof导致PHP-FPM挂了的的问题,于是同时启用两者,结果意外地发现xhprof也能用了。为了证明是不是Xdebug导致xhprof可以用了,我禁用了Xdebug,xhprof又导致PHP-FPM挂了,重新启用又好了。

  真是好奇怪的问题,不知道是什么原因造成的,暂时也没时间深究了。

附Xhprof的安装与使用方法:

XML/HTML代码
  1. [root@localhost ~]# tar -zxvf xhprof-0.9.4.tgz     
  2. [root@localhost ~]# cd xhprof-0.9.4/extension/    
  3. [root@localhost extension]# phpize    
  4. [root@localhost extension]# ./configure –with-php-config=/usr/local/php/bin/php-config    
  5. [root@localhost extension]# make    
  6. [root@localhost extension]# make install  

如果phpize执行不了,请先安装或者做链接:ln -s /usr/local/php/bin/phpize /usr/bin/phpize

在php.ini文件中,添加如下配置:

XML/HTML代码
  1. [xhprof]    
  2. extension=xhprof.so;    
  3. ; directory used by default implementation of the iXHProfRuns    
  4. ; interface (namely, the XHProfRuns_Default class) for storing    
  5. ; XHProf runs.    
  6. ;    
  7. ;xhprof.output_dir=<directory_for_storing_xhprof_runs>    
  8. xhprof.output_dir=/tmp/xhprof    

把xhprof-0.9.4目录下的目录xhprof_html 和 xhprof_lib 下的所有文件拷贝到你网站的主目录下

PHP代码
  1. <?php    
  2. //cpu: XHPROF_FLAGS_CPU    
  3. //内存: XHPROF_FLAGS_MEMORY    
  4. //如果都监控用XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY    
  5. xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);    
  6.     
  7. //这中间是需要性能分析的php代码  
  8.     
  9. //停止性能分析    
  10. $data = xhprof_disable();     
  11.   
  12. //显示性能分析数据    
  13. include_once "xhprof_lib/utils/xhprof_lib.php";     
  14. include_once "xhprof_lib/utils/xhprof_runs.php";     
  15. $objXhprofRun = new XHProfRuns_Default();     
  16.   
  17. //第一个参数 是xhprof_disable()的返回值    
  18. //第二个参数 是自定义命名空间字符串     
  19. //返回运行id,用这个id查看相关运行结果    
  20. $run_id = $objXhprofRun->save_run($data"xhprof");    
  21.   
  22. //查看运行结果的url    
  23. //run的值来源于save_run的返回值    
  24. //source值来源于save_run的第二个参数                                     
  25. //www.abc.com 需要用自己的域名替换    
  26. echo "<a href='http://www.abc.com/xhprof_html/index.php?run=".$run_id."&source=xhprof'>查看结果</a>";  

 

mysql主从同步配置

前两天配置了Mysql主从,再记录如下,以备下次查看。

 

主服务器设置

1、登录Master服务器,修改my.cnf,添加如下内容;
[mysqld]
server-id = 53 #//数据库ID号, 为1时表示为Master,其中master_id必须为1到232–1之间的一个正整数值;
log-bin=mysql-bin #//启用二进制日志;
binlog-do-db=dbname #//需要同步的二进制数据库名;
binlog-ignore-db=mysql /#/不同步的二进制数据库名;这个同步后听说很麻烦,不同步;
log-slave-updates #//把更新的记录写到二进制文件中;
slave-skip-errors=all #//跳过错误,继续执行复制;

2、建立同步用mysql账号,指定允许访问的IP为从服务器IP
mysql> #GRANT REPLICATION SLAVE,RELOAD,SUPER ON *.* to rslave@192.168.33.54 identified by '83ea4e19efe34874b50';
mysql> FLUSH PRIVILEGES;

到从服务器上验证登陆:
mysql -urslave -p83ea4e19efe34874b50 -h192.168.33.53

3、写锁定 flush tables with read lock;
4、导出数据mysqldump -uroot -p dbname > webdb.sql

从服务器设置

新版本与老版本的Mysql从服务器设置方式不一样,据说是以5.1.7版为分界线,具体请自己尝试。

老版本的Mysql配置文件[mysqld]后添加:
server-id = 54
log-bin=mysql-bin
master-host = 192.168.33.53
master-user = rslave
master-password = 83ea4e19efe34874b50
master-port = 3306
master-connect-retry=60 #//如果发现主服务器断线,重新连接的时间差
replicate-ignore-db=mysql #//不需要备份的数据库;
replicate-do-db=dbname #//需要备份的数据库
log-slave-update
slave-skip-errors = all #//跳过错误,继续执行复制;

重启Mysql服务后执行:
mysql> start slave;

新版本的Mysql配置文件[mysqld]后添加:
server-id = 61
log-bin=mysql-bin

并执行下面命令:(每次重启都要重新配置)
mysql> stop slave;
mysql> change master to master_host='192.168.33.53',master_user='rslave',master_password='83ea4e19efe34874b50';
mysql> start slave;

 

验证设置是否正确:
mysql> show slave statusG;
主要是看以下两项是否为YES:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

ssh连接速度很慢的解决方法

问题现象:

公司有几台服务器,SSH连接的时候很慢,半天才连接上,连上后一切操作正常,网络速度没问题。

处理方法:

用命令:ssh -v 服务器IP或者域名

参数v能显示连接过程中的一系列步骤,看看在哪一步完成后卡得比较久,就是那一步出问题了。

发现卡得比较久的有

XML/HTML代码
  1. debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password  
  2. debug1: Next authentication method: gssapi-keyex  
  3. debug1: No valid Key exchange context  
  4. debug1: Next authentication method: gssapi-with-mic  

说明卡在了尝试gssapi认证过程上,编辑服务器上的SSH配置文件

vi /etc/ssh/sshd_config

将#GSSAPIAuthentication no这一行前面的#号删除,同时在GSSAPIAuthentication yes这行前面加上#号,禁用gssapi认证。

重启SSH服务:service sshd restart

再次连接,发现还是有点慢,但是比之前快了一些,继续用ssh -v 跟踪,卡在这:

XML/HTML代码
  1. debug1: Authentications that can continue: publickey,password  
  2. debug1: Next authentication method: publickey  

这是因为服务器要将客户机的IP解析成域名,再次编辑SSH配置文件,将

#UseDNS yes

这行改成

UseDNS no

重启SSH服务,再次连接,终于是飞一般的感觉。

 

Ajax返回结果中文乱码的解决办法

情景:用JQuery的Ajax调用他站接口查询数据。

代码:

Javascript代码
  1. $.getJSON(  
  2.     $strurl + "/fwqueryjson.asp?callback=?",  
  3.     { FwCode: $FwCode.val() },  
  4.     function(data) {$CheckResult.html(data.QueryResult);}  
  5. );  

现象:返回的结果里的中文是乱码,英文与数字正常。

原因:本地是UTF-8编码,他站是GB2312编码,请求时默认以本地编码发起请求,与远端不一致,导致乱码。

解决:先指定Ajax请求的编码,代码如下

Javascript代码
  1. $.ajaxSetup({ scriptCharset: "gb2312" , contentType: "application/json; charset=gb2312"});  

 

各种SSH终端软件对比

Xshell

收费软件

ssh secure shell

免费软件

secureCRT

Secure[1] CRT是一款支持SSH(SSH1和SSH2)的终端仿真程序,简单的说是Windows下登录UNIX或Linux服务器主机的软件。SecureCRT支持SSH,同时支持Telnet和rlogin协议。SecureCRT是一款用于连接运行包括Windows、UNIX和VMS的理想工具。通过使用内含的VCP命令行程序可以进行加密文件的传输。有流行CRTTelnet客户机的所有特点,包括:自动注册、对不同主机保持不同的特性、打印功能、颜色设置、可变屏幕尺寸、用户定义的键位图和优良的VT100,VT102,VT220和ANSI竞争.能从命令行中运行或从浏览器中运行.其它特点包括文本手稿、易于使用的工具条、用户的键位图编辑器、可定制的ANSI颜色等.SecureCRT的SSH协议支持DES,3DES和RC4密码和密码与RSA鉴别。

SecureCRT也是一个收费软件

PuTTY

Putty是一个免费的、Windows 32平台下的telnet、rlogin和ssh客户端,但是功能丝毫不逊色于商业的telnet类工具。
用它来远程管理Linux十分好用,其主要优点如下:
◆ 完全免费;
◆ 支持公钥认证;
◆ 全面支持ssh1和ssh2;
◆ 绿色软件,无需安装,下载后在桌面建个快捷方式即可使用;
◆ 体积很小,仅484KB(0.63 版本);
◆ 操作简单,所有的操作都在一个控制面板中实现。