• 2009-09-22

    用nginx的反向代理做负载均衡 - [service]

    1. ngnix之所以比apache高效,得益于Nginx使用了最新的epoll(Linux 2.6内核)和kqueue(freebsd)网络I/O模型,而Apache则使用的是传统的select模型。目前Linux下能够承受高并发访问的 Squid、Memcached都采用的是epoll网络I/O模型。也就是说,在高并发服务器中,轮询(round-robin)I/O是最耗时间的操作。

    2. 反向代理工作原理
    反向代理服务器位于本地WEB服务器和Internet之间.
    当用户浏览器发出一个HTTP请求时,通过域名解析将请求定向到反向代理服务器(如果要实现多个WEB服务器的反向代理,需要将多个WEB服务 器的域名都指向反向代理服务器)。由反向代理服务器处理器请求。反向代理一般只缓存可缓冲的数据(比如html网页和图片等),而一些CGI脚本程序或者 ASP之类的程序不缓存。它根据从WEB服务器返回的HTTP头标记来缓冲静态页面。有四个最重要HTTP头标记:

    Last-Modified: 告诉反向代理页面什么时间被修改
    Expires: 告诉反向代理页面什么时间应该从缓冲区中删除
    Cache-Control: 告诉反向代理页面是否应该被缓冲
    Pragma: 告诉反向代理页面是否应该被缓冲.
    例如:在默认情况下,ASP页面返回” Cache-control: private.” ,所以ASP页面时不会在反向代理服务器缓存的。

    ----------------------------------------------------------------------------------

    3. ngnix最常见的用法之一就是作为反向代理使用,安装和配置相当简便,对于负载均衡它使用的是最简单的轮询算法(round-robin),不过效果还是很不错的。

    要用nginx做负载均衡的话,首先要在配置文件里面定义一组用来负载均衡的后端服务器(backend servers),例如:
    upstream backend {
      server 192.168.1.11;
      server 192.168.1.12;
      server 192.168.1.13;
    }

    那个server指令的语法是 server name [parameters],这里的name是服务器名,可以是域名、ip或者unix socket,也可以指定端口,例如:
    server 192.168.1.11:8080;

    server指令可用的参数有:

    weight —— 设置服务器的权重,默认值是1,权重值越大那么该服务器被访问到的几率就越大,例如 server 192.168.1.11 weight=5;

    max_fails和fail_timeout —— 这俩是关联的,如果某台服务器在fail_timeout时间内出现了max_fails次连接失败,那么nginx就会认为那个服务器已经挂掉,从而在 fail_timeout时间内不再去查询它,fail_timeout的默认值是10s,max_fails的默认值是1(这意味着一发生错误就认为服 务器挂掉),如果把max_fails设为0则表示把这个检查取消。
    举个例子:server 192.168.1.11 max_fails=3 fail_timeout=30s; 这表示,如果服务器192.168.1.11在30秒内出现了3次错误,那么就认为这个服务器工作不正常,从而在接下来的30秒内nginx不再去访问这个服务器。

    down —— 表示该服务器已经停用,例如server 192.168.1.11 down;

    backup —— 表示该服务器是备用服务器,只有其它后端服务器都挂了或者很忙才会访问到。

    关于upstream的更多信息请参考 http://wiki.nginx.org/NginxHttpUpstreamModule

    定义好了一组后端服务器,就该来设置nginx的反向代理配置了,例如:
    server {
      listen 80;
      server_name www.domain.com;
      location / {
        proxy_pass http://backend;
      }
    }

    关于nginx的proxy有很多配置参数的,具体可以参考 http://wiki.nginx.org/NginxHttpProxyModule
    这里有个配置可能比较有用:
    proxy_set_header Host $host;
    这表示传递给后端服务器的头部信息里面的Host信息保持跟客户端传过来的一致,如果不设置那么默认传给后端服务器的值是$proxy_host,所以不 设置可能会有问题,例如:后端服务器会处理两个域名的请求,例如www.a.com和www.b.com,这时如果nginx不把客户端的请求信息中的 host信息传给后端服务器,那么后端服务器完全不知道到底这个客户是想访问域名a还是域名b,从而导致传输数据可能不正确。
    如果你想把客户端的ip也传给后端服务器的话,可以用这个设置:
    proxy_set_header X-Real-IP $remote_addr;

    4. 负载均衡
    参考:http://blog.s135.com/nginx_php_v5/
  • 2009-09-14

    http_load 一个httpd 压力测试工具 - [service]

    到http://www.acme.com/software/http_load/ 下载http_load ,安装也很简单直接make;make instlall 就行。

    http_load的标准的两个例子是:

    1. http_load -parallel 5 -fetches 1000 urls.txt  
    2. http_load -rate 2 -seconds 300 urls.txt  

     

    例子只是个参考,参数其实可以自由组合,参数之间的选择并没有什么限制。比如你写成http_load -parallel 5 -seconds 300 urls.txt也是可以的。我们把参数给大家简单说明一下。-parallel 简写-p 含义是并发的用户进程数。

    -fetches 简写-f 含义是总计的访问次数

    -rate    简写-p 含义是每秒的访问频率

    -seconds简写-s 含义是总计的访问时间


    urls.txt 是一个url 列表,每个url 单独的一行。当然也可以直接跟一个url 而不是url 列表文件。
    实例:
    1. http_load -rate 5 -seconds 10 urls  
    2. 49 fetches, 2 max parallel, 289884 bytes, in 10.0148 seconds  
    3. 5916 mean bytes/connection  
    4. 4.89274 fetches/sec, 28945.5 bytes/sec  
    5. msecs/connect: 28.8932 mean, 44.243 max, 24.488 min  
    6. msecs/first-response: 63.5362 mean, 81.624 max, 57.803 min  
    7. HTTP response codes:  
    8.   code 200 -- 49  
     
    分析:
    1.49 fetches, 2 max parallel, 289884 bytes, in 10.0148 seconds
    说明在上面的测试中运行了49个请求,最大的并发进程数是2,总计传输的数据是289884bytes,运行的时间是10.0148秒

    2.5916 mean bytes/connection
    说明每一连接平均传输的数据量289884/49=5916

    3.4.89274 fetches/sec, 28945.5 bytes/sec
    说明每秒的响应请求为4.89274,每秒传递的数据为28945.5 bytes/sec

    4.msecs/connect: 28.8932 mean, 44.243 max, 24.488 min
    说明每连接的平均响应时间是28.8932 msecs,最大的响应时间44.243 msecs,最小的响应时间24.488 msecs

    5.msecs/first-response: 63.5362 mean, 81.624 max, 57.803 min

     6、HTTP response codes: code 200 -- 49
    说明打开响应页面的类型,如果403的类型过多,那可能要注意是否系统遇到了瓶颈。
    特殊说明:这里,我们一般会关注到的指标是fetches/sec、msecs/connect
    他们分别对应的常用性能指标参数Qpt-每秒响应用户数和response time,每连接响应用户时间。测试的结果主要也是看这两个值。当然仅有这两个指标并不能完成对性能的分析,我们还需要对服务器的cpu、men进行分析,才能得出结论
  • 2009-08-25

    Nginx中文参考资料!! - [service]

    http://code.google.com/p/nginxsrp/wiki/NginxCodeReview

    概述:
    Nginx
     ("engine x") 是一个高性能的 HTTP 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器
    Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的Rambler.ru 站点开发的,它已经在该站点运行超过四年多了。
    Igor 将源代码以类BSD许可证的形式发布。自Nginx 发布四年来,Nginx 已经因为它的稳定性、丰富的功能集
    、示例配置文件和低系统资源的消耗而闻名了。目前国内各大门户网站已经部署了Nginx
    如新浪、网易、腾讯等;国内几个重要的视频分享网站也部署了Nginx,如六房间、酷6等。
    新近发现Nginx 技术在国内日趋火热,越来越多的网站开始部署Nginx
    Tag:nginx
  • 2009-08-21

    中文全文搜索解决方案sphinx+mysql+mmseg,安装,配置,API调用 - [service]

    最近在研究中文搜索引擎,找了许多解决方案,有JAVA下的的Lucene,还有强大的C++下的fietex,哪些比较复杂,对现在的项目来讲,不是很实用,所以把目光瞄向了轻便的sphinx,今天安装还算顺利,以下备忘。
    首先,Sphinx默认不支持中文索引及检索,以前用补丁搞定,现在,写补丁那个项目组的人又弄了个CSFT,全称是:CoreSeek Fulltext Search Server,CoreSeek 全文检索服务器。于是呢,就把sphinx集成过来,挺好用的。

    1. 去Coreseek官网下载源码,需要mmseg和Coreseek Fulltext Server最好用源码安装,那个RPM文件包反正我没搞定,呵呵。
    2. 装mmseg。
          # tar zxf mmseg3_0b3.tar.gz
          # cd mmseg3_0b4;
          # ./configure –prefix=/Data/apps/mmseg
    (这个目录可以改)
          # make && make install
         运行mmseg,如果成功会有显示
         
    3. 装CSFT   
      # tar zxf csft3_0b4.tar.gz
          # cd csft3_0b3
          # ./configure -prefix=/Data/apps/sphinx  (这个需要mysql和mmseg,别把目录写错了)
          -with-mysql=/Data/apps/mysql        
          -with-mmseg=/Data/apps/mmseg
          -with-mmseg-includes=/Data/apps/mmseg/include/mmseg
          -with-mmseg-libs=/Data/apps/mmseg/lib/
          -with-mysql-includes=/Data/apps/mysql/include/mysql/
          -with-mysql-libs=/Data/apps/mysql/lib/mysql/
          # make && make install


    4. sphinx.conf
        安装完成后,会生成/Data/apps/sphinx/etc/sphinx.conf.dist  要更改为.conf
        #cp /Data/apps/sphinx/etc/sphinx.conf.dist /Data/apps/sphinx/etc/sphinx.conf
       
    5. 生成字典
        因为用到中文分词,需要生成字典,去安装目录,比如我的是 /home/changyou/mmseg.3.0b3/data/
        #mmseg -u unigram.txt 该命令执行后,将会产生一个名为unigram.txt.uni的文件,将该文件改名为uni.lib,完成词典的构造。
        然后,在/Data/apps/sphinx/var/下建立文件夹 dict,然后把uni.lib放进去
       
    6. 配置
        sphinx.conf 文件中需要对charset_dictpath指定uni.lib的路径/Data/apps/sphinx/var/dict/
        还有连接mysql的信息,这个不用说了罢。
        这里有个参数对于中文用户要注意一下:
        charset_type
        字符集编码类型。可选选项,默认为“sbcs”。已知的值包括“sbcs”和“utf-8”。
        对于中文用户,可选的值还可以有“zh_cn.utf-8 ”和“zh_cn.gbk”。当设置charset_type值为上面的两种时,系统默认您开启了中文分词特性。
        但是我设置了zh_cn.utf-8,报错说“unknown charset type 'zh_cn.utf-8'”,不知道为什么。。。。。

    7. 运行
         # /Data/apps/sphinx/bin/indexer
         启动索引服务时,如果报下面的错:
         error while loading shared libraries: libmysqlclient.so.15: cannot open shared object file: No such file or directory
         原因应该是因为mysql的lib文件不在系统的lib搜索路径上导致的。
         运行命令,解决:
         # ln -s /Data/apps/mysql/lib/mysql/libmysqlclient.so.15 /usr/lib/libmysqlclient.so.15
         
    8. 导入测试数据
         # mysql -uroot -p test < /Data/apps/sphinx/etc/example.sql
         这里千万注意,mysql编码一定要为UTF-8 !!!
        
    9. 测试建立索引
         #indexer --all
         出错,Coreseek Full Text Server 3.1
         Copyright (c) 2006-2008 coreseek.com
         FATAL: no readable config file (looked in /usr/local/sphinx/etc/csft.conf, ./csft.conf)
         这是因为 Coreseek 默认要去读 csft.conf,所以要复制一份
         # cp /Data/apps/sphinx/etc/sphinx.conf /Data/apps/sphinx/bin/csft.conf
         ( 或者,也可以指定conf文件,#indexer --config /Data/apps/sphinx/etc/sphinx.conf --all  这里我没有指定,所以用了2个conf文件,很不靠谱)

    10. 然后继续运行 #indexer --all ,应该会看到如下输出:
            Coreseek Full Text Server 2.1
            Copyright (c) 2006-2008 coreseek.com
            using config file '/usr/local/etc/csft.conf'...
            indexing index 'test1'...
            collected 5 docs, 0.0 MB
            sorted 0.0 Mhits, 100.0% done
            total 5 docs, 230 bytes
            total 0.146 sec, 1577.50 bytes/sec, 34.29 docs/sec
            indexing index 'test1stemmed'...
            collected 5 docs, 0.0 MB
            sorted 0.0 Mhits, 100.0% done
            total 5 docs, 230 bytes
            total 0.011 sec, 21879.74 bytes/sec, 475.65 docs/sec

    11. 测试全文检索
        # search doc     应该会看到如下输出:
            Coreseek Full Text Server 3.1
             Copyright (c) 2006-2008 coreseek.com
            using config file './csft.conf'...
            index 'test1': query 'doc ': returned 2 matches of 2 total in 0.000 sec
            
            displaying matches:
            1. document=3, weight=1, group_id=2, date_added=Sat Aug 22 03:54:19 2009
                    id=3
                    group_id=2
                    group_id2=7
                    date_added=2009-08-22 03:54:19
                    title=another doc
                    content=this is another group
            2. document=4, weight=1, group_id=2, date_added=Sat Aug 22 03:54:19 2009
                    id=4
                    group_id=2
                    group_id2=8
                    date_added=2009-08-22 03:54:19
                    title=doc number four
                    content=this is to test groups
            words:
            1. 'doc': 2 documents, 2 hits
            index 'test1stemmed': query 'doc ': returned 2 matches of 2 total in 0.000 sec
            displaying matches:
            1. document=3, weight=1, group_id=2, date_added=Sat Aug 22 03:54:19 2009
                    id=3
                    group_id=2
                    group_id2=7
                    date_added=2009-08-22 03:54:19
                    title=another doc
                    content=this is another group
            2. document=4, weight=1, group_id=2, date_added=Sat Aug 22 03:54:19 2009
                    id=4
                    group_id=2
                    group_id2=8
                    date_added=2009-08-22 03:54:19
                    title=doc number four
                    content=this is to test groups
            words:

            1. 'doc': 2 documents, 2 hits
    12. 启动searchd进程
         # searchd

    PHP接口在源安装包下面的api/下,可以调用测试,很好用,明天继续研究!

    接上一回,调用sphinx,我们先插入一个中文的数据:
    INSERT INTO `test`.`documents` (`id` ,`group_id` ,`group_id2` ,`date_added` ,title` ,`content`)VALUES (NULL , '3', '9', NOW( ) ,'sphinx中文搜索','Sphinx是一个基于SQL的全文检索引擎,可以结合MySQL,PostgreSQL做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。Sphinx特别为一些脚本语言设计搜索API接口,如 PHP,Python,Perl,Ruby等,同时为 MySQL也设计了一个存储引擎插件');

    因为有新数据,所以要重建索引(关于这个问题,以后遇到再研究,如果每天有新数据都要重建索引,很不靠谱)
    先kill searchd进程,运行:
    # searchd --stop    然后
    # indexer --all

    1.调用sphinx:
       一是通过Sphinx官方提供的API接口(接口有Python,Java,Php三种版本)
       二是通过安装SphinxSE(具体见1.2部分),然后创建一个中介sphinxSE类型的表,再通过执行特定的SQL语句实现。
    现在,我们用API接口,在sphinx安装目录有一个API目录,里面有三个PHP文件:test.php,test2.php和 sphinxapi.php。 sphinxapi.php是sphinx调用接口封装文件,test.php是一个在命令行下执行的查询例子文件,test2.php是一个生成摘要的例子文件。
    运行:
    # php /home/changyou/csft-3.1/api/test.php -i test1 doc
    返回结果:
    Query 'doc ' retrieved 2 of 2 matches in 0.000 sec.
    Query stats:  'doc' found 2 times in 2 documents
    Matches:
    1. doc_id=3, weight=100, group_id=2, date_added=2009-08-22 03:54:19
    2. doc_id=4, weight=100, group_id=2, date_added=2009-08-22 03:54:19

    注意:这里,如果不输入参数 -i test1 doc ,那test.php就不会知道你要查那个索引并且搜索什么字句。
    所以,如果想引入生产环境中,我们需要手动修改一下test.php

    a.  注释掉10行-43行,
    b.  然后添加:$search_info = array("1" => "-i", "2" => "test1", "3" => "$keyword");
    c.  foreach ( $search_info as $arg ) 替换原来的foreach
    d.  自己定义下$keyword="设计",记得把文件另存为utf-8
    e.   然后,运行:     # php /home/changyou/csft-3.1/api/test.php
       Query '(乱码)' retrieved 1 of 1 matches in 0.000 sec.
       Query stats:
        '(乱码)' found 8 times in 1 documents
    Matches:
    1. doc_id=5, weight=2, group_id=3, date_added=2009-08-26 20:18:33

    哈哈,OK啦!可以将sphinx文件封装好,就可以用与生产环境了。

    从上面可以看出Query并不能全部取得我们想要的记录内容,比如说Title,Contents字段就没有取出来,根据官方的说明是sphinx 并没有连到mysql去取记录,只是根据它自己的索引内容进行计算,因此如果想用sphinxAPI去取得我们想要的记录,还必须将Query的结果为依据去查询MySQL才可以得到最终我们想要的结果集。

    2.搜索全文时的摘要,高亮显示。
    假设我要搜索关键词"test",通过sphinx可以取到搜索结果,在显示搜索结果时,我希望将含有"test"的进行红色或加粗显示,同时,我不希望全部都显示出来,只需要显示一段摘要,就象google或百度那样,搜出来的结果不是全篇显示,只是部分显示,这个就是摘要的作用。
    以test2.php中为例,可以利用BuildExcerpts方法可以实现摘要的功能。具体可以看看test2.php的代码。这里不说了。

    3.后记
    从网上看到,还可以用SphinxSE方式调用Sphinx。但问题是,我安装的时候,不知道为什么没有安装SphinxSE引擎,在mysql 里用mysql> show engine; 查看。可能是我没有直接编译sphinx然后打2个中文补丁吧,而是用了官网推荐的中文搜索安装包。从索引得到ID号,然后再去查询数据库,也可以实现中文搜索的效果,但是具体效率怎么样就不知道了。
    最后,在sphinx配置文件里,如要用自己的数据,需要修改源数据,这一项:sql_query = \SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content \ FROM documents;
    让他自己抓取合适你数据结构的语句即可。

    参考:http://blog.c1gstudio.com/archives/722
            http://www.zhengjinjun.com/index.php/2009/06/28/sphinxmysql%E4%B8%AD%E6%96%87%E5%88%86%E8%AF%8D%E5%AE%89%E8%A3%85-%E5%AE%9E%E7%8E%B0%E4%B8%AD%E6%96%87%E5%85%A8%E6%96%87%E6%90%9C%E7%B4%A2/
            http://www.htmldata.cn/?p=171

     

  • 2009-04-25

    分布式服务器,查看各台服务器网页内容 - [service]

    /************************
    * 函数用途:同一域名对应多个IP时,获取指定服务器的远程网页内容
    * 创建时间:2008-12-09
    * 参数说明:
    *    $ip   服务器的IP地址
    *    $host   服务器的host名称
    *    $url   服务器的URL地址(不含域名)
    * 返回值:
    *    获取到的远程网页内容
    *    false   访问远程网页失败
    ************************/
    function HttpVisit($ip, $host, $url)  
    {  
       $fp = fsockopen ($ip, 80);
       if (!$fp)  
       {  
            return $erro=$ip." cant connected!!";  
       }  
       else  
       {  
           $out = "GET {$url} HTTP/1.1\r\n";
           $out .= "Host:{$host}\r\n";  
           $out .= "Connection: close\r\n\r\n";
           fputs ($fp, $out);  
           while($line = fread($fp, 4096))
           {
              $response .= $line;
           }
           fclose( $fp );

           //去掉Header头信息
           $pos = strpos($response, "\r\n\r\n");
           $response = substr($response, $pos + 4);
       
           return $response;  
       }  
    }
    //调用方法:
    $server_info1 = HttpVisit("60.28.209.250", "my.molihe.com", "index.php");
    $server_info2 = HttpVisit("60.28.209.245", "my.molihe.com", "index.php");
    $server_info3 = HttpVisit("60.28.209.221", "my.molihe.com", "index.php");
    ?>

    Tag:php linux
  • 2009-02-26

    解决Apache2+PHP上传文件大小限制的问题 - [service]

    在php.ini里面可以设置最大上传文件大小

    解决方法:
    第一:
    在php.ini里面查看如下行:
    upload_max_filesize = 8M
    post_max_size = 10M
    memory_limit = 20M


    另外要确认上传的 <form> 里类似下面的这行

    <input type="hidden" name="MAX_FILE_SIZE" value="500000">

    第二:

    如果是apache 2 需要修改
    /etc/httpd/conf.d/php.conf
    中的LimitRequestBody 524288将524288(=512×1024)改大,比如5M(=5×1024×1024)

    Tag:php linux Apach