OGX-3 | 妳木有小雞雞

死亡不是无知,而是不表态。

有意栽花花不開,無心插柳柳成蔭。

with one comment

在線人數大約在3000左右,用兩臺機器跑,在高峰時會出現連不了memcache的情況,以前只是11211端口佔用比較多,但昨天出現不能連memcache。老問題了,一直因為非常重要或者很重要的事情而放到出現問題才會解決(11211端口的問題在很久以前就提出)。

連接memcached的地方有兩處,session和DB Cache,我先試著改session:

  1. function open() {
  2. global $_memcache;
  3. $_memcache = memcache_pconnect(HOST,PORT);
  4. }
  5.  
  6. // session close
  7. function close() {
  8. global $_memcache;
  9. memcache_close($_memcache);
  10. }
  11.  
  12. // session gc
  13. function gc($key) {
  14. global $_memcache;
  15. memcache_close($_memcache);
  16. }
  17.  
  18. // session destroy
  19. function destroy($key) {
  20. global $_memcache;
  21. memcache_close($_memcache);
  22. }
  23.  
  24. // session read
  25. function read($key) {
  26. global $_memcache;
  27. $_memcache->get($key);
  28. }
  29.  
  30. // session write
  31. function write($key,$val) {
  32. global $_memcache;
  33. memcache_set($_memcache,$key,$val,0,SESSION_MAX_LIFTTIME);
  34. }
  35.  
  36. // 初始化
  37. function init()
  38. {
  39. ini_set(‘session.use_trans_sid’,0);
  40. ini_set(‘session.gc_maxlifetime’,SESSION_MAX_LIFTTIME);
  41. ini_set(‘session.use_cookies’, 1);
  42. ini_set(‘session.cookie_path’, ‘/’);
  43. ini_set(‘session.cookie_domain’,’.’.BASE_URL);
  44. session_module_name(‘user’);
  45.  
  46. session_set_save_handler(
  47. ‘open’,
  48. ‘close’,
  49. ‘read’,
  50. ‘write’,
  51. ‘destroy’,
  52. ‘gc’
  53. );
  54. session_start();
  55. }
  56.  
  57. init();

發現問題照舊,再改成:

  1. $_session_save_path = "tcp://192.XX.XX.XX:11211";
  2. ini_set(‘session.save_handler’, ‘memcache’);
  3. ini_set(‘session.save_path’, $_session_save_path);
  4. session_start();

還是一樣,眼看半天過去,問題都沒找到。看樣子問題不出在session,那就是db cache了,只有連接沒有斷開,不斷創建新的連接,才會有那麼多的端口被佔用,俺想到一個最簡單的辦法,設計模式的單例模式不就解決類似的問題嗎?

先看看單例模式的類圖:

  1. class Obj_Memcache {
  2. private static $_instance = null;
  3. private function __construct(){}
  4. private function __clone(){}
  5. public static function getInstance()
  6. {
  7. if (self::$_instance == null) {
  8. self::$_instance = new Memcache();
  9. self::$_instance->connect(CFG_DB_CACHE_HOST, CFG_DB_CACHE_PORT);
  10. }
  11. return self::$_instance;
  12. }
  13. }

找到實現cache的地方:

替換為:

  1. $this->Mem = Obj_Memcache::getInstance();

看看結果:

今天觀察看看,應該不是蓋的。。

Written by admin

八月 17th, 2010 at 3:33 下午

雷死人的hosts和resolv.conf

without comments

今天算是碰到怪事了,做的儲值模塊,因為代碼去抓取遠程資料庫的數據,在Server端已寫好api,直接調用就可以了。所以就用fsockopen來建立連接,問題出來了,不管怎麼寫,死活抓不到資料。

  1. if (!$_fp) {
  2.     throw new Exception($_error_msg.$_errorno."\n");
  3. }

一直提示

  1. Connection timed out 110

換成curl後還是不可以~在命令行下運行

  1. curl -G http://sub.domain.com/XX/xx/xx

出現couldn’t connect to host.

但是在內部的測試機卻是正常。就是說內部機訪問subdomain,dns可以正常解析,換服務器就不可以了。

在hosts中加入

  1. 192.X.X.X   sub.domain.com

指定ip後再試,ok了。

Written by admin

八月 16th, 2010 at 6:19 下午

整理的htc desire 大陆和香港间的差异

without comments

除了接口、htc 小工具、GPS,操作系统不一样,其他的都一样。

htc

Written by admin

七月 29th, 2010 at 8:21 上午

php5 iterator - 迭代器

with one comment

上一篇我提到php的spl(php 标准库),今天刚好又用到iterators,觉得非常方便。于是从网上找了一些资料,结合我蹩脚的能力写了下来。

先看看iterators有哪些内容:

图中有数组、文件、目录、对象和相对应实现递归的迭代器。拿数组说事:

  1. $_demo_arr = array(‘name’ => ‘OGX’, ‘sex’ => ‘B’, ‘age’ => ’100′, ‘color’ => ‘yellow’, 300);

正常我们来遍历数组:

  1. foreach ($_demo_arr AS $_key => $_val) {
  2.     echo $_key . ‘==’ .  $_val;
  3. }
  4.  
  5. //  或者
  6. while (list($_key,$_val) = @each($_demo_arr)) {
  7.     echo sprintf("%s == %s",$_key,$_val);
  8. }

结果如下:

同样的数组,我改为迭代器遍历,代码如下:

  1. $_obj_iterator = new ArrayIterator($_demo_arr);
  2. while ($_obj_iterator->valid()) {
  3.     echo "i’m iterator: \r\n";
  4.     echo sprintf("%s == %s",$_obj_iterator->key(),$_obj_iterator->current()) . "\r\n";
  5. }

结果如下:

当然,你可以使用别的iterator来实现你需要的功能,例如遍历目录、遍历对象等等。具体就不介绍了,也没能力写得更好。如有遗漏或者错误之处还请见谅。

Written by admin

七月 26th, 2010 at 10:40 下午

唠叨贴

without comments

上面说了php的异常处理,现在来骂一下吧!

php本来是弱类型的语言,所有的异常信息都要我们自己来定义,加上php5.2 和php5.3 对错误纪别处理也不一样,在php5.3下可以正常运行的代码,在php5.2下一直报错,或者白屏,毛都被qi没了。

更加弱质的是,参数前如果加了类型,php5.3会正常,php5.2就不行,况方法的参数数量不一样,也会报错。php5.2 接口的使用还不能完整的使用。

Written by admin

七月 23rd, 2010 at 1:16 上午

php异常处理

without comments

在开发中经常会碰到处理一些信息,提供给用户或者管理员。简单的直接输出就可以,如果遇到嵌套类中最内层的信息,就有些麻烦了,不得不直拉输出信息。

php5 引进异常处理,每当出的异常都会被catch语句块补获,并每一个 try必由一个catch来处理异常。

exception 是php标准的函数库,其定义如下:

  1. <?php
  2. class Exception
  3. {
  4.     protected $message = ‘Unknown exception’;   // 异常信息
  5.     protected $code = 0;                        // 用户自定义异常代码
  6.     protected $file;                            // 发生异常的文件名
  7.     protected $line;                            // 发生异常的代码行号
  8.  
  9.     function __construct($message = null, $code = 0);
  10.  
  11.     final function getMessage();                // 返回异常信息
  12.     final function getCode();                   // 返回异常代码
  13.     final function getFile();                   // 返回发生异常的文件名
  14.     final function getLine();                   // 返回发生异常的代码行号
  15.     final function getTrace();                  // backtrace() 数组
  16.     final function getTraceAsString();          // 已格成化成字符串的 getTrace() 信息
  17.  
  18.     /* 可重载的方法 */
  19.     function __toString();                       // 可输出的字符串
  20. }
  21. ?>

当我们要定义自己的异常处理类时,调用父类的构造函数,指定异常信息,如果要得到自己的字符串
信息,重载__toString()方法即可。因为默认输出的信息会比较全,我们不用让用户了解这些对他们来说没用的信息。

  1. class AppException extends Exception {
  2.     public function __construct($r_message,$r_code)
  3.     {
  4.         parent::__construct($r_message,$r_code);
  5.     }
  6.  
  7.     public function __toString()
  8.     {
  9.         return get_class($this).’XXXX’; //  这儿还可以定义信息
  10.     }
  11. }
  12.  
  13. class Demo {
  14.     public function examplException()
  15.     {
  16.         try {
  17.             $_variable = ‘abcd’;
  18.             if (!is_numeric($_variable)) {
  19.                 throw new AppException("XXXXX");
  20.             }
  21.         } catch (AppException $e) {
  22.             die($e->getMessage()); // 当然还可以做别的东东,比如打飞机
  23.         }
  24.     }
  25. }

但今天碰到一个情况,使用ajax调用,从内部类丢出的异常跟我想要的不一样。

  1. class AjaxException extends Exception {
  2.     public function __construct($r_message,$r_code)
  3.     {
  4.         parent::__construct($r_message,$r_code);
  5.     }
  6.  
  7.     public function getAjaxMessage()
  8.     {
  9.         return json_encode(array(‘status’ => $this->code,’error’ => $this->message));
  10.         // 对,我就是闲的蛋疼,想输出json格式的信息。
  11.     }
  12. }
  13.  
  14. class Demo {
  15.     public function examplException()
  16.     {
  17.         try {
  18.             $_variable = ‘abcd’;
  19.             if (!is_numeric($_variable)) {
  20.                 throw new AppException("XXXXX");
  21.             }
  22.             if (strlen($_variable) < 8) {
  23.                 throw new AjaxException("XXOO",400);
  24.             }
  25.         } catch (AppException $e) {
  26.             die($e->getMessage()); // 当然还可以做别的东东,比如打飞机
  27.         } catch (AjaxException $e) {
  28.             echo $e->getAjaxMessage();
  29.         }
  30.     }
  31. }

这样就可以使用自己定义的异常了,当然,好的地方不止这些。详细请看php的exception

当你用一阵时间后,你会发现方便很多。

Written by admin

七月 23rd, 2010 at 1:03 上午

ubuntu不支持ll 命令的解决办法

without comments

习惯使用ll命令~但再ubuntu下不支持。其实ll 就是 ls -l的一个别名。解决办法有二:

1、再当前用户目录创建bin目录,然后创建一个名为ll 的shell脚本实现ls -l,然后设定该shell脚本路径到系统变量。

  1. $ cat > ~/bin/ll
  2. #! /bin/sh
  3. # alias ll = ‘ls -l’
  4. ls -l
  5. ^D
  6.  
  7. chmod +x ~/bin/ll
  8. PATH=$PATH:$HOME/bin

现在试一下,搞定。
2、修改.bashrc文件,加入一句:alias ll=’ls -l’(或者把该句前面的注释去掉即可)。

Written by admin

七月 18th, 2010 at 2:55 下午

omg~pdo 数据抽象层 实例

with 19 comments


defined("DSN") OR define("DSN","mysql:dbname=text;127.0.0.1");
defined("DB_USER") OR define("DB_USER","root");
defined("DB_PASSWORD") OR define("DB_PASSWORD","");

/**
* 使用mysql的pdo驱动
*
* @author
* 单例模式
**/
class Db {

/**
* 类的实例
**/
private static $instance;

/**
* 构造函数,定义为私有防止类再外部被实例化
*
* @example
* $obj = new Db();
*
**/
private function __construct(){}

/**
* 定义为私有确保实例不被clone
**/
private function __clone(){}

/**
* 返回一个pdo的实例
*
**/
public static function getInstance()
{
try {
if (!self::$instance) {
self::$instance = new PDO(DSN,DB_USER,DB_PASSWORD);
self::$instance->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}
} catch (EXCEPTION $e) {
echo "connection failed!" . $e->getMessage();
die();
}
return self::$instance;
}

/**
* 通过db的实例来调用pdo的方法
*
* @param $r_method
* @param $r_arr_argument
* @return mix
**/
final public static function __callStatic($r_method,$r_arr_argument)
{
$_obj_instance = self::getInstance();
return call_user_func_array(array($_obj_instance,$r_method),$r_arr_argument);
}
}

实例:

try {
$_sql = "SELECT * FROM posts limit 10";
foreach (Db::query($_sql) AS $row) {
echo '

';
		print_r($row);
		echo '

';
}
}catch (Exception $e) {
echo $e->getMessage();
}

终于搞定简单版~接下来就是数据关系映射,然后是数据持久层。

Written by beiwei

六月 10th, 2010 at 3:36 上午

不关站升级数据库

with 2 comments

下面是infoq的计划,我认为除了计划,每一条都是值得我借鉴的。

比如说:准备工作,要让服务提供商知道详细内容。呃,这一点我就不说了。安全可控的关闭mysql,停止web服务,保证所有事务已经提交,设置mysql为只读。innodb引擎的转换,这里提到mysql的Per-Table Tablespaces –innodb-file-per-table 设置项,是因为innodb默认把数据跟索引文件分成不同的表空间存放,这也就是为什么不能直接拷贝data目录下的文件来备份innodb的原因。至于备份这mysql的官网有详细的资料 innodb-file-pre-table

接着就是主从,除了主从还是主从。具体就要看怎么去想更好的方案。嗯,就这样,睡觉。

Written by admin

六月 7th, 2010 at 12:58 上午

假想案例:不关站升级数据库

with one comment

前段时间莫哥提到升级数据库失败问题,因为他所负责的项目会比较复杂,并且在安全性上要求比较高。并且还有其他的一些原因(开发新功能、修复bug之类),后来不知有没有升级成功。今天看到infoq升级数据库的文章,收获颇丰。借鉴infoq的案例和总结的经验,我觉得也非常适合莫哥负责的项目。并且也给新成长的站点有了借鉴的地方。

先来看看infoq的经验:
1、有详细的计划。(这点非常重要)要涉及到方方面面的问题:线路、机器、人工以及可能突发的状况和状况发生时的应急预案。
2、变化。记得在head first系列书里面有提到软件开发最普遍的就是变化(change),这尤其也是我后来一直拿来安慰别人和自我安慰的一个词。
3、适应变化。这点是我加上去的,因为我们在处理碰到的问题时,往往有些人还要比我们更没有耐心和浮躁。他们往往会在你紧绷神经时来找茬或者捣乱。
4、节省系统调试的时间。这点我苟且暂时认同,因为毕竟我还没达到那种保证事情99%正确的境界。如果调试(测试)不能发现问题,就别指望我们的其他工作人员找到问题。根据我自己的经历,某些大的问题往往都是用户直接反馈给我们的。
5、积极寻求反馈。这点可能再国内或者tw市场有点困难。因为亚洲人(至少是中国人)已经习惯了出钱就是爷的思维意识。我们获得反馈信息的途径也很有限,无非就是网站留言、电话、邮件、msn(少量)等几种,不像infoq上所说的google group、twitter等。国内少有的类似twitter的网站都具有阉割和自我阉割的功能,google group已经被墙,我估计以后的网民甚至不知道有google group这样一说。当然,这些只限在中国大陆。

接下来要讲一下infoq在升级方案,未完待续。

Written by admin

六月 6th, 2010 at 8:58 下午