发布新日志

  • 测试用例

    2013-08-01 13:50:45

    测试界一直在流传着一句话就是测试用例是测试工程师价值的体现

    那怎么来设计测试用例呢,我来谈点自己的想法,我们知道测试用例里包含着很多要素,我认为最重要的要素是:

    1 前置条件:就是当你要做操作时,应该先具备什么条件

    2 数据:操作的数据样本

    3 操作步骤:操作的顺序

    4 预期结果:操作后一个或者多个的影响

    在分析需求时,我们可以先理清单个的功能点,业务规则,流程,然后把这些东西排列组合,其实就形成了测试用例。

    如果能把操作程序化,数据参数化,也就形成了qtp的自动化思路

    一家之言,大家共勉。
  • childnodes在ie和ff下的计算

    2012-03-30 14:46:57

    childnodes大家应该都知道,就是取一个元素的子元素,返回的是数组

    不过在ie和ff下计算出来的childnodes的个数是不一致的

    原因就是在ff下的时候,会把标签结束的空格和回车计算在内

    比如ff下
    <h1></h1><ul></ul>

    元素个数就是3个

    如果是这样的
    <h1></h1>
    <ul></ul>

    元素个数就是4个

    而在ie下就不会有这样的情况
  • sqlserver 数据导入导出

    2011-12-26 15:58:44

    今天想导一批文本数据到数据库里

    于是就用到了bcp和bulk insert

    bcp

    其实windows的自带工具,只不过用sql用cmdshell来调用而已

    但是sqlserver默认是关闭cmd_shell的,因为安全问题,所以使用时要先打开cmdshell

    1 EXEC sp_configure 'show advanced options', 1

    2 RECONFIGURE

    3 EXEC sp_configure 'xp_cmdshell', 1

    4 RECONFIGURE

    然后就可以用cmdshell来导入数据了

    EXEC master..xp_cmdshell 'BCP database.schema.table in filepath -c -Sservername -Uusername -Ppassword'

    用的时候碰到几个问题:

    1 如果-S参数不带的话,会默认为本地的数据库服务器,如果本地有多个数据库的话,会报错,要写上具体的服务器名\实例名

    2 导入数据时,有的数据格式不对,会造成错误,默认的错误数达到10次,命令就会停止运行,造成后面的数据导入不成功 ,可以使用-m 最大错误数

    3 -e这个参数,可以生成错误日志,知道哪些数据没有导入成功,使用时要指定错误文件的完整路径

    bulk insert

    如果导入的数据中,有分隔符,用bcp就不太好用了,比如字段分隔符为#
    这个时候可以用bulk insert,它可以自定义字段分隔符和行终止符,默认的都为/t为字符分隔符,/n为行终止符

    BULK INSERT database.schema.table

       FROM 'filepath'

       WITH

         (

            FIELDTERMINATOR = '#',

            ROWTERMINATOR = '/n',

          )

    同样bulk insert也有错误数限制,默认为10,可以使用MAXERRORS参数来设定最大错误数

    补充点:

    如果是bcp导入的话,错误次数超过默认数,导入停止,但是已导入的数据会保存,而bulk insert 错误次数超过默认数,会回滚,一条数据也不会导入


  • sql的日期格式转换参数

    2011-12-15 15:02:18

    --*******************************************************************************
    --
    日期转换参数大全
    --
    ********************************************************************************
    select CONVERT(varchar,getdate(),120)
    --2009-03-15 15:10:02

    select replace(replace(replace(CONVERT(varchar, getdate(), 120 ),'-',''),' ',''),':','')
    --20090315151201

    select CONVERT(varchar(12) , getdate(), 111)
    --2009/03/15

    select CONVERT(varchar(12) , getdate(), 112)
    --20090315

    select CONVERT(varchar(12) , getdate(), 102)
    --2009.03.15

    select CONVERT(varchar(12) , getdate(), 108)
    --15:13:26

    其它我不常用的日期格式转换方法:

    select CONVERT(varchar(12) , getdate(), 101 )
    --03/15/2009

    select CONVERT(varchar(12) , getdate(), 103 )
    --15/03/2009

    select CONVERT(varchar(12) , getdate(), 104 )
    --15.03.2009

    select CONVERT(varchar(12) , getdate(), 105 )
    --15-03-2009

    select CONVERT(varchar(12) , getdate(), 106 )
    --15 03 2009

    select CONVERT(varchar(12) , getdate(), 107 )
    -- 15, 2009

    select CONVERT(varchar(12) , getdate(), 109 )
    --03 15 2009

    select CONVERT(varchar(12) , getdate(), 110 )
    --03-15-2009

    select CONVERT(varchar(11) , getdate(), 113 )
    --15 03 2009

    select CONVERT(varchar(12) , getdate(), 114)
    --15:15:55:717
  • qtp关于ordinal identifier参数化的问题

    2010-12-07 09:57:23

    想编写一个选中页面所有checkbox的一个操作

    这个是选中一个复选框的代码:

    Browser("形式审查系统").Page("电子政务").Frame("mainFrame").WebCheckBox("name:=messagecheck","index:=1").Set "ON"

    因为页面上有多个相同对象,所以用了ordinal identifier的index来确定唯一对象

    然后对编码做了些修改,能够选中页面上10个复选框


    For  i = 0 to 9
       
        Browser("形式审查系统").Page("电子政务").Frame("mainFrame").WebCheckBox("name:=messagecheck","index:=i").Set "ON"

    Next

    用了 for 循环

    可是运行的时候,还是只选中一个复选框

    变为以下这种形式后,运行成功

    For  i = 0 to 9
        
        Browser("形式审查系统").Page("电子政务").Frame("mainFrame").WebCheckBox("name:=messagecheck","index:="+Cstr(i)).Set "ON"

    Next




    后续:

    经人指点,终于知道原因所在,"index:=i" 只是把i作为了一个常量给了index,不是变量,如果要赋予变量的话 应该是 "index:="&i 或者我文章中的方法。

  • 关于qtp的手动编写脚本

    2010-12-06 15:34:58

    不知道怎么写这篇文章,因为我对qtp手工编写脚本也不熟,大多数是在录制的基础上修改脚本但qtp的牛人都是自己手工写脚本的,我想成为牛人,所以也学着手工编写脚本。

    很多人的所谓手工编写脚本,就是不依赖于qtp的对象库,所有的对象都写在脚本里,比如描述性编程。其实qtp的对象库还是很强大的,它可以帮助我们手工编写脚本。

    我们可以事先先录制好操作对象,并且对它们命名,这样便于管理对象库,然后就可以手工编写脚本了,qtp有一个好的地方,就是在编写脚本的时候,会自动读取对象库里的对象名,如果有多个对象,可以选择你要的对象的对象名,这样其实可以节省很多时间,而且也不会错误。
  • qtp外部调用vbs脚本,报错“无效类型”

    2010-11-29 11:24:41

    上周想试下qtp的外部调用vbs函数

    通过 file-settings-resources里添加脚本函数

    qtp代码里通过 call来调用函数

    可是运行的时候老是报错“无效类型”

    查了很多办法都没法解决

    只能重装了qtp,问题解决,但是产生的原因还是不知道,估计是qtp的内部问题

  • 使用ExcuteFile时,无效字符的错误

    2010-11-26 15:50:44

    今天用ExcuteFile 调用外部vb脚本的时候,一运行就报"无效字符"的错误

    后来上网查了,发现是因为vb脚本采用的是Unicode的编码,而使用ExcuteFile脚本必须是ansi的编码,后来重新用ansi编码保存了下,再次运行通过。不知道这算不算qtp的一个bug。
  • qtp对excel表的操作

    2010-11-26 09:18:51

    步骤:

    1 Excel的三层概念:ApplicationExcelFileSheet,因此需要创建三个对象来实现对Excel文件的操作。首先创建一个Excel.Application对象excelapp,然后通过excelapp打开一个Excel文件,并返回一个对象给excelbook,最后通过excelbookSheets属性来操作某一个sheet

    2 通过sheet对象的cells子对象来操作某一sheet中的区域,sheet对象可以通过usedRange属性来识别此文件已经使用的cells。通过其中的count方法来获取具体值

    3 操作完成,保存文件、关闭文件、退出程序

    4 释放对象

    代码如下:

    Dim excelapp,excelbook,excelsheet
    Set excelapp = createobject("excel.application")'创建execl的app对象

    'excelapp.Visible=true 'excel是否可见

    set excelbook=excelapp.Workbooks.Open("D:/test.xls")

    Set excelsheet=excelbook.worksheets("2011").usedrange'覆盖sheet的区域

    rowcount=excelsheet.rows.count'取行数

    columncount=excelsheet.columns.count'取列数

    For i=1to rowcount
           For  j=1 to columncount
                  'msgbox excelsheet.cells(i,j)

        Next

    Next

    Set excellsheet=nothing

    excelbook.Close

    excelapp.quit

    'Set excelbook=nothing

    'Set excelapp=nothing

  • webshell

    2010-03-17 10:26:44

  • 关于论坛上传图片,报错“无效图片”的原因

    2009-08-14 22:54:54

    目前遇到很多的用户反应,在论坛上传图片的时候,会报错“插入的图片无效”。现在分析下来主要有两个原因

    1 使用ie8

    在IE8的情况下,论坛上传附件时,无法用添加附件的方式,添加图片.出现“无效图片的文件”这只是IE8的安全系数更高造成的。有一个最让人头疼的就是:删除了IE8,删除之后IE自动恢复到了IE7,结果却是IE7居然也出现了相同问题,于是将IE7又重新装了一次,问题还是会出现.(只要装过IE8,不管你后来是不是卸载还是用其他的,问题还是会出现)

    解决方法:IE设置-安全-internet-自定义级别将文件上载到服务器时包含本地路径,默认是禁用,改成启用就可以了


     

    2 网页上传不了或者上传了显示不了JPG图片

    与图片CMYK格式有关

    部份数码相机、扫描仪等输出的相片,上传到网页上无法显示,原因就在于图片生成的格式是CMYK格式,而WEB中支持的是RGB格式。

    通常的作法都是用绘图软件将该图档打开,重新存档一次就可以在 IE 看到了。在 IE/Firefox 中看不见图片的真正原因出在于这些 JPEG 图档是用 CMYK 模式存档的,而 IE 只能读取 RGB 模式的图档,所以就会导致图片无法开启了。

    如果你是用 Photoshop 的話,可以在存档的时候选择 Save for web 也可以将图片强制转成 RGB 模式

  • 对于工作的感想

    2009-01-03 16:55:14

       做了这份工作也快半年了,发现网站测试和其他的web测试还是有蛮大的不同的,网站测试发现需求的变更太快了,快的都无法控制,可能上午刚做的决定,下午就修改了,而原因仅仅是老板觉得的不好看。做网站测试除了一般的功能外,什么样式啊,css之类的东西也需要考虑,不能光考虑功能上的问题,一些设计的问题也需要涉及,做的东西很杂,到现在我也没找到怎样才能保证网站运行质量的方法,因为这部分更多是运维在负责,他们掌控着所有的服务器。

       对于web测试来说,除了功能外,性能和安全性的测试也同样的不容忽视,包括其他的互联网技术,用到的东西很多,碰到的问题也可能是不同的原因造成的,如果对互联网了解不深的话,是很难定位和分析问题的,因为不单单是程序的问题,很有可能是网络当中的某一环出了问题。所以相对来说相比网站,自己更倾向于做一些纯软件方面的测试,最起码不需要考虑太多的东西。不过在当前的形式下,也只能走一步看一步了。

  • 转载 Linux下Memcache的使用及安装

    2008-11-12 22:35:28

    再转一篇关于memcache的文章。

    原文出处:http://hi.baidu.com/haomao/blog/item/6fae34d1f1a7c83d9b5027bc.html

    Memcached是什么?

    Memcached是高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。
    Memcached由Danga Interactive开发,用于提升LiveJournal.com访问速度的。LJ每秒动态页面访问量几千次,用户700万。Memcached将数据库负载大幅度降低,更好的分配资源,更快速访问。

    如何使用memcached-Server端?

    在服务端运行:
    # ./memcached -d -m 2048 -l 10.0.0.40 -p 11211
    这将会启动一个占用2G内存的进程,并打开11211端口用于接收请求。由于32位系统只能处理4G内存的寻址,所以在大于4G内存使用PAE的32位服务器上可以运行2-3个进程,并在不同端口进行监听。

    如何使用memcached-Client端?

    在应用端包含一个用于描述Client的Class后,就可以直接使用,非常简单。
    PHP Example:
    $options["servers"] = array("192.168.1.41:11211", "192.168.1.42:11212");
    $options["debug"] = false;
    $memc = new MemCachedClient($options);
    $myarr = array("one","two", 3);
    $memc->set("key_one", $myarr);
    $val = $memc->get("key_one");
    print $val[0]."\n"; // prints 'one‘
    print $val[1]."\n"; // prints 'two‘
    print $val[2]."\n"; // prints 3

    为什么不使用数据库做这些?


    暂且不考虑使用什么样的数据库(MS-SQL, Oracle, Postgres, MysQL-InnoDB, etc..), 实现事务(ACID,Atomicity, Consistency, Isolation, and Durability )需要大量开销,特别当使用到硬盘的时候,这就意味着查询可能会阻塞。当使用不包含事务的数据库(例如Mysql-MyISAM),上面的开销不存在,但 读线程又可能会被写线程阻塞。
    Memcached从不阻塞,速度非常快。

    为什么不使用共享内存?

    最初的缓存做法是在线程内对对象进行缓存,但这样进程间就无法共享缓存,命中率非常低,导致缓存效率极低。后来出现了共享内存的缓存,多个进程或者线程共享同一块缓存,但毕竟还是只能局限在一台机器上,多台机器做相同的缓存同样是一种资源的浪费,而且命中率也比较低。
    Memcached Server和Clients共同工作,实现跨服务器分布式的全局的缓存。并且可以与Web Server共同工作,Web Server对CPU要求高,对内存要求低,Memcached Server对CPU要求低,对内存要求高,所以可以搭配使用。

    Mysql 4.x的缓存怎么样?

    Mysql查询缓存不是很理想,因为以下几点:
    当指定的表发生更新后,查询缓存会被清空。在一个大负载的系统上这样的事情发生的非常频繁,导致查询缓存效率非常低,有的情况下甚至还不如不开,因为它对cache的管理还是会有开销。
    在32位机器上,Mysql对内存的操作还是被限制在4G以内,但memcached可以分布开,内存规模理论上不受限制。
    Mysql上的是查询缓存,而不是对象缓存,如果在查询后还需要大量其它操作,查询缓存就帮不上忙了。
    如果要缓存的数据不大,并且查询的不是非常频繁,这样的情况下可以用Mysql 查询缓存,不然的话memcached更好。

    数据库同步怎么样?

    这里的数据库同步是指的类似Mysql Master-Slave模式的靠日志同步实现数据库同步的机制。
    你可以分布读操作,但无法分布写操作,但写操作的同步需要消耗大量的资源,而且这个开销是随着slave服务器的增长而不断增长的。
    下一步是要对数据库进行水平切分,从而让不同的数据分布到不同的数据库服务器组上,从而实现分布的读写,这需要在应用中实现根据不同的数据连接不同的数据库。
    当这一模式工作后(我们也推荐这样做),更多的数据库导致更多的让人头疼的硬件错误。
    Memcached可以有效的降低对数据库的访问,让数据库用主要的精力来做不频繁的写操作,而这是数据库自己控制的,很少会自己阻塞 自己。

    Memcached快吗?


    非常快,它使用libevent,可以应付任意数量打开的连接(使用epoll,而非poll),使用非阻塞网络IO,分布式散列对象到不同的服务器,查询复杂度是O(1)。

    参考资料:
    Distributed Caching with Memcached | Linux Journal
    http://www.danga.com/

    肖理达 (KrazyNio AT hotmail.com), 2006.04. 06, 转载请注明出处

    一、memcached 简介

    在很多场合,我们都会听到 memcached 这个名字,但很多同学只是听过,并没有用过或实际了解过,只知道它是一个很不错的东东。这里简单介绍一下,memcached 是高效、快速的分布式内存对象缓存系统,主要用于加速 WEB 动态应用程序。

    二、memcached 安装

    首先是下载 memcached 了,目前最新版本是 1.1.12,直接从官方网站即可下载到 memcached-1.1.12.tar.gz。除此之外,memcached 用到了 libevent,我下载的是 libevent-1.1a.tar.gz。

    接下来是分别将 libevent-1.1a.tar.gz 和 memcached-1.1.12.tar.gz 解开包、编译、安装:

    [cmd]
    # tar -xzf libevent-1.1a.tar.gz
    # cd libevent-1.1a
    # ./configure --prefix=/usr
    # make
    # make install
    # cd ..
    # tar -xzf memcached-1.1.12.tar.gz
    # cd memcached-1.1.12
    # ./configure --prefix=/usr
    # make
    # make install
    [/cmd]

    <补充安装>

    # fetch http://www.danga.com/memcached/dist/memcached-1.1.12.tar.gz
       memcached运行需要用到libevent.

    # fetch http://monkey.org/~provos/libevent-1.1a.tar.gz
    # tar zxvf libevent-1.1a.tar.gz
    # cd libevent-1.1a
    # ./configure && make
    # make install
    # make verify
    # cd ..
    # tar zxvf memcached-1.1.12.tar.gz
    # cd memcached-1.1.12
    # ./configure --with-libevent=/usr/local
    # make
    # make check
    # make install
    # cat > /usr/local/etc/rc.d/memcache.sh
    /usr/local/bin/memcached -d -uroot -m 512 -p 12345
    # chmod +x /usr/local/etc/rc.d/memcache.sh
    安装完成之后,memcached 应该在 /usr/bin/memcached。

    </补充安装>

    三、运行 memcached 守护程序

    运行 memcached 守护程序很简单,只需一个命令行即可,不需要修改任何配置文件(也没有配置文件给你修改 ):
    [cmd]
    /usr/bin/memcached -d -m 128 -l 192.168.1.1 -p 11211 -u httpd
    参数解释:

    -d 以守护程序(daemon)方式运行 memcached;
    -m 设置 memcached 可以使用的内存大小,单位为 M;
    -l 设置监听的 IP 地址,如果是本机的话,通常可以不设置此参数;
    -p 设置监听的端口,默认为 11211,所以也可以不设置此参数;
    -u 指定用户,如果当前为 root 的话,需要使用此参数指定用户。

    当然,还有其它参数可以用,man memcached 一下就可以看到了。
    [/cmd]

    四、memcached 的工作原理

    首先 memcached 是以守护程序方式运行于一个或多个服务器中,随时接受客户端的连接操作,客户端可以由各种语言编写,目前已知的客户端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等。PHP 等客户端在与 memcached 服务建立连接之后,接下来的事情就是存取对象了,每个被存取的对象都有一个唯一的标识符 key,存取操作均通过这个 key 进行,保存到 memcached 中的对象实际上是放置内存中的,并不是保存在 cache 文件中的,这也是为什么 memcached 能够如此高效快速的原因。注意,这些对象并不是持久的,服务停止之后,里边的数据就会丢失。

    三、PHP 如何作为 memcached 客户端

    有两种方法可以使 PHP 作为 memcached 客户端,调用 memcached 的服务进行对象存取操作。

    第一种,PHP 有一个叫做 memcache 的扩展,Linux 下编译时需要带上 –enable-memcache[=DIR] 选项,Window 下则在 php.ini 中去掉 php_memcache.dll 前边的注释符,使其可用。

    除此之外,还有一种方法,可以避开扩展、重新编译所带来的麻烦,那就是直接使用 php-memcached-client。

    本文选用第二种方式,虽然效率会比扩展库稍差一些,但问题不大。

    四、PHP memcached 应用示例

    首先 下载 memcached-client.php,在下载了 memcached-client.php 之后,就可以通过这个文件中的类“memcached”对 memcached 服务进行操作了。其实代码调用非常简单,主要会用到的方法有 add()、get()、replace() 和 delete(),方法说明如下:

    add ($key, $val, $exp = 0)
    往 memcached 中写入对象,$key 是对象的唯一标识符,$val 是写入的对象数据,$exp 为过期时间,单位为秒,默认为不限时间;

    get ($key)
    从 memcached 中获取对象数据,通过对象的唯一标识符 $key 获取;

    replace ($key, $value, $exp=0)
    使用 $value 替换 memcached 中标识符为 $key 的对象内容,参数与 add() 方法一样,只有 $key 对象存在的情况下才会起作用;

    delete ($key, $time = 0)
    删除 memcached 中标识符为 $key 的对象,$time 为可选参数,表示删除之前需要等待多长时间。

    下面是一段简单的测试代码,代码中对标识符为 ‘mykey’ 的对象数据进行存取操作:

    PHP代码:
    <?php
    //      包含 memcached 类文件
    require_once(&lsquo;memcached-client.php&rsquo
    ;);
    //      选项设置
    $options
    = array(
          &
    rsquo;servers&rsquo; => array(&lsquo;192.168.1.1:11211&prime;),
    //memcached 服务的地址、端口,可用多个数组元素表示多个 memcached 服务
         
    &lsquo;debug&rsquo; => true,     
    //是否打开 debug
         
    &lsquo;compress_threshold&rsquo; => 10240,     
    //超过多少字节的数据时进行压缩
         
    &lsquo;persistant&rsquo; => false     
    //是否使用持久连接
         
    );
    //      创建 memcached 对象实例
    $mc = new memcached($options
    );
    //      设置此脚本使用的唯一标识符
    $key = &lsquo;mykey&rsquo
    ;;
    //      往 memcached 中写入对象
    $mc->add($key, &rsquo;some random strings&rsquo
    ;);
    $val = $mc->get($key
    );
    echo &
    ldquo;n&rdquo;.str_pad(&lsquo;$mc->add() &rsquo;, 60, &lsquo;_&rsquo;).&ldquo;n&rdquo
    ;;
    var_dump($val
    );
    //      替换已写入的对象数据值
    $mc->replace($key, array(&rsquo;some&rsquo;=>&lsquo;haha&rsquo;, &lsquo;array&rsquo;=>&lsquo;xxx&rsquo
    ;));
    $val = $mc->get($key
    );
    echo &
    ldquo;n&rdquo;.str_pad(&lsquo;$mc->replace() &rsquo;, 60, &lsquo;_&rsquo;).&ldquo;n&rdquo
    ;;
    var_dump($val
    );
    //      删除 memcached 中的对象
    $mc->delete($key
    );
    $val = $mc->get($key
    );
    echo &
    ldquo;n&rdquo;.str_pad(&lsquo;$mc->delete() &rsquo;, 60, &lsquo;_&rsquo;).&ldquo;n&rdquo
    ;;
    var_dump($val
    );
    ?>


     

    是不是很简单,在实际应用中,通常会把数据库查询的结果集保存到 memcached 中,下次访问时直接从 memcached 中获取,而不再做数据库查询操作,这样可以在很大程度上减轻数据库的负担。通常会将 SQL 语句 md5() 之后的值作为唯一标识符 key。下边是一个利用 memcached 来缓存数据库查询结果集的示例(此代码片段紧接上边的示例代码):

    PHP代码:
    <?php
    $sql
    = &lsquo;SELECT * FROM users&rsquo
    ;;
    $key = md5($sql);     
    //memcached 对象标识符
    if ( !($datas = $mc->get($key
    )) ) {
         
    //      在 memcached 中未获取到缓存数据,则使用数据库查询获取记录集。
         
    echo &ldquo;n&rdquo;.str_pad(&lsquo;Read datas from MySQL.&rsquo;, 60, &lsquo;_&rsquo;).&ldquo;n&rdquo
    ;;
         
    $conn = mysql_connect(&lsquo;localhost&rsquo;, &lsquo;test&rsquo;, &lsquo;test&rsquo
    ;);
         
    mysql_select_db(&lsquo;test&rsquo
    ;);
         
    $result = mysql_query($sql
    );
          while (
    $row = mysql_fetch_object($result
    ))
                 
    $datas[] = $row
    ;
         
    //      将数据库中获取到的结果集数据保存到 memcached 中,以供下次访问时使用。
         
    $mc->add($key, $datas
    );
    } else {
          echo &
    ldquo;n&rdquo;.str_pad(&lsquo;Read datas from memcached.&rsquo;, 60, &lsquo;_&rsquo;).&ldquo;n&rdquo
    ;;
    }
    var_dump($datas
    );
    ?>


     

    可以看出,使用 memcached 之后,可以减少数据库连接、查询操作,数据库负载下来了,脚本的运行速度也提高了。

    之前我曾经写过一篇名为《PHP 实现多服务器共享 SESSION 数据》文章,文中的 SESSION 是使用数据库保存的,在并发访问量大的时候,服务器的负载会很大,经常会超出 MySQL 最大连接数,利用 memcached,我们可以很好地解决这个问题,工作原理如下:

    用户访问网页时,查看 memcached 中是否有当前用户的 SESSION 数据,使用 session_id() 作为唯一标识符;如果数据存在,则直接返回,如果不存在,再进行数据库连接,获取 SESSION 数据,并将此数据保存到 memcached 中,供下次使用;
    当前的 PHP 运行结束(或使用了 session_write_close())时,会调用 My_Sess::write() 方法,将数据写入数据库,这样的话,每次仍然会有数据库操作,对于这个方法,也需要进行优化。使用一个全局变量,记录用户进入页面时的 SESSION 数据,然后在 write() 方法内比较此数据与想要写入的 SESSION 数据是否相同,不同才进行数据库连接、写入数据库,同时将 memcached 中对应的对象删除,如果相同的话,则表示 SESSION 数据未改变,那么就可以不做任何操作,直接返回了;
    那么用户 SESSION 过期时间怎么解决呢?记得 memcached 的 add() 方法有个过期时间参数 $exp 吗?把这个参数值设置成小于 SESSION 最大存活时间即可。另外别忘了给那些一直在线的用户延续 SESSION 时长,这个可以在 write() 方法中解决,通过判断时间,符合条件则更新数据库数据。

  • 转载 memcache的使用

    2008-11-12 22:30:29

       最近在做测试的时候,发现一个问题,大数据量访问时很多用户的昵称不能在前台显示了,而这个昵称用户是确实拥有的,数据库里也存在,但到底是什么原因,查了很久都没找出来,后来在开发的帮助下知道是memcache出来问题,我以前不知道什么是memcache,就上网查了下,现在把他转载过来,大家可以一起看看,到时就知道是哪出问题了。

    原文出处:http://blog.sina.com.cn/s/blog_4aea5d890100am61.html

       Memcache是什么
    Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。
    它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这些HashTable。
    Memcache官方网站:http://www.danga.com/memcached,更多详细的信息可以来这里了解 :)

    为什么会有Memcache和memcached两种名称?
    其实Memcache是这个项目的名称,而memcached是它服务器端的主程序文件名,知道我的意思了把~~~~。一个是项目名称,一个是主程序文件名,在网上看到了很多人不明白,于是混用了。

       Memcache的安装
    分为两个过程:memcache服务器端的安装和memcached客户端的安装。
    所谓服务器端的安装就是在服务器(一般都是linux系统)上安装Memcache实现数据的存储
    所谓客户端的安装就是指php(或者其他程序,Memcache还有其他不错的api接口提供)去使用服务器端的Memcache提供的函数,需要php添加扩展。

    具体的配置大家可以参考:
    Linux下的Memcache安装:http://www.ccvita.com/index.php/257.html
    Windows下的Memcache安装:http://www.ccvita.com/index.php/258.html
    Memcache基础教程:http://www.ccvita.com/index.php/259.html


       PHP的Memcache

    < ?php
    //连接
    $mem = new Memcache;
    $mem->connect("192.168.0.200", 12000);

    //保存数据
    $mem->set('key1', 'This is first value', 0, 60);
    $val = $mem->get('key1');
    echo "Get key1 value: " . $val ."<br />";

    //替换数据
    $mem->replace('key1', 'This is replace value', 0, 60);
    $val = $mem->get('key1');
    echo "Get key1 value: " . $val . "<br />";

    //保存数组
    $arr = array('aaa', 'bbb', 'ccc', 'ddd');
    $mem->set('key2', $arr, 0, 60);
    $val2 = $mem->get('key2');
    echo "Get key2 value: ";
    print_r($val2);
    echo "<br />";

    //删除数据
    $mem->delete('key1');
    $val = $mem->get('key1');
    echo "Get key1 value: " . $val . "<br />";

    //清除所有数据
    $mem->flush();
    $val2 = $mem->get('key2');
    echo "Get key2 value: ";
    print_r($val2);
    echo "<br />";

    //关闭连接
    $mem->close();
    ?>

    如果正常的话,浏览器将输出:
    Get key1 value: This is first value
    Get key1 value: This is replace value
    Get key2 value: Array ( [0] => aaa [1] => bbb [2] => ccc [3] => ddd )
    Get key1 value:
    Get key2 value:

        程序代码分析

    初始化一个Memcache的对象:
    $mem = new Memcache;

    连接到我们的Memcache服务器端,第一个参数是服务器的IP地址,也可以是主机名,第二个参数是Memcache的开放的端口:
    $mem->connect("192.168.0.200", 12000);

    保存一个数据到Memcache服务器上,第一个参数是数据的key,用来定位一个数据,第二个参数是需要保存的数据内容,这里是一个字符串,第三个参数是一个标记,一般设置为0或者MEMCACHE_COMPRESSED就行了,第四个参数是数据的有效期,就是说数据在这个时间内是有效的,如果过去这个时间,那么会被Memcache服务器端清除掉这个数据,单位是秒,如果设置为0,则是永远有效,我们这里设置了60,就是一分钟有效时间:
    $mem->set(‘key1‘, ‘This is first value’, 0, 60);

    从Memcache服务器端获取一条数据,它只有一个参数,就是需要获取数据的key,我们这里是上一步设置的key1,现在获取这个数据后输出输出:
    $val = $mem->get(’key1′);
    echo "Get key1 value: " . $val;

    现在是使用replace方法来替换掉上面key1的值,replace方法的参数跟set是一样的,不过第一个参数key1是必须是要替换数据内容的key,最后输出了:
    $mem->replace(‘key1′, ‘This is replace value’, 0, 60);
    $val = $mem->get(‘key1′);
    echo "Get key1 value: " . $val;

    同样的,Memcache也是可以保存数组的,下面是在Memcache上面保存了一个数组,然后获取回来并输出
    $arr = array(‘aaa’, ‘bbb’, ‘ccc’, ‘ddd’);
    $mem->set(‘key2′, $arr, 0, 60);
    $val2 = $mem->get(‘key2′);
    print_r($val2);

    现在删除一个数据,使用delte接口,参数就是一个key,然后就能够把Memcache服务器这个key的数据删除,最后输出的时候没有结果
    $mem->delete(‘key1′);
    $val = $mem->get(‘key1′);
    echo "Get key1 value: " . $val . "<br>";

    最后我们把所有的保存在Memcache服务器上的数据都清除,会发现数据都没有了,最后输出key2的数据为空,最后关闭连接
    $mem->flush();
    $val2 = $mem->get(‘key2′);
    echo "Get key2 value: ";
    print_r($val2);
    echo "<br>";

        Memcache的使用
    使用Memcache的网站一般流量都是比较大的,为了缓解数据库的压力,让 Memcache作为一个缓存区域,把部分信息保存在内存中,在前端能够迅速的进行存取。那么一般的焦点就是集中在如何分担数据库压力和进行分布式,毕竟单台Memcache的内存容量的有限的。我这里简单提出我的个人看法,未经实践,权当参考。

    分布式应用
    Memcache本来支持分布式,我们客户端稍加改造,更好的支持。我们的key可以适当进行有规律的封装,比如以user为主的网站来说,每个用户都有User ID,那么可以按照固定的ID来进行提取和存取,比如1开头的用户保存在第一台Memcache服务器上,以2开头的用户的数据保存在第二胎 Mecache服务器上,存取数据都先按照User ID来进行相应的转换和存取。

    但是这个有缺点,就是需要对User ID进行判断,如果业务不一致,或者其他类型的应用,可能不是那么合适,那么可以根据自己的实际业务来进行考虑,或者去想更合适的方法。

    减少数据库压力
    这个算是比较重要的,所有的数据基本上都是保存在数据库当中的,每次频繁的存取数据库,导致数据库性能极具下降,无法同时服务更多的用户,比如MySQL,特别频繁的锁表,那么让Memcache来分担数据库的压力吧。我们需要一种改动比较小,并且能够不会大规模改变前端的方式来进行改变目前的架构。

    我考虑的一种简单方法:
    后端的数据库操作模块,把所有的Select操作提取出来(update/delete/insert不管),然后把对应的SQL进行相应的hash算法计算得出一个hash数据key(比如MD5或者SHA),然后把这个key去Memcache中查找数据,如果这个数据不存在,说明还没写入到缓存中,那么从数据库把数据提取出来,一个是数组类格式,然后把数据在set到Memcache中,key就是这个SQL的 hash值,然后相应的设置一个失效时间,比如一个小时,那么一个小时中的数据都是从缓存中提取的,有效减少数据库的压力。缺点是数据不实时,当数据做了修改以后,无法实时到前端显示,并且还有可能对内存占用比较大,毕竟每次select出来的数据数量可能比较巨大,这个是需要考虑的因素。

        Memcache的安全
    我们上面的Memcache服务器端都是直接通过客户端连接后直接操作,没有任何的验证过程,这样如果服务器是直接暴露在互联网上的话是比较危险,轻则数据泄露被其他无关人员查看,重则服务器被入侵,因为Mecache是以root 权限运行的,况且里面可能存在一些我们未知的bug或者是缓冲区溢出的情况,这些都是我们未知的,所以危险性是可以预见的。为了安全起见,我做两点建议,能够稍微的防止黑客的入侵或者数据的泄露。

    内网访问
    最好把两台服务器之间的访问是内网形态的,一般是Web服务器跟Memcache服务器之间。普遍的服务器都是有两块网卡,一块指向互联网,一块指向内网,那么就让Web服务器通过内网的网卡来访问Memcache服务器,我们Memcache的服务器上启动的时候就监听内网的IP地址和端口,内网间的访问能够有效阻止其他非法的访问。
    # memcached -d -m 1024 -u root -l 192.168.0.200 -p 11211 -c 1024 -P /tmp/memcached.pid
    Memcache服务器端设置监听通过内网的192.168.0.200的ip的11211端口,占用1024MB内存,并且允许最大1024个并发连接

    设置防火墙
    防火墙是简单有效的方式,如果却是两台服务器都是挂在网的,并且需要通过外网IP来访问Memcache的话,那么可以考虑使用防火墙或者代理程序来过滤非法访问。
    一般我们在Linux下可以使用iptables或者FreeBSD下的ipfw来指定一些规则防止一些非法的访问,比如我们可以设置只允许我们的Web服务器来访问我们Memcache服务器,同时阻止其他的访问。
    # iptables -F
    # iptables -P INPUT DROP
    # iptables -A INPUT -p tcp -s 192.168.0.2 –dport 11211 -j ACCEPT
    # iptables -A INPUT -p udp -s 192.168.0.2 –dport 11211 -j ACCEPT
    上面的iptables规则就是只允许192.168.0.2这台Web服务器对Memcache服务器的访问,能够有效的阻止一些非法访问,相应的也可以增加一些其他的规则来加强安全性,这个可以根据自己的需要来做

  • 工作中的性能问题

    2008-11-01 15:57:18

        最近公司帮别的公司做了一个项目,具体是什么公司就不说了。项目做完交给我来进行测试,因为做的都是些小的项目,所以公司只有我一个测试,而且只做功能上的测试,对于性能没什么要求。但是事情就这样发生了。

        我们把这个项目的推广广告投放到了51.com,51是个何等的地方,号称日注册量16万,虽然我对这个数据抱有很大的怀疑,但起码说明51的影响力之大,当51的用户通过广告链接到我们自己的网站来的时候,由于数据流量太大,造成了服务器几次当机,项目进行的不顺利,客户那里没法交代。于是对代码进行了大规模的优化,包括sql语句,页面的图片等,造成了很多的返工。

        其实这些东西都是在前期的测试中可以分析出来的,但是我们没有估计到51那里的数据流量会那么大,其次我们对性能分析和性能的测试都不太重视,虽然我是有这种想法,无奈的是我只有一个人,对测试工作也才刚刚起步,对性能测试还不是那么了解。我只是觉得性能测试是测试工作很重要的一环,特别现在是互联网的时代,大家都通过网络参与,沟通,以及大量新技术的应用,都会对服务器造成压力,在资源有限的情况下如何解决好性能的问题是我下个阶段的目标。

  • SNS何去何从

    2008-10-26 23:31:21

        SNS(社会网络服务),是web2.0下的产物,更加注重用户之间的交互性,是目前互联网时代的主流。

        每个互联网公司都想从中分的一杯羹,造成了国内出现了大批的打着sns旗号的网站,51.com,校内,开心等,大多数的公司只是在模仿着facebook,并没有自己的创意,更别说盈利模式了,从最初的新鲜,好玩到现在的无聊,甚至有些厌烦,为什么这些网站看上去都一个样,不同的只不过是一个名字。以前是博客,后来出现了播客,现在轮到了sns,第一个吃螃蟹的是英雄,第二个,第三个也许是跟随英雄脚步的人,可一旦出现了第10个,第n个的时候,而且还是不做任何变更的跟随,谁还知道这些东西做出来还有没有价值,互联网时代可以使一个人一夜暴富,也能使他一夜就平穷,我们似乎总是在抄袭这国外的网站形式,但这样做是并不长远的,只有创造出属于自己的核心竞争力,建立忠实于自己的用户群体,这样的公司才能长久的发展下去。

Open Toolbar