分页: 3/11 第一页 上页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]
nginx配合codeIgniter有点麻烦,没有apache和lighttpd那么简单。

$HTTP["host"] == "www.aslibra.com" {
  server.document-root = "/path/to/www.aslibra.com/"
  url.rewrite = (
    "^/static/.*$" => "$0",
    "^/(.*)$" => "index.php/$1"
  )
  fastcgi.server = ( ".php" =>
    ( "weibo"=>( "host" => "127.0.0.1","port" => 9000) )
  )
}


在apache和lighttpd里面,判断 /index.php/sth 时,如果 /index.php是一个文件,就不会当做是文件路径了

我们可以这样简单的把某些路径rewrite,达到一样的效果:
1 保持地址格式是 /index.php/control/model
2 不产生404错误或者是no input的情况

server {
  index index.php index.htm;
  server_name  www.aslibra.com;
  root    /Data/webapps/www.aslibra.com;

  location /book/ {
    if (!-e $request_filename) {
      rewrite ^/book/(.*)$ /book/index.php/$1 last;
    }
  }
  location /book/index.php {
    fastcgi_pass   127.0.0.1:9000;
    include        fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME    /Data/webapps/www.aslibra.com/book/index.php;
  }
}


我们还需要避免类似以下地址异常:

/book/?test 404 查询字符会查找test的control
/book/&test 错误 The URI you submitted has disallowed characters.

总体而言,是查询字符的问题,我们可以有两种方式处理:

方式一:在codeIgniter处理之前避免

我们定义系统使用REQUEST_URI来处理mvc参数,不修改系统的文件,我们修改自定义的文件

文件 application/config/config.php
指定为REQUEST_URI方式处理,不是用auto,auto方式会判断查询字符

| 'AUTO'      Default - auto detects
| 'PATH_INFO'    Uses the PATH_INFO
| 'QUERY_STRING'  Uses the QUERY_STRING
| 'REQUEST_URI'    Uses the REQUEST_URI
| 'ORIG_PATH_INFO'  Uses the ORIG_PATH_INFO
|
*/
$config['uri_protocol']  = "REQUEST_URI";


文件 index.php
我们可以直接砍掉查询字符,保证参数不受影响

//处理查询字符
$url = explode('?', $_SERVER['REQUEST_URI']);
$url = explode('&', $url[0]);
$_SERVER['REQUEST_URI'] = $url[0];

/*
|---------------------------------------------------------------
| LOAD THE FRONT CONTROLLER
|---------------------------------------------------------------
|
| And away we go...
|
*/
require_once BASEPATH.'codeigniter/CodeIgniter'.EXT;


方式二:发生错误之后调整

发生404错误时,我们自动跳转到相应的地址,比如去掉后面 ?xxxx 和 &xxxx

文件 application/errors/error_404.php

<?php
$url = explode('?', $_SERVER['REQUEST_URI']);
$url = explode('&', $url[0]);
if($url[0] != $_SERVER['REQUEST_URI']){
  echo "<meta http-equiv=\"refresh\" content=\"0;url=$url[0]\">";
}
?>
</head>


在 error_general.php 里也可以这样加一样的代码。

参考资料:

1 不错的nginx配置方式,本文有参考: CodeIgniter Nginx Rewrite Rule
2 CodeIgniter URLs & Nginx
3 lighttpd rewrite rule && apache mod_rewrite
分享一段代码,平时在使用的
// code from http://www.aslibra.com/
// by hqlulu
// replace <img (any code) src="(pic url)">
// to <img src="(pic url)">

function parse_img ( $content ) {
  preg_match_all ("/<img[^>]+src=\"(.+)\"[^>]*>/isU",
    $content,
    $out, PREG_PATTERN_ORDER);

  foreach($out[1] as $k=>$v){
    $content = str_replace($out[0][$k], '<img src="'.$out[1][$k].'">', $content);
  }

  return $content;
}


清理img标签里的其它属性,保留src,如果要清理别的,自行修改即可
Tags:
codeIgniter我用过一下,觉得比较的理想,很适合做开发,一个很小巧的php的MVC框架。
由于是一个框架模式,所以样例代码拿过来是很容易看清楚程序架构的,也很容易参考,这比自己写的程序要好很多,至少你很容易找到每个代码的功能和位置。

碰到一个问题:

apache里面可以这样做rewrite

<VirtualHost *:80>
    ServerName    www.aslibra.com
    DocumentRoot  F:\WebsiteLocal\www.aslibra.com
    RewriteEngine On
    RewriteRule   ^/(topic|user)  /index.php$0
    #RewriteRule   ^/(topic|user)  /index.php?$0
</VirtualHost>


两种写法都可以让index.php处理此链接,而第一种是最好的,用户输入查询也没事,比如 /topic?test=ds
第二种写法就不行了,会出现错误,地址匹配有特殊字符
但对于nginx的服务器,是不能那样写的,如果按第一种写法,会出现404错误,当作目录了
如果是lighttpd,那应该和apache类似,没有问题。

location ~^/(topic|user) {
        rewrite ^/(.*)  /index.php?/$1 last;
}


出现的错误是:

引用
An Error Was Encountered
The URI you submitted has disallowed characters.


出自(系统库文件URI.php):

function _filter_uri($str)
{
  if ($str != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE)
  {
    // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards
    // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern
    if ( ! preg_match("|^[".str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-'))."]+$|i", $str))
    {
      show_error('The URI you submitted has disallowed characters.', 400);
    }
  }

  // Convert programatic characters to entities
  $bad  = array('$',     '(',     ')',     '%28',     '%29');
  $good  = array('&#36;',  '&#40;',  '&#41;',  '&#40;',  '&#41;');

  return str_replace($bad, $good, $str);
}


看代码,我们可以设置config里面 enable_query_strings 为TRUE
这次会得到什么结果:

引用
404 Page Not Found
The page you requested was not found.


这说明已经过了检查地址,到了路由这一部分了,这个错误是找不到相应的class/method所导致的
重要的URI处理是在 _fetch_uri_string 函数里面,调用这个过滤器是在路由控制里面:

从Router.php里面找到(大概90行)

// Fetch the complete URI string
$this->uri->_fetch_uri_string();
echo $this->uri->uri_string."<hr>"; //检查


我们可以看到路由取出来的地址是什么,比较两种方式
设置为:

$config['uri_protocol']  = "AUTO";
$config['enable_query_strings'] = TRUE;


测试地址为: /topic/test?site=aslibra.com
理想状态应该是进入 /topic/test

第一种情况,取得的uri为 site,这错的比较离谱
第二种为 /topic,检查server变量
引用
[QUERY_STRING] => /topic
    [REQUEST_URI] => /topic/test/?site=aslibra.com
    [SCRIPT_NAME] => /topic/test/
    [PHP_SELF] => /topic/test/
    [REQUEST_TIME] => 1259512731
    [argv] => Array
        (
            [0] => /topic
        )

    [argc] => 1
)


都发生了错误,修改auto为REQUEST_URI应该可以有救
对于这个是支持,因为有正常的class和method,但如果是一级参数,那就出错了,比如
/topic/?site=aslibra.com

这种情况最好的解决办法是钩子处理,在系统开始的时候把查询字符都忽略了
或者,在index.php调用CI之前,就去掉,比如

//code from http://aslibra.com/
$tmp = explode('?',$_SERVER['REQUEST_URI']);
$_SERVER['REQUEST_URI'] = $tmp[0];


钩子方式的解决办法:

//配置里 $config['enable_hooks'] = TRUE;

//config/hooks.php
$hook['pre_system'] = array(
                                'class'    => 'Uri',
                                'function' => 'fix',
                                'filename' => 'Uri.php',
                                'filepath' => 'hooks',
                                'params'   => ''
                                );


新建 hooks/Uri.php
<?php
//code from http://aslibra.com/
class Uri{
  
  function fix(){
    $tmp = explode('?',$_SERVER['REQUEST_URI']);
    $_SERVER['REQUEST_URI'] = $tmp[0];
  }
}
?>


那修改auto为REQUEST_URI应该可以,查询字符支持可以不支持了
要读写二进制文件,就需要用到pack和unpack了。
今天要处理一个二进制文件的问题,所以需要用一下,特意了解一下pack的用法,unpack用法类似了吧,没看 \(^o^)/~

先通俗的理解一下,就是给一个目标格式,和相应的参数,就可以返回二进制数据给你了。
先举例说明,四个整数:

pack("L4", 0,1,2,3)
pack("LLLL", 0,1,2,3)
pack("L", 0).pack("L", 1).pack("L", 2).pack("L", 3)

上面的结果是一样的,也就是说,format是描述后面的数据的格式。
具体format可以用什么,那看format characters就知道了。
比如一个30字符的 pack("a30", "http://www.aslibra.com") ,就是这个意思,很简单

pack函数的声明:
Tags:
一直有想到是否该用wordpress玩玩blog,因为实在是有欣赏的地方,当然了,转换肯定也需要精力,还好转换程序有热心网友提供给大家用:

Bo-blog to WordPress 转换程序 v2.0 build.20090415

升级到新版2.8有bug:
1 转换友情链接,字段不一样导致出错
不熟悉wordpress,暂时注释掉几行,276/288/289
2 日志字段有更改,查找替换 post_category -> post_parent

在本地转换后打开首页,发现程序没跑完就停止了,失望。。
一直都感觉wordpress很慢,新安装好的时候都很慢很慢滴,烦死
打开xdebug看看结果,感觉真的是一份失望的php程序:

点击在新窗口中浏览此图片

调用程序居然有将近10万次的,不知道是否我的程序有什么问题,是否非官方版本而产生的问题
数据库都调用了几万次查询,我 ⊙﹏⊙b汗~~
30秒超时时间过去了,程序停止了,增加程序运行时间的结果:

Fatal error: Allowed memory size of 41943040 bytes exhausted (tried to allocate 2097152 bytes) in F:\MyWebsite\wordpress\wp-includes\post.php on line 3398
Call Stack
# Time Memory Function Location
1 0.0303 61008 {main}( ) ..\index.php:0
2 0.0309 65024 require( 'F:\MyWebsite\wordpress\wp-blog-header.php' ) ..\index.php:18
3 2.6930 17547624 require_once( 'F:\MyWebsite\wordpress\wp-includes\template-loader.php' ) ..\wp-blog-header.php:16
4 2.6980 17569792 include( 'F:\MyWebsite\wordpress\wp-content\themes\classic\index.php' ) ..\template-loader.php:27
。。。
Tags: ,
memcachedb和memcached的两个主要区别:
1 前者不管理过期,每个存储都是长期有效
2 前者使用磁盘存储,有广阔的存储空间

这两个优点使得很多缓存的地方可以使用上memcachedb。

1 本地数据缓存
这个带来的最大便利是可以实现数据共享,备份简便,这是本地文件缓存无法比拟的。
2 网页缓存
在Nginx可以使用memcache接口,很简便的实现网页cache

以上两项应用需要解决过期问题方式不同:

1 对于本地数据缓存,可以再保存一个值是当前保存的数据的时间即可。
类似读写文件一样,记录修改时的时间戳
$key=>"http://www.aslibra.com/"
$key."_time"=>time()


2 对于nginx无法判断是否过期的情况,可以实现自动清理,阿权设计方案的是按秒存储数据,定期清理
清理的方法决定了保存的其它数据的方式,你也可以写入文件日志的方式,然后按日志清理
这里用自身的存储,记录相应的数据信息
$key=>"http://www.aslibra.com/"
$key2=>"http://www.aslibra.com/blog/"
$expire_time=>Num
$expire_time.'_'.Num=>$key
$expire_time.'_'.Num2=>$key2


这个主要在解决$expire_time的自增的问题,细节可以处理此问题
需要用到increment和add,他们都有键值是否存在的问题,根据此功效解决冲突。
先尝试increment,如果成功,说明已经有了,否则可能没有。在没有的情况下,尝试添加此键值,成功说明此时没有同时的进程,否则有同时请求的进程已经在此短暂的不行的时间里添加了,那就再次调用increment即可。

下面是封装了的PHP代码:

<?

/****************************************
*** memcachedb_manage version 0.1 @ 2009-6-12
*** code by hqlulu#gmail.com
*** http://www.aslibra.com
*** http://code.google.com/p/memcachedb-manage/
*** http://code.google.com/p/memcachedb/
*** let the memcachedb acts like memcached!
****************************************/

class memcachedb extends Memcache{

  //是否有调试信息
  var $debug = false;
  //兼容使用memcache,这样就不用set时再保存额外数据
  var $is_memcachedb = true;
  //清理时间开始为0时,默认最小的清理时间差
  var $mini_clear_time = 86400;
  //临时数据前缀
  var $prefix = 'db_';
  //临时数据,清理的最后时间戳
  var $last_timeid_key = 'last_timeid';
  
  //本地处理缓存有效性
  var $cache_expire = 900;
  var $cache_prefix = 'WWW_FILE_';
  var $cache_time_prefix = 'WWW_TIME_';

  function memcachedb(){
  }
  
  //改写函数
  //此功能适合前端无法判断数据是否有效的情况,需要自行清理过期数据
  function set($key, $value, $flag=0, $expire=0){

    if($expire>0 && $this->is_memcachedb){
      $mykey = $this->prefix.(time() + $expire);
      //尝试取得自增值
      $i = parent::increment($mykey);
      if($i == FALSE){
        //尝试增加key,防止用set产生的冲突
        $i = parent::add($mykey,1) ? 1 : parent::increment($mykey);
      }
      parent::set($this->mykey($mykey, $i), $key);
    }

    return parent::set($key, $value, $flag, $expire);
  }

  //管理自增的键值组合方式
  function mykey($mykey, $i){
    return $mykey.'_'.$i;
  }

  //保存上次清理的时间戳的键值
  function last_timeid_key(){
    return $this->prefix.$this->last_timeid_key;
  }
  
  //清理
  function clear($start=0, $end=0){

    //取得上次清理的最后时间戳,可以不需要从time_start开始
    $last_timeid = parent::get($this->last_timeid_key());
    if($last_timeid == false) $last_timeid = 0;
    $start = $last_timeid>$start ? $last_timeid : $start;
    $start = $start>0 ? $start : ( time() - $this->mini_clear_time );
    $end = $end>0 ? $end : time();
    if($this->debug)echo " clear $start to $end <br>";

    for($mytime = $start; $mytime<=$end; $mytime++){
      $mykey = $this->prefix.$mytime;
      $auto_id = parent::get($mykey);
      if($auto_id){
        if($this->debug)echo "<hr>clear time: $mytime<br>";
        for($i = 1;$i<=$auto_id;$i++){
          $key = parent::get($this->mykey($mykey, $i));
          if($this->debug)echo " delete ".$k."<br>";
          parent::delete($key);
          if($this->debug)echo " delete ".$this->mykey($mykey, $i)."<br>";
          parent::delete($this->mykey($mykey, $i));
        }
        if($this->debug)echo " delete $mykey<br>";
        parent::delete($mykey);
      }
    }

    //记下当前处理过的时间戳
    $this->set($this->last_timeid_key(), $end);
  }

  //缓存读写
  //此功能适合PHP使用的数据,自行判断数据是否有效的情况
  function get_cache($key, $expire=0){
    $expire = $expire>0 ? $expire : 0;
    if($expire == 0)
      return parent::get($this->cache_prefix.$key);
    $cache_time = parent::get($this->cache_time_prefix.$key);
    $cache_time = $cache_time == FALSE ? 0 : $cache_time;
    if(time() - $cache_time <= $expire)
      return parent::get($this->cache_prefix.$key);
    return FALSE;
  }

  function set_cache($key, $value, $flag=0, $expire=0){
    $expire = $expire>=0 ? $expire : $this->cache_expire;
    parent::set($this->cache_time_prefix.$key, time());
    return parent::set($this->cache_prefix.$key, $value, $flag, $expire);
  }
}
?>


一些示例:

<?
require_once('memcachedb.class.php');

$m = new memcachedb;
$m->connect('192.168.1.5', 11311);

//保存一个300秒有效期的数据
$m->set('test','www.aslibra.com', 0, 300);
//清理到1000秒前到100秒前过期的数据
$m->clear(time()-1000, time()-100);

//获取一个键值,不理会是否过期,相当于get
echo $m->get_cache("test", 0);
//获取一个键值,300秒内保存的才有效
$m->get_cache("test", 300);
//保存一个数据,300秒内有效
$m->set_cache("test", "www.aslibra.com", 0, 300);
//保存一个数据,长期有效,相当于set
$m->set_cache("test", "www.aslibra.com");

//清理到目前已经过期是数据
$m->clear();
?>


相关资料:

1 memcachedb-manage
2 memcachedb
3 代码下载

代码更新:

# Non-members may check out a read-only working copy anonymously over HTTP.
svn checkout http://memcachedb-manage.googlecode.com/svn/trunk/ memcachedb-manage-read-only
本代码是从uchome的代码修改的,是因为要解决uchome的效率而处理的。
这个思维其实很久就有了,只是一直没有去做,相信也有人有同样的想法,如果有类似的,那真的希望提出相关的建议。
封装的方式比较简单,增加了只读数据库连接的接口扩展,不使用只读数据库也不影响原代码使用。
有待以后不断完善。。

为了方便,试试建立了google的一个项目:
http://code.google.com/p/mysql-rw-php/

希望给有需要的朋友带来帮助。

为什么需要读写分离?

主要是数据库压力过大的情况下的解决方案。写操作会把表锁定,而导致很多查询相继锁定而等候,导致程序处于等候状态。
读写分离是建立在mysql的replication基础上的,master服务器仅负责写操作,slave机器仅提供读操作,相对而言提高了读写性能,也可以增加mysql的承受能力。

PHP实现的Mysql读写分离

主要特性:

1 简单的读写分离
2 一个主数据库,可以添加更多的只读数据库
3 读写分离但不用担心某些特性不支持
4 缺点:同时连接两个数据库

英文比较烂,也写几个字吧

php code for mysql read/write split
feature:
simply rw split
one master,can add more slaves
support all mysql feature
link to the master and slave at the same time
Tags: ,
分页: 3/11 第一页 上页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]

阅读推荐

服务器相关推荐

开发相关推荐

应用软件推荐