<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>我的技术生活-王炜 &#187; WEB</title>
	<atom:link href="http://www.aaronw.cn/cache/web/feed" rel="self" type="application/rss+xml" />
	<link>http://www.aaronw.cn</link>
	<description>只为成功找方法，不为失败找借口</description>
	<lastBuildDate>Wed, 01 Sep 2010 13:51:26 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>用自己的邮箱注册MSN ID</title>
		<link>http://www.aaronw.cn/static/674.html</link>
		<comments>http://www.aaronw.cn/static/674.html#comments</comments>
		<pubDate>Wed, 01 Sep 2010 13:51:26 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[id]]></category>
		<category><![CDATA[msn]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=674</guid>
		<description><![CDATA[https://accountservices.passport.net/reg.srf?id=9&#038;cbid=956&#038;sl=1&#038;lc=2052
]]></description>
			<content:encoded><![CDATA[<p>https://accountservices.passport.net/reg.srf?id=9&#038;cbid=956&#038;sl=1&#038;lc=2052</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/674.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WSGI、flup、fastcgi、web.py的关系</title>
		<link>http://www.aaronw.cn/static/630.html</link>
		<comments>http://www.aaronw.cn/static/630.html#comments</comments>
		<pubDate>Sat, 27 Feb 2010 14:20:17 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[fastcgi]]></category>
		<category><![CDATA[flup]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web.py]]></category>
		<category><![CDATA[WSGI]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=630</guid>
		<description><![CDATA[最近一直在学习python，了解了python的基本语法和编写规则！想用python写一个网络接口，但是不知道怎么下手！关键是还有很概念没有搞明白，刚看了一篇文章上有这方面的解释，现在转载到这里与大家分享！
Apache/lighttpd: 相当于一个request proxy，根据配置，把不同的请求转发给不同的server处理，例如静态的文件请求自己处理，这个时候它就像一个web server，对于fastcgi/python这样的请求转发给flup这样的Server/Gateway进行处理
flup: 一个用python写的web server，也就是cgi中所谓的Server/Gateway，它负责接受apache/lighttpd转发的请求，并调用你写的程序 (application)，并将application处理的结果返回到apache/lighttpd
fastcgi: apache/lighttpd的一个模块，虽然flup可以作为一个独立的web server使用，但是对于浏览器请求处理一般都交给 apache/lighttpd处理，然后由apache/lighttpd转发给flup处理，这样就需要一个东西来把apache/lighttpd跟flup联系起来，这个东西就是fastcgi，它通过环境变量以及socket将客户端请求的信息传送给flup并接收flup返回的结果
web.py: 应该说有了上面的东西你就可以开始编写你的web程序了，但是问题是你就要自己处理浏览器的输入输出，还有cookie、session、模板等各种各样的问题了，web.py的作用就是帮你把这些工作都做好了，它就是所谓的web framework，另外一个出名的是django，不过感觉太复杂了，web.py差不多就够用了
WSGI : 除了flup Server/Gateway外还有很多其他人的写的Server/Gateway, 这个时候就会出问题了，如果你在flup上写了一个程序，现在由于各种原因你要使用xdly了，这个时候你的程序也许就要做很多痛苦的修改才能使用 xdly server了，WSGI就是一个规范，他规范了flup这个服务应该怎么写，应该使用什么方式什么参数调用你写的程序(application)等，当然同时也规范你的程序应该怎么写了，这样的话，只要flup跟xdly都遵守WSGI的话，你的程序在两个上面都可以使用了，flup就是一个WSGI server
转自豆瓣网
]]></description>
			<content:encoded><![CDATA[<p>最近一直在学习python，了解了python的基本语法和编写规则！想用python写一个网络接口，但是不知道怎么下手！关键是还有很概念没有搞明白，刚看了一篇文章上有这方面的解释，现在转载到这里与大家分享！</p>
<p>Apache/lighttpd: 相当于一个request proxy，根据配置，把不同的请求转发给不同的server处理，例如静态的文件请求自己处理，这个时候它就像一个web server，对于fastcgi/python这样的请求转发给flup这样的Server/Gateway进行处理</p>
<p>flup: 一个用python写的web server，也就是cgi中所谓的Server/Gateway，它负责接受apache/lighttpd转发的请求，并调用你写的程序 (application)，并将application处理的结果返回到apache/lighttpd</p>
<p>fastcgi: apache/lighttpd的一个模块，虽然flup可以作为一个独立的web server使用，但是对于浏览器请求处理一般都交给 apache/lighttpd处理，然后由apache/lighttpd转发给flup处理，这样就需要一个东西来把apache/lighttpd跟flup联系起来，这个东西就是fastcgi，它通过环境变量以及socket将客户端请求的信息传送给flup并接收flup返回的结果</p>
<p>web.py: 应该说有了上面的东西你就可以开始编写你的web程序了，但是问题是你就要自己处理浏览器的输入输出，还有cookie、session、模板等各种各样的问题了，web.py的作用就是帮你把这些工作都做好了，它就是所谓的web framework，另外一个出名的是django，不过感觉太复杂了，web.py差不多就够用了</p>
<p>WSGI : 除了flup Server/Gateway外还有很多其他人的写的Server/Gateway, 这个时候就会出问题了，如果你在flup上写了一个程序，现在由于各种原因你要使用xdly了，这个时候你的程序也许就要做很多痛苦的修改才能使用 xdly server了，WSGI就是一个规范，他规范了flup这个服务应该怎么写，应该使用什么方式什么参数调用你写的程序(application)等，当然同时也规范你的程序应该怎么写了，这样的话，只要flup跟xdly都遵守WSGI的话，你的程序在两个上面都可以使用了，flup就是一个WSGI server</p>
<p>转自豆瓣网</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/630.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转载]在wordpress中插入flash和音乐文件[无需插件]</title>
		<link>http://www.aaronw.cn/static/500.html</link>
		<comments>http://www.aaronw.cn/static/500.html#comments</comments>
		<pubDate>Thu, 29 Oct 2009 13:16:46 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[wp插件]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=500</guid>
		<description><![CDATA[今天查看部落格的PV的时候,发现关键字Hippop的搜索就顺便看了看我的那篇日志,原来那篇日志是引用了56的一个flash视频,因为coolplayer的作者不更新,而该插件又不支持高版本的WP,所以该日志不能显示,于是我就找个替代插件,发现了这个不需插件也能播放flash的日志,现转载至此!
插入FLASH:
&#60;embed play=&#34;true&#34; quality=&#34;best&#34; height=&#34;500&#34; width=&#34;500&#34; src=&#34;FLASH'S URL&#34; pluginspage=&#34;http://www.macromedia.com/go/getflashplayer&#34;&#62;&#60;/embed&#62;
插入音乐文件:
&#60;embed loop=&#34;false&#34; autostart=&#34;false&#34; controls=&#34;ImageWindow&#34; maxwidth=&#34;500&#34; src=&#34;AUDIOURL&#34;&#62;&#60;/embed&#62;
媒体标签介绍:
图文并茂的帖子还需要有音乐、影像等媒体做衬托，帖子的整体效果才达到极致。虽然论坛一般都提供插入媒体文件的方法，但那是很有局限的，并不能满足特殊的要求。为此，有必要学习和掌握媒体标签的使用方法。
首先我们先了解一下三种主要的音乐格式。这些音乐格式都是当前网络上较为流行的，它们更被广泛地应用于论坛。
出于编写代码的要求，我们这里以支持这些音乐的播放机为划分音乐格式的依据，这种划分方法以前也是有人使用过的。

第一种：WMP格式。
WMP即为Windows Media Player的缩写，是微软公司的媒体播放机，它集成在Windows系统里，可以格外免费升级（网上一般都有下载链接）。其网络ActiveX插件为 Windows Media Player。当前WMP所支持的音乐及影像媒体文件的格式主要有（仅介绍网络上常用的格式，下同）：
MP3（音频）、WMA（音频）、WMV（视频）、AVI（视频）、MPEG（电影）、WAV（音频）、MIDI（音频）、ASF（视频）、AIFF（音频）、AU（音频）、wpl文件（WMP播放列表文件）、m3u文件（Winamp的播放列表文件）等。
第二种：RP格式。
这是有着悠久历史的一种媒体格式，宽带普及以前的网络媒体文件的老大，由RealNetworks公司开发。它当前的网络ActiveX插件是Real Player G2 Control。常见文件后缀名为：
rax、ram、rmm、rsml、rvx、rmj、rmx、rjt、rm
REAL也支持MP3、MIDI、Wav等格式的媒体文件，但它的播放效果没有WMP的好，所以我们不把它列入RP格式。
第三种：Flash格式。这是Macromedia公司开发的结合音频视频在一块的媒体格式。其插件为Shock Wave。文件后缀名为.swf。
弄清楚以上文件格式后，我们就可以使用标签来编写播放媒体文件的代码了。语法：
格式一：
格式二：
格式一适用于显示播放界面的情形，格式二适用于隐藏播放界面的情形。
下面分别讲解各参数的取值规定和要求。
src：媒体音乐地址。地址要完整、有效。如果文件名包含非英文字符，建议整个地址用小角双引号引起来。
autostart：是否自动播放（即一打开帖子就播放与否）。true为自动，false为手动。
loop:是否循环播放。true为循环，false只播放一次；也可用正整数表示播放多少次，比如等于3表示播放3次。
width:播放界面的宽度。建议在300到500之间。
height:播放界面的度度。这个很讲究。针对音频文件，视频界面是没有必要出现的，为此，WMP播放机设置为45非常合适，RP播放机为85较好；有视频的则根据情况设置。
hidden:是否隐藏播放界面。格式二语法式样中设置为true，即不可见，如果设置为false，则表示可见，但若不设置width和 height，它的样子是不好看的。有不少人也用width=0 height=0来隐藏播放机的播放界面，其是这样是隐藏不了的，WMP有一个点，RP有一条竖线。
type:这是一个重要的值，用于指播放机的插件类型，一些论坛会根据有效的src自动给出type类型（这类论坛我们编写代码时可以省略type），但也有的论坛不会自动给出类型，需要用户指定。type的取值依据和取值规定是：
WMP类：audio/mpeg (wma的可用audio/x-ms-wma，不过都一样)
RP类：application/octet-stream
Flash：application/x-shockwave-flash
注：Flash还可指定wmode=transparent表示背景透明，quality=high表示以高档画质播放，pluginspage=http://www.macromedia.com/go/getflashplayer指定插件下载地址（可省略）。
类型的指定尽量不要弄错，否则极可能出现有些朋友访问你的帖子时不能正常欣赏到音乐和影像媒体。
对于支持object的论坛，建议使用object来播放媒体文件，它得到的效果更能令人满意。因其代码较多，不便记忆，这里就不介绍了，但你可以通过FP或DW插入Web组件的方法并对ActiveX控件进行相应的设置得到完整的代码。
原文地址:http://www.a18zhizao.cn/y2008/99_在wordpress中插入flash和音乐文件无需插件.html
]]></description>
			<content:encoded><![CDATA[<p>今天查看部落格的PV的时候,发现关键字Hippop的搜索就顺便看了看我的那篇日志,原来那篇日志是引用了56的一个flash视频,因为coolplayer的作者不更新,而该插件又不支持高版本的WP,所以该日志不能显示,于是我就找个替代插件,发现了这个不需插件也能播放flash的日志,现转载至此!<br />
插入FLASH:</p>
<pre class="brush: php;">&lt;embed play=&quot;true&quot; quality=&quot;best&quot; height=&quot;500&quot; width=&quot;500&quot; src=&quot;FLASH'S URL&quot; pluginspage=&quot;http://www.macromedia.com/go/getflashplayer&quot;&gt;&lt;/embed&gt;</pre>
<p>插入音乐文件:</p>
<pre class="brush: php;">&lt;embed loop=&quot;false&quot; autostart=&quot;false&quot; controls=&quot;ImageWindow&quot; maxwidth=&quot;500&quot; src=&quot;AUDIOURL&quot;&gt;&lt;/embed&gt;</pre>
<p>媒体标签介绍:<br />
图文并茂的帖子还需要有音乐、影像等媒体做衬托，帖子的整体效果才达到极致。虽然论坛一般都提供插入媒体文件的方法，但那是很有局限的，并不能满足特殊的要求。为此，有必要学习和掌握媒体标签的使用方法。</p>
<p>首先我们先了解一下三种主要的音乐格式。这些音乐格式都是当前网络上较为流行的，它们更被广泛地应用于论坛。</p>
<p>出于编写代码的要求，我们这里以支持这些音乐的播放机为划分音乐格式的依据，这种划分方法以前也是有人使用过的。<br />
<span id="more-500"></span><br />
第一种：WMP格式。</p>
<p>WMP即为Windows Media Player的缩写，是微软公司的媒体播放机，它集成在Windows系统里，可以格外免费升级（网上一般都有下载链接）。其网络ActiveX插件为 Windows Media Player。当前WMP所支持的音乐及影像媒体文件的格式主要有（仅介绍网络上常用的格式，下同）：</p>
<p>MP3（音频）、WMA（音频）、WMV（视频）、AVI（视频）、MPEG（电影）、WAV（音频）、MIDI（音频）、ASF（视频）、AIFF（音频）、AU（音频）、wpl文件（WMP播放列表文件）、m3u文件（Winamp的播放列表文件）等。</p>
<p>第二种：RP格式。</p>
<p>这是有着悠久历史的一种媒体格式，宽带普及以前的网络媒体文件的老大，由RealNetworks公司开发。它当前的网络ActiveX插件是Real Player G2 Control。常见文件后缀名为：</p>
<p>rax、ram、rmm、rsml、rvx、rmj、rmx、rjt、rm</p>
<p>REAL也支持MP3、MIDI、Wav等格式的媒体文件，但它的播放效果没有WMP的好，所以我们不把它列入RP格式。</p>
<p>第三种：Flash格式。这是Macromedia公司开发的结合音频视频在一块的媒体格式。其插件为Shock Wave。文件后缀名为.swf。</p>
<p>弄清楚以上文件格式后，我们就可以使用标签来编写播放媒体文件的代码了。语法：</p>
<p>格式一：</p>
<p>格式二：</p>
<p>格式一适用于显示播放界面的情形，格式二适用于隐藏播放界面的情形。</p>
<p>下面分别讲解各参数的取值规定和要求。</p>
<p>src：媒体音乐地址。地址要完整、有效。如果文件名包含非英文字符，建议整个地址用小角双引号引起来。</p>
<p>autostart：是否自动播放（即一打开帖子就播放与否）。true为自动，false为手动。</p>
<p>loop:是否循环播放。true为循环，false只播放一次；也可用正整数表示播放多少次，比如等于3表示播放3次。</p>
<p>width:播放界面的宽度。建议在300到500之间。</p>
<p>height:播放界面的度度。这个很讲究。针对音频文件，视频界面是没有必要出现的，为此，WMP播放机设置为45非常合适，RP播放机为85较好；有视频的则根据情况设置。</p>
<p>hidden:是否隐藏播放界面。格式二语法式样中设置为true，即不可见，如果设置为false，则表示可见，但若不设置width和 height，它的样子是不好看的。有不少人也用width=0 height=0来隐藏播放机的播放界面，其是这样是隐藏不了的，WMP有一个点，RP有一条竖线。</p>
<p>type:这是一个重要的值，用于指播放机的插件类型，一些论坛会根据有效的src自动给出type类型（这类论坛我们编写代码时可以省略type），但也有的论坛不会自动给出类型，需要用户指定。type的取值依据和取值规定是：</p>
<p>WMP类：audio/mpeg (wma的可用audio/x-ms-wma，不过都一样)</p>
<p>RP类：application/octet-stream</p>
<p>Flash：application/x-shockwave-flash</p>
<p>注：Flash还可指定wmode=transparent表示背景透明，quality=high表示以高档画质播放，pluginspage=http://www.macromedia.com/go/getflashplayer指定插件下载地址（可省略）。</p>
<p>类型的指定尽量不要弄错，否则极可能出现有些朋友访问你的帖子时不能正常欣赏到音乐和影像媒体。</p>
<p>对于支持object的论坛，建议使用object来播放媒体文件，它得到的效果更能令人满意。因其代码较多，不便记忆，这里就不介绍了，但你可以通过FP或DW插入Web组件的方法并对ActiveX控件进行相应的设置得到完整的代码。<br />
原文地址:http://www.a18zhizao.cn/y2008/99_在wordpress中插入flash和音乐文件无需插件.html</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/500.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Firefox临时文件的位置和修改</title>
		<link>http://www.aaronw.cn/static/488.html</link>
		<comments>http://www.aaronw.cn/static/488.html#comments</comments>
		<pubDate>Mon, 26 Oct 2009 07:28:05 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[temp]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=488</guid>
		<description><![CDATA[Firefox临时文件通常存放在“C:\Documents and Settings\你的用户名\Application Data\Mozilla\Firefox\Profiles\.default\Cache”一般可以通过：about:cache来查看。
如果路径被篡改，可以在地址栏输入“about:cache”命令回车，查看临时文件所在的具体位置。我们也能自己修改Firefox临时文件的存放路径：新建一个标签页在地质栏中输入“about:config”回车，在Config列表中点击右键，选择“新建→字符串”，在弹出的“新的字符串值”对话框“首选项名称”中输入“browser.cache.disk.parent_directory”确定，在下个窗口中输入字符串的值，即新的文件路径，确定后在Config列表中看到新建的这个字符串，并可以随时修改这个值改变路径
本文转载自互联网,原文地址:http://www.cnblogs.com/qlight/archive/2008/09/20/1294923.html
]]></description>
			<content:encoded><![CDATA[<p>Firefox临时文件通常存放在“C:\Documents and Settings\你的用户名\Application Data\Mozilla\Firefox\Profiles\.default\Cache”一般可以通过：about:cache来查看。</p>
<p>如果路径被篡改，可以在地址栏输入“about:cache”命令回车，查看临时文件所在的具体位置。我们也能自己修改Firefox临时文件的存放路径：新建一个标签页在地质栏中输入“about:config”回车，在Config列表中点击右键，选择“新建→字符串”，在弹出的“新的字符串值”对话框“首选项名称”中输入“browser.cache.disk.parent_directory”确定，在下个窗口中输入字符串的值，即新的文件路径，确定后在Config列表中看到新建的这个字符串，并可以随时修改这个值改变路径</p>
<p>本文转载自互联网,原文地址:http://www.cnblogs.com/qlight/archive/2008/09/20/1294923.html</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/488.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wordpress自动升级和plugin插件更新的问题</title>
		<link>http://www.aaronw.cn/static/446.html</link>
		<comments>http://www.aaronw.cn/static/446.html#comments</comments>
		<pubDate>Tue, 22 Sep 2009 02:01:08 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[Wordpress插件]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=446</guid>
		<description><![CDATA[Wordpress2.7的一键自动更新很好用。可是在使用Wordpress插件自动更新和安装时，有时发现需要提示输入ftp信息：
FTP Connection Information
Host:
Username:
Password:
这是Wordpress的一个bug，在某些文件系统上有问题从wordpress2.5到2.7都一直没有更新，在国外网站上查了下修复方法如下：
1. 编辑wp-admin/includes/file.php找到以下这行
if(getmyuid()==fileowner($tempFile)){
把这句中把getmyuid改成posix_getuid
2. 完成以上修改应该不会再要输入ftp信息了，但是有时候会告知目录不对，在wp-content目录下建立upgrade目录
chown www:www wp-content/upgrade
chmod +w wp-content/upgrade
做完以上设置应该就可以自动更新了。
]]></description>
			<content:encoded><![CDATA[<p>Wordpress2.7的一键自动更新很好用。可是在使用Wordpress插件自动更新和安装时，有时发现需要提示输入ftp信息：<br />
<code>FTP Connection Information<br />
Host:<br />
Username:<br />
Password:</code></p>
<p>这是Wordpress的一个bug，在某些文件系统上有问题从wordpress2.5到2.7都一直没有更新，在国外网站上查了下修复方法如下：</p>
<p>1. 编辑wp-admin/includes/file.php找到以下这行<br />
<code>if(getmyuid()==fileowner($tempFile)){</code><br />
把这句中把getmyuid改成posix_getuid</p>
<p>2. 完成以上修改应该不会再要输入ftp信息了，但是有时候会告知目录不对，在wp-content目录下建立upgrade目录<br />
<code>chown www:www wp-content/upgrade<br />
chmod +w wp-content/upgrade</code><br />
做完以上设置应该就可以自动更新了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/446.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转载]wordpress 常用函数</title>
		<link>http://www.aaronw.cn/static/407.html</link>
		<comments>http://www.aaronw.cn/static/407.html#comments</comments>
		<pubDate>Fri, 19 Jun 2009 07:37:30 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[常用函数]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=407</guid>
		<description><![CDATA[    打算自己学着写个主题,所以就找了些wordpress 常用函数,下面这些是我转载的.
转载地址http://blogsdiy.org/2007-12/wordpress-template-handbook
Header部分常用到的PHP函数
&#60;? php bloginfo('name'); ?&#62;	博客名称(Title)
&#60;? php bloginfo('stylesheet_url'); ?&#62;	CSS文件路径
&#60;? php bloginfo('pingback_url'); ?&#62;	PingBack Url
&#60;? php bloginfo('template_url'); ?&#62;	模板文件路径
&#60;? php bloginfo('version'); ?&#62;	WordPress版本
&#60;? php bloginfo('atom_url'); ?&#62;	Atom Url
&#60;? php bloginfo('rss2_url'); ?&#62;	RSS 2.o Url
&#60;? php bloginfo('url'); ?&#62;	博客 Url
&#60;? php bloginfo('html_type'); ?&#62;	博客网页Html类型
&#60;? php bloginfo('charset'); ?&#62;	博客网页编码
&#60;? php bloginfo('description'); ?&#62;	博客描述
&#60;? php wp_title(); ?&#62;	特定内容页(Post/Page)的标题

模板常用的PHP函数及命令
&#60;? php get_header(); ?&#62;	调用Header模板
&#60;? php get_sidebar(); ?&#62;	调用Sidebar模板
&#60;? php get_footer(); [...]]]></description>
			<content:encoded><![CDATA[<p>    打算自己学着写个主题,所以就找了些wordpress 常用函数,下面这些是我转载的.</p>
<p>转载地址http://blogsdiy.org/2007-12/wordpress-template-handbook</p>
<p><strong>Header部分常用到的PHP函数</strong></p>
<pre class="brush: php;">&lt;? php bloginfo('name'); ?&gt;	博客名称(Title)
&lt;? php bloginfo('stylesheet_url'); ?&gt;	CSS文件路径
&lt;? php bloginfo('pingback_url'); ?&gt;	PingBack Url
&lt;? php bloginfo('template_url'); ?&gt;	模板文件路径
&lt;? php bloginfo('version'); ?&gt;	WordPress版本
&lt;? php bloginfo('atom_url'); ?&gt;	Atom Url
&lt;? php bloginfo('rss2_url'); ?&gt;	RSS 2.o Url
&lt;? php bloginfo('url'); ?&gt;	博客 Url
&lt;? php bloginfo('html_type'); ?&gt;	博客网页Html类型
&lt;? php bloginfo('charset'); ?&gt;	博客网页编码
&lt;? php bloginfo('description'); ?&gt;	博客描述
&lt;? php wp_title(); ?&gt;	特定内容页(Post/Page)的标题</pre>
<p><span id="more-407"></span><br />
<strong>模板常用的PHP函数及命令</strong></p>
<pre class="brush: php;">&lt;? php get_header(); ?&gt;	调用Header模板
&lt;? php get_sidebar(); ?&gt;	调用Sidebar模板
&lt;? php get_footer(); ?&gt;	调用Footer模板
&lt;? php the_content(); ?&gt;	显示内容(Post/Page)
&lt;? php if(have_posts())	?&gt;	检查是否存在Post/Page
&lt;? php while(have_posts())	the_post(); ?&gt;	如果存在Post/Page则予以显示
&lt;? php endwhile; ?&gt;	While 结束
&lt;? php endif; ?&gt;	If 结束
&lt;? php the_time('字符串') ?&gt;	显示时间，时间格式由“字符串”参数决定，具体参考PHP手册
&lt;? php comments_popup_link(); ?&gt;	正文中的留言链接。
    如果使用 comments_popup_script()，则留言会在新窗口中打开，反之，则在当前窗口打开
&lt;? php the_title(); ?&gt;	内容页(Post/Page)标题
&lt;? php the_permalink() ?&gt;	内容页(Post/Page) Url
&lt;? php the_category(', ') ?&gt;	特定内容页(Post/Page)所属Category
&lt;? php the_author(); ?&gt;	作者
&lt;? php the_ID(); ?&gt;	特定内容页(Post/Page) ID
&lt;? php edit_post_link(); ?&gt;	如果用户已登录并具有权限，显示编辑链接
&lt;? php get_links_list(); ?&gt;	显示Blogroll中的链接
&lt;? php comments_template(); ?&gt;	调用留言/回复模板
&lt;? php wp_list_pages(); ?&gt;	显示Page列表
&lt;? php wp_list_categories(); ?&gt;	显示Categories列表
&lt;? php next_post_link(' %link '); ?&gt;	下一篇文章链接
&lt;? php previous_post_link('%link'); ?&gt;	上一篇文章链接
&lt;? php get_calendar(); ?&gt;	日历
&lt;? php wp_get_archives() ?&gt;	显示内容存档
&lt;? php posts_nav_link(); ?&gt;	导航，显示上一篇/下一篇文章链接
&lt;? php include(TEMPLATEPATH . '/文件名'); ?&gt;	嵌入其他文件，可为定制的模板或其他类型文件</pre>
<p>与模板相关的其他函数</p>
<pre class="brush: php;">&lt;? php _e('Message'); ?&gt;	输出相应信息
&lt;? php wp_register(); ?&gt;	显示注册链接
&lt;? php wp_loginout(); ?&gt;	显示登录/注销链接
&lt; !-- next page --&gt;	将当前内容分页
&lt; !-- more --&gt;	将当前内容截断，以不在主页/目录页显示全部内容
&lt;? php timer_stop(1); ?&gt;	网页加载时间(秒)
&lt;? php echo get_num_queries(); ?&gt;	网页加载查询量</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/407.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WordPress超酷分页导航插件—Paginator 3000</title>
		<link>http://www.aaronw.cn/static/396.html</link>
		<comments>http://www.aaronw.cn/static/396.html#comments</comments>
		<pubDate>Wed, 17 Jun 2009 10:21:00 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[Paginator 3000]]></category>
		<category><![CDATA[Wordpress插件]]></category>
		<category><![CDATA[分页导航]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=396</guid>
		<description><![CDATA[今天上网无意间浏览到一个部落格,发现他的分页导航很不错,名字叫Paginator 3000。下载安装发现很不错,留个记录吧!
安装流程:下载、上传、激活、插入代码
1、下载     Paginator 3000
2、解压后上传到wp-content\plugins目录里面
3、进入管理后台选择插件&#8212;&#62;已安装&#8212;-&#62;Paginator&#8212;-&#62;启用
4、修改主题的index.php页面,找到div class=&#8221;navigation&#8221;后按下面代码修改
&#60;div class=&#34;navigation&#34;&#62;
&#60;?php if(function_exists('wp_paginator')) { wp_paginator(); } ?&#62;
&#60;?php if(function_exists('wp_pagenavi')) : { wp_pagenavi(); } ?&#62;
&#60;?php else : ?&#62;
&#60;?php endif; ?&#62;
&#60;/div&#62;
]]></description>
			<content:encoded><![CDATA[<p>今天上网无意间浏览到一个部落格,发现他的分页导航很不错,名字叫Paginator 3000。下载安装发现很不错,留个记录吧!</p>
<p>安装流程:下载、上传、激活、插入代码</p>
<p>1、下载     <a href="http://downloads.wordpress.org/plugin/paginator.zip" target="_blank">Paginator 3000</a></p>
<p>2、解压后上传到wp-content\plugins目录里面</p>
<p>3、进入管理后台选择插件&#8212;&gt;已安装&#8212;-&gt;Paginator&#8212;-&gt;启用</p>
<p>4、修改主题的index.php页面,找到div class=&#8221;navigation&#8221;后按下面代码修改</p>
<pre class="brush: php;">&lt;div class=&quot;navigation&quot;&gt;
&lt;?php if(function_exists('wp_paginator')) { wp_paginator(); } ?&gt;
&lt;?php if(function_exists('wp_pagenavi')) : { wp_pagenavi(); } ?&gt;
&lt;?php else : ?&gt;
&lt;?php endif; ?&gt;
&lt;/div&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/396.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>000webhost &#8211; 1500M支持PHP可绑域名的免费虚拟主机</title>
		<link>http://www.aaronw.cn/static/330.html</link>
		<comments>http://www.aaronw.cn/static/330.html#comments</comments>
		<pubDate>Mon, 27 Apr 2009 14:39:31 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[000webhost]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[免费PHP空间]]></category>
		<category><![CDATA[免费虚拟主机]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=330</guid>
		<description><![CDATA[
Hosting24旗下的000webhost，自称“比收费虚拟主机更好”的免费空间，他的口碑也确实不错。免费提供1500M空间，100G流量，FTP、Web方式上传管理文件，支持PHP5，提供2个MySQL数据库，功能强大的cPanel管理面板，管理面板中可一键安装WordPress、phpBB2、Drupal、Joomla等几种热门PHP程序，免费提供1个二级域名，可以绑定自己的域名，速度不错，无广告。但需要使用VPN代理才能成功申请。
网址：http://www.000webhost.com
MySQL数据库创建过程：
登陆后台，进入“Go to CPanel”，再点“MySQL”中进入。依次输入数据库名、数据库用户名、数据库用户密码和确认密码，点下面的按钮创建数据库。然后会给出MySQL 服务器地址，一般是“mysqlN.000webhost.com”这样的地址，不是localhost。
一键安装程序：
进入“Fantastico Autoinstaller”，点你要选择安装程序下面的“New Installation”按钮，然后输入要安装到的目录名称以及管理用户名和密码。然后回到前面的一键安装页面，点“View Installation Details”按钮查看管理地址和用户信息。
绑定域名：
进入“Parked Domains”，输入你的域名点下面的按钮绑定到你的免费空间上，再设置你的域名解析到你的空间上即可。可以修改你的域名DNS 为：ns01.000webhost.com和ns02.000webhost.com，或者设置你的域名CNAME别名解析到000webhost提供给你的免费二级域名，也可以设置A记录解析到你的000webhost二级域名的IP地址，CNAME和A记录解析比修改DNS会快很多。
000webhost的FAQ帮助：http://www.000webhost.com/faq.php
]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone" title="000webhost" src="http://www.aaronw.cn/wp-content/uploads/images/000webhost.jpg" alt="" width="290" height="83" /></p>
<p>Hosting24旗下的000webhost，自称“比收费虚拟主机更好”的免费空间，他的口碑也确实不错。免费提供1500M空间，100G流量，FTP、Web方式上传管理文件，支持PHP5，提供2个MySQL数据库，功能强大的cPanel管理面板，管理面板中可一键安装WordPress、phpBB2、Drupal、Joomla等几种热门PHP程序，免费提供1个二级域名，可以绑定自己的域名，速度不错，无广告。但需要使用VPN代理才能成功申请。</p>
<p>网址：http://www.000webhost.com</p>
<p>MySQL数据库创建过程：<br />
登陆后台，进入“Go to CPanel”，再点“MySQL”中进入。依次输入数据库名、数据库用户名、数据库用户密码和确认密码，点下面的按钮创建数据库。然后会给出MySQL 服务器地址，一般是“mysqlN.000webhost.com”这样的地址，不是localhost。</p>
<p>一键安装程序：<br />
进入“Fantastico Autoinstaller”，点你要选择安装程序下面的“New Installation”按钮，然后输入要安装到的目录名称以及管理用户名和密码。然后回到前面的一键安装页面，点“View Installation Details”按钮查看管理地址和用户信息。</p>
<p>绑定域名：<br />
进入“Parked Domains”，输入你的域名点下面的按钮绑定到你的免费空间上，再设置你的域名解析到你的空间上即可。可以修改你的域名DNS 为：ns01.000webhost.com和ns02.000webhost.com，或者设置你的域名CNAME别名解析到000webhost提供给你的免费二级域名，也可以设置A记录解析到你的000webhost二级域名的IP地址，CNAME和A记录解析比修改DNS会快很多。</p>
<p>000webhost的FAQ帮助：http://www.000webhost.com/faq.php</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/330.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>关于wordpress中the_category() 取分类标题的问题!</title>
		<link>http://www.aaronw.cn/static/272.html</link>
		<comments>http://www.aaronw.cn/static/272.html#comments</comments>
		<pubDate>Wed, 22 Apr 2009 05:50:33 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[vcluster]]></category>
		<category><![CDATA[worepress]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=272</guid>
		<description><![CDATA[前一段时间用wordpress做了个企业站点www.vcluster.cn,再做导航的时候分类总是有连接,后来在网上找了个方法把这个问题解决了,方法如下:
将
&#60;?php the_category('/',''); ?&#62;
换成
&#60;?php

foreach((get_the_category()) as $category) { 
    echo $category-&#62;cat_name . ' '; 
} 
?&#62;
]]></description>
			<content:encoded><![CDATA[<p>前一段时间用wordpress做了个企业站点www.vcluster.cn,再做导航的时候分类总是有连接,后来在网上找了个方法把这个问题解决了,方法如下:</p>
<p>将
<pre class="brush: php;">&lt;?php the_category('/',''); ?&gt;</pre>
<p>换成</p>
<pre class="brush: php;">&lt;?php

foreach((get_the_category()) as $category) { 
    echo $category-&gt;cat_name . ' '; 
} 
?&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/272.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nginx重定向[Rewrite]配置及示例</title>
		<link>http://www.aaronw.cn/static/222.html</link>
		<comments>http://www.aaronw.cn/static/222.html#comments</comments>
		<pubDate>Sun, 01 Feb 2009 07:17:37 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=222</guid>
		<description><![CDATA[今天我把webserver换成了NGINX后，发现wordpress不能用了。是NGINX不能识别apache的Rrewrite rule,后来google了一下把问题解决了！先贴代码，后贴找到的相关文章。
vi wordpress.conf
if (-f $request_filename/index.html){
rewrite (.*) $1/index.html break;
}
if (-f $request_filename/index.php){
rewrite (.*) $1/index.php;
}
if (!-f $request_filename){
rewrite (.*) /index.php;
}
server {
listen 80;
server_name www.aaronw.cn;
index index.html index.php;
include wordpress.conf;

一定要加在这里，我开始加在location里面发现它不生效。 Nginx重定向[Rewrite]配置及示例
首先Apache的Rewite规则差别不是很大,但是Nginx的Rewrite规则比Apache的简单灵活多了 Nginx可以用if进行条件匹配，语法规则类似C
if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /msie/$1 break; }
官方文档请点击这里
Rewrite的Flags
Flags can be any of the following:
* last &#8211; completes processing of rewrite directives, after which searches for corresponding URI and location
* break [...]]]></description>
			<content:encoded><![CDATA[<p>今天我把webserver换成了NGINX后，发现wordpress不能用了。是NGINX不能识别apache的Rrewrite rule,后来google了一下把问题解决了！先贴代码，后贴找到的相关文章。</p>
<pre class="brush: plain;">vi wordpress.conf</pre>
<pre class="brush: plain;">if (-f $request_filename/index.html){
rewrite (.*) $1/index.html break;
}
if (-f $request_filename/index.php){
rewrite (.*) $1/index.php;
}
if (!-f $request_filename){
rewrite (.*) /index.php;
}</pre>
<pre class="brush: plain;">server {
listen 80;
server_name www.aaronw.cn;
index index.html index.php;
include wordpress.conf;</pre>
<p><span id="more-222"></span><br />
一定要加在这里，我开始加在location里面发现它不生效。 Nginx重定向[Rewrite]配置及示例<br />
首先Apache的Rewite规则差别不是很大,但是Nginx的Rewrite规则比Apache的简单灵活多了 Nginx可以用if进行条件匹配，语法规则类似C</p>
<pre class="brush: plain;">if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /msie/$1 break; }</pre>
<p>官方文档请点击这里<br />
Rewrite的Flags</p>
<p>Flags can be any of the following:<br />
* last &#8211; completes processing of rewrite directives, after which searches for corresponding URI and location<br />
* break &#8211; completes processing of rewrite directives<br />
*redirect &#8211; returns temporary redirect with code 302; it is used if the substituting line begins with http://<br />
* permanent &#8211; returns permanent redirect with code 301</p>
<p>last &#8211; 完成重写指令后，搜索相应的URI和位置。相当于Apache里的[L]标记，表示完成rewrite，不再匹配后面的规则。<br />
break &#8211; 中止Rewirte，不在继续匹配。<br />
redirect &#8211; 返回临时重定向的HTTP状态302。<br />
permanent &#8211; 返回永久重定向的HTTP状态301。</p>
<p>ZEND Framework的重定向规则：<br />
案例一：<br />
全部重定向到 /index.php</p>
<pre class="brush: plain;">rewrite ^/(.*) /index.php?$1&amp;;</pre>
<p>案例二： 如果文件或目录不存在则重定向到index.php</p>
<pre class="brush: plain;">if (!-e $request_filename) { rewrite ^/(.*) /index.php?$1&amp;; }</pre>
<p>Wordpress的重定向规则：<br />
案例一： http://www.abc.com/12 重定向到http://www.abc.com/index.php?p=12</p>
<pre class="brush: plain;">if (!-e $request_filename) { rewrite ^/(.+)$ /index.php?p=$1 last; }</pre>
<p>案例二： 与zendframework配置很像</p>
<pre class="brush: plain;">if (!-e $request_filename) { rewrite ^/(.*) /index.php?$1&amp;; }</pre>
<p>以下为Discuz完整的Rewrite for Nginx规则</p>
<pre class="brush: plain;">if (!-f $request_filename) {
rewrite ^/archiver/((fid|tid)-[\w\-]+\.html)$ /archiver/index.php?$1 last;
rewrite ^/forum-([0-9]+)-([0-9]+)\.html$ /forumdisplay.php?fid=$1&amp;page=$2 last;
rewrite ^/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$/viewthread.php?tid=$1&amp;extra=page%3D$3&amp;page=$2 last;
rewrite ^/space-(username|uid)-(.+)\.html$ /space.php?$1=$2 last;
rewrite ^/tag-(.+)\.html$ /tag.php?name=$1 last; }</pre>
<p>文件及目录匹配，其中：<br />
-f和!-f用来判断是否存在文件<br />
-d和!-d用来判断是否存在目录<br />
-e和!-e用来判断是否存在文件或目录<br />
-x和!-x用来判断文件是否可执行</p>
<p>正则表达式全部符号解释<br />
~ 为区分大小写匹配<br />
~* 为不区分大小写匹配<br />
!~和!~* 分别为区分大小写不匹配及不区分大小写不匹配<br />
(pattern) 匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到，在VBScript 中使用 SubMatches 集合，在JScript 中则使用 $0…$9 属性。要匹配圆括号字符，请使用 ‘\(’ 或 ‘\)’。<br />
^ 匹配输入字符串的开始位置。<br />
$ 匹配输入字符串的结束位置。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/222.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>今天给blog增加了代码高亮插件-SyntaxHighlighter</title>
		<link>http://www.aaronw.cn/static/219.html</link>
		<comments>http://www.aaronw.cn/static/219.html#comments</comments>
		<pubDate>Thu, 15 Jan 2009 03:05:03 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[SyntaxHighlighter]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=219</guid>
		<description><![CDATA[          今天给blog增加了代码高亮插件-SyntaxHighlighter，安装了好几次都不好用！readme只有简单的语法没有配置，就去google上，最终找到了个配置方法，现在转载过来，做个记录！
SyntaxHighlighter支持的语法
            C# — c#、c-sharp、csharp
            CSS — css
            Delphi — delphi、pascal
            Java — java
            JavaScript — js、jscript、javascript
            PHP — php
            Python — py、python
            Ruby — rb、ruby、rails、ror
            SQL — sql
            VB — vb、vb.net
            XML/HTML — xml、html、xhtml、xslt
SyntaxHighlighter 的下载
       下载地址

SyntaxHighlighter 的安裝
      1、将下载的文档解压，会生成一个syntaxhighlighter文件夹，然后将文件夹放到/wp-content/plugins/ 下面。
      2、后台启用该插件。
      3、编辑你正使用主题的header.php文件，然后将下面的语句复制到&#60;head&#62;与&#60;/head&#62;标记之间。
      
link rel=&#38;amp;amp;quot;stylesheet&#38;amp;amp;quot; href=&#38;amp;amp;quot;&#38;amp;amp;lt; ?php echo get_bloginfo('wpurl').'/wp-content/plugins/syntaxhighlighter/files/SyntaxHighlighter.css'; ?&#38;amp;amp;gt;&#38;amp;amp;quot; type=&#38;amp;amp;quot;text/css&#38;amp;amp;quot; media=&#38;amp;amp;quot;screen&#38;amp;amp;quot; /&#38;amp;amp;gt;
      4、上述步骤完成后检查你使用主题的footer.php文件,看看其中是否有这个的语句&#60;?php wp_footer(); ?&#62;，如果没有则该插件的JavaScript 不能使用。
SyntaxHighlighter 的使用
      在遇到想用程序语法的时候，下面的方式择一使用：
   [...]]]></description>
			<content:encoded><![CDATA[<p>          今天给blog增加了代码高亮插件-SyntaxHighlighter，安装了好几次都不好用！readme只有简单的语法没有配置，就去google上，最终找到了个配置方法，现在转载过来，做个记录！<br />
<strong>SyntaxHighlighter支持的语法</strong><br />
            C# — c#、c-sharp、csharp<br />
            CSS — css<br />
            Delphi — delphi、pascal<br />
            Java — java<br />
            JavaScript — js、jscript、javascript<br />
            PHP — php<br />
            Python — py、python<br />
            Ruby — rb、ruby、rails、ror<br />
            SQL — sql<br />
            VB — vb、vb.net<br />
            XML/HTML — xml、html、xhtml、xslt<br />
<strong>SyntaxHighlighter 的下载<br />
</strong>       <a href="http://wordpress.org/extend/plugins/syntaxhighlighter/" target="_blank"><span style="color: #0000ff;">下载地址</span><br />
</a><span id="more-219"></span><br />
<strong>SyntaxHighlighter 的安裝<br />
</strong>      1、将下载的文档解压，会生成一个syntaxhighlighter文件夹，然后将文件夹放到/wp-content/plugins/ 下面。<br />
      2、后台启用该插件。<br />
      3、编辑你正使用主题的header.php文件，然后将下面的语句复制到&lt;head&gt;与&lt;/head&gt;标记之间。<br />
      
<pre class="brush: php;">link rel=&amp;amp;amp;quot;stylesheet&amp;amp;amp;quot; href=&amp;amp;amp;quot;&amp;amp;amp;lt; ?php echo get_bloginfo('wpurl').'/wp-content/plugins/syntaxhighlighter/files/SyntaxHighlighter.css'; ?&amp;amp;amp;gt;&amp;amp;amp;quot; type=&amp;amp;amp;quot;text/css&amp;amp;amp;quot; media=&amp;amp;amp;quot;screen&amp;amp;amp;quot; /&amp;amp;amp;gt;</pre>
<p>      4、上述步骤完成后检查你使用主题的footer.php文件,看看其中是否有这个的语句&lt;?php wp_footer(); ?&gt;，如果没有则该插件的JavaScript 不能使用。</p>
<p><strong>SyntaxHighlighter 的使用<br />
</strong>      在遇到想用程序语法的时候，下面的方式择一使用：<br />
   （红色的部分请选择相应的语言）</p>
<p>        您的程序代码<br />
        您的程序代码<br />
        您的程序代码<br />
        您的程序代码<br />
        您的程序代码<br />
        您的程序代码<br />
        您的程序代码<br />
        您的程序代码<br />
        您的程序代码<br />
PHP范例</p>
<pre class="brush: php;">&amp;amp;amp;lt; ?php
define('ABSPATH', dirname(__FILE__).'/');&amp;amp;amp;lt;span class=&amp;amp;amp;quot;MyColor1&amp;amp;amp;quot;&amp;amp;amp;gt;&amp;amp;amp;lt; ?php wp_footer(); ?&amp;amp;amp;gt;
require_once(ABSPATH.'wp-settings.php');
?&amp;amp;amp;gt;</pre>
<p>CSS范例</p>
<pre class="brush: css;">div.Test {
 width: 190px;
 font-size: 13px;
 font-family: Verdana, Serif;
} /* 测试 */</pre>
<p>JavaScript范例</p>
<pre class="brush: jscript;">var a = 1;
var b = 5;
flag1 = new Boolean(a &amp;amp;amp;lt; b);
 document.write(&amp;amp;amp;quot;1 &amp;amp;amp;lt; 5 是 &amp;amp;amp;quot; + flag1);
flag2 = new Boolean(a &amp;amp;amp;gt; b);
 document.write(&amp;amp;amp;quot;1 &amp;amp;amp;gt; 5 是 &amp;amp;amp;quot; + flag2);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/219.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>FireBug 1.2 for Firefox 3.0</title>
		<link>http://www.aaronw.cn/static/161.html</link>
		<comments>http://www.aaronw.cn/static/161.html#comments</comments>
		<pubDate>Fri, 20 Jun 2008 09:16:51 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[firebug1.2]]></category>
		<category><![CDATA[firefox 3.0]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=161</guid>
		<description><![CDATA[最近将firefox更新3.0 发现很多扩展软件被禁用，FireBug就是其中一个。官方的更新地址不能使用
在此本人提供一个Firebug 1.2的下载！
firebug-120b3
]]></description>
			<content:encoded><![CDATA[<p>最近将firefox更新3.0 发现很多扩展软件被禁用，FireBug就是其中一个。官方的更新地址不能使用<br />
在此本人提供一个Firebug 1.2的下载！</p>
<p><a href="http://www.aaronw.cn/wp-content/uploads/2008/06/firebug-120b3-fx.xpi">firebug-120b3</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/161.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>配置Red5详解</title>
		<link>http://www.aaronw.cn/static/152.html</link>
		<comments>http://www.aaronw.cn/static/152.html#comments</comments>
		<pubDate>Tue, 06 May 2008 07:19:18 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[Red5]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=152</guid>
		<description><![CDATA[RED5将所有的应用程序都放在RED5根目录下的”webapps“目录。你需要为所创建的程序在webapps目录下添加相应的目录。在你的应用程序目录里应该有一个名为”WEB-INF“的目录，用来存放你的程序的配置文件。在”doc/templates/myapp“目录有一个模板，可以用来帮你完成建立程序的初始工作。
RED5启动的时候，在”webapps”目录的程序文件都是搜索”WEB-INF”的目录下的配置文件来完成配置的。
最主要的配置文件是”web.xml”。这个文件里包含了以下参数：
globalScope：指定全局作用范围


&#60;context-param&#62;
 &#60;param-name&#62;globalScope&#60;/param-name&#62;
 &#60;param-value&#62;default&#60;/param-value&#62;
&#60;/context-param&#62;


contextConfigLocation：指定配置handler的文件的位置。这些配置文件描述了客户端加入/离开的动作触发后调用的处理方法，作用范围。在描述的时候可以使用通配符来描述多个文件：



&#60;context-param&#62;
 &#60;param-name&#62;contextConfigLocation&#60;/param-name&#62;
 &#60;param-value&#62;/WEB-INF/red5-*.xml&#60;/param-value&#62;
&#60;/context-param&#62;


locatorFactorySelector：程序的根上下文，通常是”red5.xml”


&#60;context-param&#62;
 &#60;param-name&#62;locatorFactorySelector&#60;/param-name&#62;
 &#60;param-value&#62;red5.xml&#60;/param-value&#62;
&#60;/context-param&#62;


parentContextKey：父级上下文，通常是”default.context”


&#60;context-param&#62;
 &#60;param-name&#62;parentContextKey&#60;/param-name&#62;
 &#60;param-value&#62;default.context&#60;/param-value&#62;
&#60;/context-param&#62;


log4jConfigLocation：日志配置文件的位置


&#60;context-param&#62;
 &#60;param-name&#62;log4jConfigLocation&#60;/param-name&#62;
 &#60;param-value&#62;/WEB-INF/log4j.properties&#60;/param-value&#62;
&#60;/context-param&#62;


webAppRootKey：程序的全局唯一名


&#60;context-param&#62;
 &#60;param-name&#62;webAppRootKey&#60;/param-name&#62;
 &#60;param-value&#62;/myapp&#60;/param-value&#62;
&#60;/context-param&#62;


对于每一个Handler配置文件最少需要有三个bean
Context：用来影射路径到某个作用范围、搜索服务和Handler，它有一个保留的名字”web.context”。 其默认的类为org.red5.server.Context


&#60;bean id=&#8220;web.context&#8220; class=&#8220;org.red5.server.Context&#8220;
 autowire=&#8220;byType&#8220; /&#62;


对于没有一个应用程序只应该有一个Context，但是同一个Context可以被多个作用范围共享
Scope：每一个应用程序最少有一个作用范围，用来将handler连接到context和服务器。作用范围可以建立一棵树，每一个客户端连接到树上的一个节点，而共享对象存在于作用范围里。可以把作用范围看作是聊天室或者程序实例。默认的作用范围通常是web.scope，不过这名字是可以任意取的。
对于bean有以下属性：
server：与全局服务器”red5.server”相关。
parent：指定当前作用范围的父范围，通常是”global.scope”
context：当前作用范围的服务器上下文，一般指定为”web.context”
handler：对应当前作用范围的handler
contextPath：用来连接到当前作用范围的路径
virtualHosts：一个主机名或IP的列表，用来描述虚拟主机的位置，列表项目之间用逗号分隔开。


&#60;bean id=&#8220;web.scope&#8220; class=&#8220;org.red5.server.WebScope&#8220;
 init-method=&#8220;register&#8220;&#62;
 &#60;property name=&#8220;server&#8220; ref=&#8220;red5.server&#8220; /&#62;
 &#60;property name=&#8220;parent&#8220; ref=&#8220;global.scope&#8220; /&#62;
 &#60;property name=&#8220;context&#8220; ref=&#8220;web.context&#8220; /&#62;
 &#60;property name=&#8220;handler&#8220; ref=&#8220;web.handler&#8220; /&#62;
 &#60;property name=&#8220;contextPath&#8220; value=&#8220;/myapp&#8220; /&#62;
 &#60;property name=&#8220;virtualHosts&#8220; value=&#8220;localhost, 127.0.0.1&#8220; /&#62;
&#60;/bean&#62;


为了应用程序配置方便的需要，可以将”contextPath“和”virtualHosts“放到另外一个单独的属性文件里边，而在这里使用变量来表示，为此需要添加一个特别的bean来指定属性文件的位置。


&#60;bean id=&#8220;placeholderConfig&#8220; class=&#8220;org.springframework.beans.factory.config.PropertyPlaceholderConfigurer&#8220;&#62;
 &#60;property name=&#8220;location&#8220; value=&#8220;/WEB-INF/red5-web.properties&#8220; /&#62;
&#60;/bean&#62;


假设在属性文件red5-web.properties里有如下的数据：


webapp.contextPath=/myapp
 webapp.virtualHosts=localhost, 127.0.0.1


则上边的bean的”contextPath“和”virtualHosts“属性即可使用变量来指定值


&#60;property name=&#8220;contextPath&#8220; [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://osflash.org/red5">RED5</a>将所有的应用程序都放在RED5<strong>根目录</strong>下的”<strong>webapps</strong>“目录。你需要为所创建的程序在<strong>webapps目录</strong>下添加相应的目录。在你的应用程序目录里应该有一个名为”<strong>WEB-INF</strong>“的目录，用来存放你的程序的配置文件。在”<strong>doc/templates/myapp</strong>“目录有一个模板，可以用来帮你完成建立程序的初始工作。</p>
<p>RED5启动的时候，在”webapps”目录的程序文件都是搜索”WEB-INF”的目录下的配置文件来完成配置的。</p>
<p>最主要的配置文件是”web.xml”。这个文件里包含了以下参数：</p>
<p><strong>globalScope：</strong>指定全局作用范围</p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: olive;">&lt;</span><span style="color: green;">context-param</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">param-name</span><span style="color: olive;">&gt;</span><span style="color: gray;">globalScope</span><span style="color: olive;">&lt;/</span><span style="color: green;">param-name</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">param-value</span><span style="color: olive;">&gt;</span><span style="color: gray;">default</span><span style="color: olive;">&lt;/</span><span style="color: green;">param-value</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: olive;">&lt;/</span><span style="color: green;">context-param</span><span style="color: olive;">&gt;</span></li>
</ol>
</div>
<p><strong>contextConfigLocation：</strong>指定配置handler的文件的位置。这些配置文件描述了客户端加入/离开的动作触发后调用的处理方法，作用范围。在描述的时候可以使用通配符来描述多个文件：<br />
<span id="more-152"></span></p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: olive;">&lt;</span><span style="color: green;">context-param</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">param-name</span><span style="color: olive;">&gt;</span><span style="color: gray;">contextConfigLocation</span><span style="color: olive;">&lt;/</span><span style="color: green;">param-name</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">param-value</span><span style="color: olive;">&gt;</span><span style="color: gray;">/WEB-INF/red5-*.xml</span><span style="color: olive;">&lt;/</span><span style="color: green;">param-value</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: olive;">&lt;/</span><span style="color: green;">context-param</span><span style="color: olive;">&gt;</span></li>
</ol>
</div>
<p><strong>locatorFactorySelector：</strong>程序的根上下文，通常是”red5.xml”</p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: olive;">&lt;</span><span style="color: green;">context-param</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">param-name</span><span style="color: olive;">&gt;</span><span style="color: gray;">locatorFactorySelector</span><span style="color: olive;">&lt;/</span><span style="color: green;">param-name</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">param-value</span><span style="color: olive;">&gt;</span><span style="color: gray;">red5.xml</span><span style="color: olive;">&lt;/</span><span style="color: green;">param-value</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: olive;">&lt;/</span><span style="color: green;">context-param</span><span style="color: olive;">&gt;</span></li>
</ol>
</div>
<p><strong>parentContextKey：</strong>父级上下文，通常是”default.context”</p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: olive;">&lt;</span><span style="color: green;">context-param</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">param-name</span><span style="color: olive;">&gt;</span><span style="color: gray;">parentContextKey</span><span style="color: olive;">&lt;/</span><span style="color: green;">param-name</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">param-value</span><span style="color: olive;">&gt;</span><span style="color: gray;">default.context</span><span style="color: olive;">&lt;/</span><span style="color: green;">param-value</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: olive;">&lt;/</span><span style="color: green;">context-param</span><span style="color: olive;">&gt;</span></li>
</ol>
</div>
<p><strong>log4jConfigLocation：</strong>日志配置文件的位置</p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: olive;">&lt;</span><span style="color: green;">context-param</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">param-name</span><span style="color: olive;">&gt;</span><span style="color: gray;">log4jConfigLocation</span><span style="color: olive;">&lt;/</span><span style="color: green;">param-name</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">param-value</span><span style="color: olive;">&gt;</span><span style="color: gray;">/WEB-INF/log4j.properties</span><span style="color: olive;">&lt;/</span><span style="color: green;">param-value</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: olive;">&lt;/</span><span style="color: green;">context-param</span><span style="color: olive;">&gt;</span></li>
</ol>
</div>
<p><strong>webAppRootKey：</strong>程序的全局唯一名</p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: olive;">&lt;</span><span style="color: green;">context-param</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">param-name</span><span style="color: olive;">&gt;</span><span style="color: gray;">webAppRootKey</span><span style="color: olive;">&lt;/</span><span style="color: green;">param-name</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">param-value</span><span style="color: olive;">&gt;</span><span style="color: gray;">/myapp</span><span style="color: olive;">&lt;/</span><span style="color: green;">param-value</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: olive;">&lt;/</span><span style="color: green;">context-param</span><span style="color: olive;">&gt;</span></li>
</ol>
</div>
<p>对于每一个Handler配置文件最少需要有三个bean</p>
<p><strong>Context：</strong>用来影射路径到某个作用范围、搜索服务和Handler，它有一个保留的名字”web.context”。 其默认的类为<strong>org.red5.server.Context</strong></p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: olive;">&lt;</span><span style="color: green;">bean</span><span style="color: gray;"> </span><span style="color: #00008b;">id</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">web.context</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: #00008b;">class</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">org.red5.server.Context</span><span style="color: #8b0000;">&#8220;</span></li>
<li><span style="color: gray;"> </span><span style="color: #00008b;">autowire</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">byType</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: olive;">/&gt;</span></li>
</ol>
</div>
<p>对于没有一个应用程序只应该有一个Context，但是同一个Context可以被多个作用范围共享</p>
<p><strong>Scope：</strong>每一个应用程序最少有一个作用范围，用来将handler连接到context和服务器。作用范围可以建立一棵树，每一个客户端连接到树上的一个节点，而共享对象存在于作用范围里。可以把作用范围看作是聊天室或者程序实例。默认的作用范围通常是<strong>web.scope</strong>，不过这名字是可以任意取的。</p>
<p>对于bean有以下属性：</p>
<p><strong>server：</strong>与全局服务器”red5.server”相关。</p>
<p><strong>parent：</strong>指定当前作用范围的父范围，通常是”global.scope”</p>
<p><strong>context：</strong>当前作用范围的服务器上下文，一般指定为”web.context”</p>
<p><strong>handler：</strong>对应当前作用范围的handler</p>
<p><strong>contextPath：</strong>用来连接到当前作用范围的路径</p>
<p><strong>virtualHosts：</strong>一个主机名或IP的列表，用来描述虚拟主机的位置，列表项目之间用逗号分隔开。</p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: olive;">&lt;</span><span style="color: green;">bean</span><span style="color: gray;"> </span><span style="color: #00008b;">id</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">web.scope</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: #00008b;">class</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">org.red5.server.WebScope</span><span style="color: #8b0000;">&#8220;</span></li>
<li><span style="color: gray;"> </span><span style="color: #00008b;">init-method</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">register</span><span style="color: #8b0000;">&#8220;</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">property</span><span style="color: gray;"> </span><span style="color: #00008b;">name</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">server</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: #00008b;">ref</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">red5.server</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: olive;">/&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">property</span><span style="color: gray;"> </span><span style="color: #00008b;">name</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">parent</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: #00008b;">ref</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">global.scope</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: olive;">/&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">property</span><span style="color: gray;"> </span><span style="color: #00008b;">name</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">context</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: #00008b;">ref</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">web.context</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: olive;">/&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">property</span><span style="color: gray;"> </span><span style="color: #00008b;">name</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">handler</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: #00008b;">ref</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">web.handler</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: olive;">/&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">property</span><span style="color: gray;"> </span><span style="color: #00008b;">name</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">contextPath</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: #00008b;">value</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">/myapp</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: olive;">/&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">property</span><span style="color: gray;"> </span><span style="color: #00008b;">name</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">virtualHosts</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: #00008b;">value</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">localhost, 127.0.0.1</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: olive;">/&gt;</span></li>
<li><span style="color: olive;">&lt;/</span><span style="color: green;">bean</span><span style="color: olive;">&gt;</span></li>
</ol>
</div>
<p>为了应用程序配置方便的需要，可以将”<strong>contextPath</strong>“和”<strong>virtualHosts</strong>“放到另外一个单独的属性文件里边，而在这里使用变量来表示，为此需要添加一个特别的bean来指定属性文件的位置。</p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: olive;">&lt;</span><span style="color: green;">bean</span><span style="color: gray;"> </span><span style="color: #00008b;">id</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">placeholderConfig</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: #00008b;">class</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">org.springframework.beans.factory.config.PropertyPlaceholderConfigurer</span><span style="color: #8b0000;">&#8220;</span><span style="color: olive;">&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">property</span><span style="color: gray;"> </span><span style="color: #00008b;">name</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">location</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: #00008b;">value</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">/WEB-INF/red5-web.properties</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: olive;">/&gt;</span></li>
<li><span style="color: olive;">&lt;/</span><span style="color: green;">bean</span><span style="color: olive;">&gt;</span></li>
</ol>
</div>
<p>假设在属性文件<strong>red5-web.properties</strong>里有如下的数据：</p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: blue;">webapp</span><span style="color: gray;">.</span><span style="color: blue;">contextPath</span><span style="color: gray;">=/</span><span style="color: blue;">myapp</span></li>
<li><span style="color: gray;"> </span><span style="color: blue;">webapp</span><span style="color: gray;">.</span><span style="color: blue;">virtualHosts</span><span style="color: gray;">=</span><span style="color: blue;">localhost</span><span style="color: gray;">, </span><span style="color: maroon;">127.0.0.1</span></li>
</ol>
</div>
<p>则上边的<strong>bean</strong>的”<strong>contextPath</strong>“和”<strong>virtualHosts</strong>“属性即可使用变量来指定值</p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: olive;">&lt;</span><span style="color: green;">property</span><span style="color: gray;"> </span><span style="color: #00008b;">name</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">contextPath</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: #00008b;">value</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">http://www.ruyiblog.com/${webapp.contextPath}</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: olive;">/&gt;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">&lt;</span><span style="color: green;">property</span><span style="color: gray;"> </span><span style="color: #00008b;">name</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">virtualHosts</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: #00008b;">value</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">http://www.ruyiblog.com/${webapp.virtualHosts}</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: olive;">/&gt;</span></li>
</ol>
</div>
<p>对于”<strong>contextPath</strong>“可以视为是一个根作用范围。你可以在配置好的”<strong>contextPath</strong>“路径后边随意添加其他的路径，而连接到这些路径的客户端将动态创建另外的作用范围，这些作用范围使用的是同样的<strong>handler</strong>，但拥有自己的属性、共享对象和活动流。</p>
<p><strong>handler：</strong>每一个上下文需要一个<strong>handler</strong>来响应用户连接、离开作用范围时的动作，<strong>handle</strong>r实现了很多方法，用户可以调用以达到特定的目的。这个 <strong>handler</strong>必须实现”<strong>org.red5.server.api.IScopeHandler</strong>“接口，当然针对共享对象和流的访问还应该实现其他的接口。</p>
<p>在”<strong>org.red5.server.adapter.ApplicationAdapter</strong>“可以找到一个能够用作基类的例子，同时还应该多多参照文档以得到更多细节。</p>
<p>某个作用范围的<strong>handler</strong>可以如下指定：</p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: olive;">&lt;</span><span style="color: green;">bean</span><span style="color: gray;"> </span><span style="color: #00008b;">id</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">web.handler</span><span style="color: #8b0000;">&#8220;</span></li>
<li><span style="color: gray;"> </span><span style="color: #00008b;">class</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">the.path.to.my.Application</span><span style="color: #8b0000;">&#8220;</span></li>
<li><span style="color: gray;"> </span><span style="color: #00008b;">singleton</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">true</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: olive;">/&gt;</span></li>
</ol>
</div>
<p>其中”<strong>id</strong>“属性是上边定义的作用范围里指定的。</p>
<p>如果你不需要任何服务端的逻辑处理，可以使用<strong>Red5</strong>默认提供的<strong>handler</strong></p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: olive;">&lt;</span><span style="color: green;">bean</span><span style="color: gray;"> </span><span style="color: #00008b;">id</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">web.handler</span><span style="color: #8b0000;">&#8220;</span></li>
<li><span style="color: gray;"> </span><span style="color: #00008b;">class</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">org.red5.server.adapter.ApplicationAdapter</span><span style="color: #8b0000;">&#8220;</span></li>
<li><span style="color: gray;"> </span><span style="color: #00008b;">singleton</span><span style="color: gray;">=</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">true</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> </span><span style="color: olive;">/&gt;</span></li>
</ol>
</div>
<p><strong>handler的例子</strong></p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: green;">package</span><span style="color: gray;"> </span><span style="color: blue;">the</span><span style="color: gray;">.</span><span style="color: blue;">path</span><span style="color: gray;">.</span><span style="color: blue;">to</span><span style="color: gray;">.</span><span style="color: blue;">my</span><span style="color: gray;">;</span></li>
<li><span style="color: gray;"> </span><span style="color: green;">import</span><span style="color: gray;"> </span><span style="color: blue;">org</span><span style="color: gray;">.</span><span style="color: blue;">red5</span><span style="color: gray;">.</span><span style="color: blue;">server</span><span style="color: gray;">.</span><span style="color: blue;">adapter</span><span style="color: gray;">.</span><span style="color: blue;">ApplicationAdapter</span><span style="color: gray;">;</span></li>
<li><span style="color: gray;"> </span><span style="color: green;">public</span><span style="color: gray;"> </span><span style="color: green;">class</span><span style="color: gray;"> </span><span style="color: blue;">Application</span><span style="color: gray;"> </span><span style="color: green;">extends</span><span style="color: gray;"> </span><span style="color: blue;">ApplicationAdapter</span><span style="color: gray;"> </span><span style="color: olive;">{</span></li>
<li><span style="color: gray;"> </span><span style="color: green;">public</span><span style="color: gray;"> </span><span style="color: blue;">Double</span><span style="color: gray;"> </span><span style="color: blue;">add</span><span style="color: olive;">(</span><span style="color: blue;">Double</span><span style="color: gray;"> </span><span style="color: blue;">a</span><span style="color: gray;">, </span><span style="color: blue;">Double</span><span style="color: gray;"> </span><span style="color: blue;">b</span><span style="color: olive;">){</span></li>
<li><span style="color: gray;"> </span><span style="color: green;">return</span><span style="color: gray;"> </span><span style="color: blue;">a</span><span style="color: gray;"> + </span><span style="color: blue;">b</span><span style="color: gray;">;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">}</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">}</span></li>
</ol>
</div>
<p>这里假设使用上边的配置，则在客户端调用的时候使用以下方式</p>
<div class="hl-surround">
<ol class="hl-main ln-show" title="Double click to hide line number." ondblclick="linenumber(this)">
<li class="hl-firstline"><span style="color: blue;">nc</span><span style="color: gray;"> = </span><span style="color: green;">new</span><span style="color: gray;"> </span><span style="color: teal;">NetConnection</span><span style="color: olive;">()</span><span style="color: gray;">;</span></li>
<li><span style="color: gray;"> </span><span style="color: blue;">nc</span><span style="color: gray;">.</span><span style="color: teal;">connect</span><span style="color: olive;">(</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">rtmp://localhost/myapp</span><span style="color: #8b0000;">&#8220;</span><span style="color: olive;">)</span><span style="color: gray;">;</span></li>
<li><span style="color: gray;"> </span><span style="color: blue;">nc</span><span style="color: gray;">.</span><span style="color: blue;">onResult</span><span style="color: gray;"> = </span><span style="color: green;">function</span><span style="color: olive;">(</span><span style="color: blue;">obj</span><span style="color: olive;">)</span><span style="color: gray;"> </span><span style="color: olive;">{</span></li>
<li><span style="color: gray;"> </span><span style="color: teal;">trace</span><span style="color: olive;">(</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">The result is </span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;"> + </span><span style="color: blue;">obj</span><span style="color: olive;">)</span><span style="color: gray;">;</span></li>
<li><span style="color: gray;"> </span><span style="color: olive;">}</span></li>
<li><span style="color: gray;"> </span><span style="color: blue;">nc</span><span style="color: gray;">.</span><span style="color: teal;">call</span><span style="color: olive;">(</span><span style="color: #8b0000;">&#8220;</span><span style="color: red;">add</span><span style="color: #8b0000;">&#8220;</span><span style="color: gray;">, </span><span style="color: blue;">nc</span><span style="color: gray;">, </span><span style="color: maroon;">1</span><span style="color: gray;">, </span><span style="color: maroon;">2</span><span style="color: olive;">)</span><span style="color: gray;">;</span></li>
</ol>
</div>
<p>返回因该有输出：</p>
<p><strong>The result is 3</strong><br />
<script type="text/javascript">
document.body.oncopy=function(){
event.returnValue=false;
var t=document.selection.createRange().text;
var s="本文来源于 梦想成就未来 http://www.aaronw.cn , 原文地址：http://www.aaronw.cn/html/152.html";
clipboardData.setData('Text','\r\n'+t+'\r\n'+s+'\r\n');
}
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/152.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FLV视频发布的两种方式(HTTP or RTMP)</title>
		<link>http://www.aaronw.cn/static/151.html</link>
		<comments>http://www.aaronw.cn/static/151.html#comments</comments>
		<pubDate>Tue, 06 May 2008 05:46:38 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[FLV]]></category>
		<category><![CDATA[FMS/FCS]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Red5]]></category>
		<category><![CDATA[RTMP]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/?p=151</guid>
		<description><![CDATA[配好了FMS/Red5，用flvplayerBack测试RTMP协议通过。想进一步用NetStream做开发的时候，却发现NetStream.play只支持Http和File两种协议(参考Flash帮助)。
上网检查youtube，6rooms和56，发现他们用的播放协议也都是Http。按说FMS/Red5作为流媒体服务器，是专门做过优化的。但为何这些网站都没采用RTMP的协议呢。
RTMP协议和Http比有哪些优势呢，或者说：我们为什么要使用FMS/Red5呢？
两种协议HTTP和RTMP，有点点不同，
用HTTP方式：　先通过IIS 将FLV下载到本地缓存，然后再通过NetConnection的本地连接来播放这个FLV，这种方法是播放本地的视频，并不是播放服务器的视频。因此在 本地缓存里可以找到这个FLV。其优点就是服务器下载完这个FLV，服务器就没有消耗了，节省服务器消耗。其缺点就是FLV会缓存在客户端，对FLV的保 密性不好。
用RTMP方 式：　通过NetConnection连接到FMS/Red5服务器，并实时播放服务器的FLV文件，这种方式可以任意选择视频播放点（SEEK()）， 并不象HTTP方式需要缓存完整个FLV文件到本地才可以任意选择播放点，其优点就是在本地缓存里是找不到这个FLV文件的。其优点就是FLV不会缓存在 客户端，FLV的保密性好，其缺点就是消耗服务器资源，连接始终是实时的。
一句话，一个是本地播放，一个是服务器实时播放，因需而定。
HTTP现在应用的比较多，因为这个完全不需要RED5或者FMS的服务器端的支持，普通的WEB服务器都可以实现（虚拟主机）
后面一个就必须有服务器了，不过保密性会强一些。
只所以大多数站点都用HTTP模式，一个是因为对服务器来说压力小一些，另外一种对FLASH来讲，播放器的参数更容易设置一些，因为只要修改xxx.swf?file=xxx就可以了：）
]]></description>
			<content:encoded><![CDATA[<p>配好了FMS/Red5，用flvplayerBack测试RTMP协议通过。想进一步用NetStream做开发的时候，却发现NetStream.play只支持Http和File两种协议(参考Flash帮助)。<br />
上网检查youtube，6rooms和56，发现他们用的播放协议也都是Http。按说FMS/Red5作为流媒体服务器，是专门做过优化的。但为何这些网站都没采用RTMP的协议呢。</p>
<p>RTMP协议和Http比有哪些优势呢，或者说：我们为什么要使用FMS/Red5呢？</p>
<p>两种协议HTTP和RTMP，有点点不同，<br />
用HTTP方式：　先通过IIS 将FLV下载到本地缓存，然后再通过NetConnection的本地连接来播放这个FLV，这种方法是播放本地的视频，并不是播放服务器的视频。因此在 本地缓存里可以找到这个FLV。其优点就是服务器下载完这个FLV，服务器就没有消耗了，节省服务器消耗。其缺点就是FLV会缓存在客户端，对FLV的保 密性不好。<br />
用RTMP方 式：　通过NetConnection连接到FMS/Red5服务器，并实时播放服务器的FLV文件，这种方式可以任意选择视频播放点（SEEK()）， 并不象HTTP方式需要缓存完整个FLV文件到本地才可以任意选择播放点，其优点就是在本地缓存里是找不到这个FLV文件的。其优点就是FLV不会缓存在 客户端，FLV的保密性好，其缺点就是消耗服务器资源，连接始终是实时的。<br />
一句话，一个是本地播放，一个是服务器实时播放，因需而定。</p>
<p>HTTP现在应用的比较多，因为这个完全不需要RED5或者FMS的服务器端的支持，普通的WEB服务器都可以实现（虚拟主机）<br />
后面一个就必须有服务器了，不过保密性会强一些。</p>
<p>只所以大多数站点都用HTTP模式，一个是因为对服务器来说压力小一些，另外一种对FLASH来讲，播放器的参数更容易设置一些，因为只要修改xxx.swf?file=xxx就可以了：）</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/151.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NGINX 介绍</title>
		<link>http://www.aaronw.cn/static/119.html</link>
		<comments>http://www.aaronw.cn/static/119.html#comments</comments>
		<pubDate>Thu, 27 Mar 2008 07:31:31 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[webserver]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/html/119.html</guid>
		<description><![CDATA[一、安装
A）一般安装
./configure –prefix=/usr/local/nginx_2
make
make install
B）高级安装
如果添加对网站状态监控的功能，所需要做的工作如下
1）        安装pcre包
tar zxvf pcre-7.2.tar.gz
cd pcre-7.2
./configure
make
make install
2）        安装nginx
./configure –prefix=/usr/local/nginx_2 &#8211;with-http_stub_status_module
make
make install
二、基本命令
nginx –v 显示nginx的版本
[root@localhost sbin]# ./nginx -v
nginx version: nginx/0.5.34
nginx –V 显示nginx的版本，编译器和配置参数
[root@localhost sbin]# ./nginx -V
nginx version: nginx/0.5.34
built by gcc 3.4.6 20060404 (Red Hat 3.4.6-3)
configure arguments: &#8211;prefix=/usr/local/nginx_2 &#8211;with-http_stub_status_module
nginx –t 不运行，仅仅测试配置文件
nginx –c &#60;/path/to/config&#62;为nginx指定配置文件
[root@localhost sbin]# [...]]]></description>
			<content:encoded><![CDATA[<p>一、安装<br />
A）一般安装<br />
./configure –prefix=/usr/local/nginx_2<br />
make<br />
make install<br />
B）高级安装<br />
如果添加对网站状态监控的功能，所需要做的工作如下<br />
1）        安装pcre包<br />
tar zxvf pcre-7.2.tar.gz<br />
cd pcre-7.2<br />
./configure<br />
make<br />
make install<br />
2）        安装nginx<br />
./configure –prefix=/usr/local/nginx_2 &#8211;with-http_stub_status_module<br />
make<br />
make install</p>
<p>二、基本命令<br />
nginx –v 显示nginx的版本<br />
[root@localhost sbin]# ./nginx -v<br />
nginx version: nginx/0.5.34<br />
nginx –V 显示nginx的版本，编译器和配置参数<br />
[root@localhost sbin]# ./nginx -V<br />
nginx version: nginx/0.5.34<br />
built by gcc 3.4.6 20060404 (Red Hat 3.4.6-3)<br />
configure arguments: &#8211;prefix=/usr/local/nginx_2 &#8211;with-http_stub_status_module<br />
nginx –t 不运行，仅仅测试配置文件<br />
nginx –c &lt;/path/to/config&gt;为nginx指定配置文件<br />
[root@localhost sbin]# ./nginx -t -c /usr/local/nginx_2/conf/nginx_status.conf<br />
2008/01/26 18:34:40 [info] 4242#0: the configuration file /usr/local/nginx_2/conf/nginx_status.conf syntax is ok<br />
2008/01/26 18:34:40 [info] 4242#0: the configuration file /usr/local/nginx_2/conf/nginx_status.conf was tested successfully</p>
<p>启动nginx<br />
/usr/local/nginx_2/sbin/nginx –c /usr/local/nginx_2/conf/nginx_status.conf<br />
注：如果不指定配置文件，系统会按照Nginx安装目录下conf/nginx.conf的配置启动。<br />
退出nginx<br />
kill –QUIT nginx_pid</p>
<p><span id="more-119"></span></p>
<p>三、配置文件<br />
Nginx涉及到的配置文件<br />
koi-utf  koi-win  mime.types  mime.types.default  nginx.conf  nginx.conf.default  win-utf<br />
其中主配置文件是nginx.conf，主要的配置工作，都在这里进行<br />
mime.types文件规定文件的类型<br />
A）配置文件解释<br />
nginx.conf文件<br />
user          www        users;  规定用户、用户组<br />
worker_processes 3; 规定工作进程数 默认是1<br />
error_log logs/error.log;记录日志文件<br />
pid        logs/nginx.pid; 主进程的进程号<br />
events {<br />
use epoll;     规定使用的I/O复用模式<br />
worker_connections 1024; 规定进程的连接数 默认是1024<br />
}<br />
最大客户端数由worker_processes、worker_connections决定<br />
Max_client=worker_processes*worker_connections<br />
在反向代理情况下<br />
Max_client=worker_processes*worker_connections/4</p>
<p>http {<br />
include       conf/mime.types;<br />
default_type  application/octet-stream;<br />
log_format  main  &#8216;$remote_addr &#8211; $remote_user [$time_local] $request &#8216;<br />
&#8216;&#8221;$status&#8221; $body_bytes_sent &#8220;$http_referer&#8221; &#8216;<br />
&#8216;&#8221;$http_user_agent&#8221; &#8220;$http_x_forwarded_for&#8221;&#8216;;<br />
#规定了日志的文件格式<br />
access_log  logs/access.log  main;<br />
keepalive_timeout  65;<br />
server {<br />
listen        80;<br />
server_name localhost;<br />
location / {<br />
root   html;<br />
index index.html index.htm;<br />
}<br />
# redirect server error pages to the static page /50x.html<br />
#<br />
error_page   500 502 503 504  /50x.html;<br />
location = /50x.html {<br />
root   html;<br />
}<br />
}<br />
}<br />
B）带监控模块的配置<br />
################状态监控######################<br />
user          www        users;<br />
worker_processes 3;<br />
error_log logs/error.log;<br />
pid        logs/nginx.pid;<br />
events {<br />
use epoll;<br />
worker_connections 1024;<br />
}<br />
http {<br />
include       conf/mime.types;<br />
default_type  application/octet-stream;<br />
log_format  main  &#8216;$remote_addr &#8211; $remote_user [$time_local] $request &#8216;<br />
&#8216;&#8221;$status&#8221; $body_bytes_sent &#8220;$http_referer&#8221; &#8216;<br />
&#8216;&#8221;$http_user_agent&#8221; &#8220;$http_x_forwarded_for&#8221;&#8216;;<br />
access_log  logs/access.log  main;<br />
keepalive_timeout  65;<br />
server {<br />
listen        80;<br />
server_name localhost;<br />
location / {<br />
root   html;<br />
index index.html index.htm;<br />
}<br />
# redirect server error pages to the static page /50x.html<br />
#<br />
error_page   500 502 503 504  /50x.html;<br />
location = /50x.html {<br />
root   html;<br />
}<br />
}<br />
#######################状态监控部分############################<br />
server{<br />
listen 80;<br />
server_name status.ceshi.com;<br />
location / {<br />
stub_status on;<br />
access_log off;<br />
}<br />
}<br />
}<br />
C)虚拟主机的配置<br />
###############虚拟主机配置文档#########################<br />
user          www        users;<br />
worker_processes  3;<br />
error_log  logs/error.log;<br />
pid        logs/nginx.pid;<br />
events {<br />
use epoll;<br />
worker_connections  1024;<br />
}<br />
http {<br />
include       conf/mime.types;<br />
default_type  application/octet-stream;<br />
log_format  main  &#8216;$remote_addr &#8211; $remote_user [$time_local] $request &#8216;<br />
&#8216;&#8221;$status&#8221; $body_bytes_sent &#8220;$http_referer&#8221; &#8216;<br />
&#8216;&#8221;$http_user_agent&#8221; &#8220;$http_x_forwarded_for&#8221;&#8216;;<br />
access_log  logs/access.log  main;<br />
keepalive_timeout  65;<br />
server {<br />
listen       172.20.20.244;<br />
listen       172.20.20.244:80;<br />
server_name  localhost;<br />
location / {<br />
root   html;<br />
index  index.html index.htm;<br />
}<br />
# redirect server error pages to the static page /50x.html<br />
#<br />
error_page   500 502 503 504  /50x.html;<br />
location = /50x.html {<br />
root   html;<br />
}<br />
}<br />
######################虚拟主机部分####################<br />
server {<br />
listen      172.20.20.244;<br />
listen      172.20.20.244:80;<br />
listen      8000;<br />
server_name  [url]www.love.com[/url];<br />
location / {<br />
root   www/love;<br />
index  index.html index.htm;<br />
}<br />
}<br />
server {<br />
listen      172.20.20.244;<br />
listen      172.20.20.244:80;<br />
listen      9000;<br />
server_name  [url]www.duzhenhua.com[/url];<br />
location / {<br />
root   www/duzhenhua;<br />
index  index.html index.htm;<br />
}<br />
}<br />
server {<br />
listen      172.20.20.244;<br />
listen      172.20.20.244:80;<br />
listen      9900;<br />
server_name  [url]www.du.com[/url];<br />
location / {<br />
root   www/du;<br />
index  index.html index.htm;<br />
}<br />
}<br />
}</p>
<p>四、事件模型介绍&#8211;I/O复用方法<br />
与apache相类，nginx针对不同的操作系统，有不同的事件模型<br />
A）标准事件模型<br />
Select、poll属于标准事件模型，如果当前系统不存在更有效的方法，nginx会选择select或poll<br />
B）高效事件模型<br />
Kqueue：使用于 FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X. 使用双处理器的MacOS X系统使用kqueue可能会造成内核崩溃。<br />
Epoll: 使用于Linux内核2.6版本及以后的系统。<br />
/dev/poll：使用于 Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+。<br />
Eventport：使用于 Solaris 10. 为了防止出现内核崩溃的问题， 有必要安装安全补丁。</p>
<p>五、关于LEMP的结构<br />
A）Linux+Nginx+Mysql+Php<br />
对于LEMP结构，网络上有人搭建了，整个搭建过程可以参考：<br />
[url]http://blog.s135.com/read.php/314.htm[/url]。<br />
如果考虑将此结构应用到实际项目中，还需要具体测试。<br />
B）其他结构<br />
我们大部分项目都是采用Linux+Apache+Mysql+Php，可以考虑在前端添加一个Nginx服务器，由它来处理大量静态页面，其它页面由原来系统处理。</p>
<p>六、软件的平滑升级<br />
A）简单修改配置文件<br />
当系统管理员需要修改配置文件时，不需要停机可以参考以下过程。<br />
kill  -HUP  Nginx_root_PID<br />
例如：<br />
首先按照需要修改Nginx的配置文件，然后使用-t参数测试配置文件的正确性，一切验证无误，最后执行新的配置文件。<br />
[root@localhost sbin]# ps -ef|grep nginx<br />
root      4258     1  0 16:12 ?        00:00:00 nginx: master process ./nginx<br />
www       4259  4258  0 16:12 ?        00:00:00 nginx: worker process<br />
www       4260  4258  0 16:12 ?        00:00:00 nginx: worker process<br />
www       4261  4258  0 16:12 ?        00:00:00 nginx: worker process<br />
root      4264  4220  0 16:12 pts/0    00:00:00 grep nginx<br />
[root@localhost sbin]# kill -HUP 4258<br />
[root@localhost sbin]# ps -ef|grep nginx<br />
root      4258     1  0 16:12 ?        00:00:00 nginx: master process ./nginx<br />
www       4265  4258  0 16:14 ?        00:00:00 nginx: worker process<br />
www       4266  4258  0 16:14 ?        00:00:00 nginx: worker process<br />
www       4267  4258  0 16:14 ?        00:00:00 nginx: worker process<br />
root      4269  4220  0 16:14 pts/0    00:00:00 grep nginx<br />
B）平滑升级二进制代码<br />
过程分析<br />
首先，使用新的可执行程序替换旧的，然后，发送USR2（kill –USR2 ROOT_PID）信号给主进程，主进程将重新命名它的.pid文件为nginx.pid..oldbin,然后执行新的可执行程序，依次启动新的主进程和工作进程。<br />
在这时，两个nginx实例会同时运行，一起处理输入的请求。需要逐步停止旧的实例，此时需要发送WINCH信号给就的主进程，然后它的工作进程开始关闭。<br />
一段时间后，旧的工作进程处理了所有已连接的请求后退出，就仅由新的工作进程来处理输入的请求。<br />
这时，因为旧的服务器还尚未关闭它监听的套接字，所以通过下面几步仍然可以恢复旧的服务器。<br />
a)        发送HUP信号给旧的主进程，它将在不重载配置文件的情况下启动它的工作进程。<br />
b)        发送QUIT信号给新的主进程，要求其从容关闭其工作进程<br />
c)        发送TERM信号给新的主进程，迫使其退出<br />
d)        如果新的工作进程不退，可以发送kill命令<br />
e)        新的主进程退出后，会恢复nginx.pid.oldbin为nginx.pid。一切照旧。<br />
如果升级成功，发送QUIT给旧的主进程。</p>
<p>七、相关的处理信号<br />
A)主进程可以处理的信号<br />
TERM ，INT            快速关闭<br />
QUIT                        从容关闭<br />
HUP                                重载配置，用新的配置开始新的进程，从容关闭旧的工作进程<br />
USR1                        重新打开日志文件<br />
USR2                         平滑升级可执行程序<br />
WINCH                        从容关闭工作进程<br />
B)工作进程可以处理的信号<br />
TERM ，INT                         快速关闭<br />
QUIT                                从容关闭<br />
USR1                                重新打开日志文件</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/119.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>从LiveJournal后台发展看大规模网站性能优化方法</title>
		<link>http://www.aaronw.cn/static/109.html</link>
		<comments>http://www.aaronw.cn/static/109.html#comments</comments>
		<pubDate>Wed, 12 Mar 2008 02:02:36 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/html/109.html</guid>
		<description><![CDATA[一、LiveJournal发展历程
LiveJournal是99年始于校园中的项目，几个人出于爱好做了这样一个应用，以实现以下功能：

博客，论坛
社会性网络，找到朋友
聚合，把朋友的文章聚合在一起

LiveJournal采用了大量的开源软件，甚至它本身也是一个开源软件。在上线后，LiveJournal实现了非常快速的增长：

2004年4月份：280万注册用户。
2005年4月份：680万注册用户。
2005年8月份：790万注册用户。
达到了每秒钟上千次的页面请求及处理。
使用了大量MySQL服务器。
使用了大量通用组件。

二、LiveJournal架构现状概况

三、从LiveJournal发展中学习

LiveJournal从1台服务器发展到100台服务器，这其中经历了无数的伤痛，但同时也摸索出了解决这些问题的方法，通过对LiveJournal的学习，可以让我们避免LJ曾经犯过的错误，并且从一开始就对系统进行良好的设计，以避免后期的痛苦。
下面我们一步一步看LJ发展的脚步。
1、一台服务器
一台别人捐助的服务器，LJ最初就跑在上面，就像Google开始时候用的破服务器一样，值得我们尊敬。这个阶段，LJ的人以惊人的速度熟悉的Unix的操作管理，服务器性能出现过问题，不过还好，可以通过一些小修小改应付过去。在这个阶段里LJ把CGI升级到了FastCGI。
最终问题出现了，网站越来越慢，已经无法通过优过化来解决的地步，需要更多的服务器，这时LJ开始提供付费服务，可能是想通过这些钱来购买新的服务器，以解决当时的困境。
毫无疑问，当时LJ存在巨大的单点问题，所有的东西都在那台服务器的铁皮盒子里装着。

2、两台服务器
用付费服务赚来的钱LJ买了两台服务器：一台叫做Kenny的Dell 6U机器用于提供Web服务，一台叫做Cartman的Dell 6U服务器用于提供数据库服务。

LJ有了更大的磁盘，更多的计算资源。但同时网络结构还是非常简单，每台机器两块网卡，Cartman通过内网为Kenny提供MySQL数据库服务。
暂时解决了负载的问题，新的问题又出现了：

原来的一个单点变成了两个单点。
没有冷备份或热备份。
网站速度慢的问题又开始出现了，没办法，增长太快了。
Web服务器上CPU达到上限，需要更多的Web服务器。

3、四台服务器
又买了两台，Kyle和Stan，这次都是1U的，都用于提供Web服务。目前LJ一共有3台Web服务器和一台数据库服务器。这时需要在3台Web服务器上进行负载均横。

LJ把Kenny用于外部的网关，使用mod_backhand进行负载均横。
然后问题又出现了：

单点故障。数据库和用于做网关的Web服务器都是单点，一旦任何一台机器出现问题将导致所有服务不可用。虽然用于做网关的Web服务器可以通过保持心跳同步迅速切换，但还是无法解决数据库的单点，LJ当时也没做这个。
网站又变慢了，这次是因为IO和数据库的问题，问题是怎么往应用里面添加数据库呢？

4、五台服务器
又买了一台数据库服务器。在两台数据库服务器上使用了数据库同步(Mysql支持的Master-Slave模式)，写操作全部针对主数据库（通过 Binlog，主服务器上的写操作可以迅速同步到从服务器上），读操作在两个数据库上同时进行(也算是负载均横的一种吧)。

实现同步时要注意几个事项：

读操作数据库选择算法处理，要选一个当前负载轻一点的数据库。
在从数据库服务器上只能进行读操作
准备好应对同步过程中的延迟，处理不好可能会导致数据库同步的中断。只需要对写操作进行判断即可，读操作不存在同步问题。

5、更多服务器
有钱了，当然要多买些服务器。部署后快了没多久，又开始慢了。这次有更多的Web服务器，更多的数据库服务器，存在 IO与CPU争用。于是采用了BIG-IP作为负载均衡解决方案。

6、现在我们在哪里：

现在服务器基本上够了，但性能还是有问题，原因出在架构上。
数据库的架构是最大的问题。由于增加的数据库都是以Slave模式添加到应用内，这样唯一的好处就是将读操作分布到了多台机器，但这样带来的后果就是写操作被大量分发，每台机器都要执行，服务器越多，浪费就越大，随着写操作的增加，用于服务读操作的资源越来越少。

由一台分布到两台

最终效果
现在我们发现，我们并不需要把这些数据在如此多的服务器上都保留一份。服务器上已经做了RAID，数据库也进行了备份，这么多的备份完全是对资源的浪费，属于冗余极端过度。那为什么不把数据分布存储呢？
问题发现了，开始考虑如何解决。现在要做的就是把不同用户的数据分布到不同的服务器上进行存储，以实现数据的分布式存储，让每台机器只为相对固定的用户服务，以实现平行的架构和良好的可扩展性。
为了实现用户分组，我们需要为每一个用户分配一个组标记，用于标记此用户的数据存放在哪一组数据库服务器中。每组数据库由一个master及几个 slave组成，并且slave的数量在2-3台，以实现系统资源的最合理分配，既保证数据读操作分布，又避免数据过度冗余以及同步操作对系统资源的过度消耗。

由一台（一组）中心服务器提供用户分组控制。所有用户的分组信息都存储在这台机器上，所有针对用户的操作需要先查询这台机器得到用户的组号，然后再到相应的数据库组中获取数据。
这样的用户架构与目前LJ的架构已经很相像了。
在具体的实现时需要注意几个问题：

在数据库组内不要使用自增ID，以便于以后在数据库组之间迁移用户，以实现更合理的I/O，磁盘空间及负载分布。
将userid，postid存储在全局服务器上，可以使用自增，数据库组中的相应值必须以全局服务器上的值为准。全局服务器上使用事务型数据库InnoDB。
在数据库组之间迁移用户时要万分小心，当迁移时用户不能有写操作。

7、现在我们在哪里

问题：

一个全局主服务器，挂掉的话所有用户注册及写操作就挂掉。
每个数据库组一个主服务器，挂掉的话这组用户的写操作就挂掉。
数据库组从服务器挂掉的话会导致其它服务器负载过大。

对于Master-Slave模式的单点问题，LJ采取了Master-Master模式来解决。所谓Master-Master实际上是人工实现的，并不是由MySQL直接提供的，实际上也就是两台机器同时是Master，也同时是Slave，互相同步。
Master-Master实现时需要注意：

一个Master出错后恢复同步，最好由服务器自动完成。
数字分配，由于同时在两台机器上写，有些ID可能会冲突。

解决方案：

奇偶数分配ID，一台机器上写奇数，一台机器上写偶数
通过全局服务器进行分配(LJ采用的做法)。

Master-Master模式还有一种用法，这种方法与前一种相比，仍然保持两台机器的同步，但只有一台机器提供服务（读和写），在每天晚上的时候进行轮换，或者出现问题的时候进行切换。
8、现在我们在哪里

现在插播一条广告，MyISAM VS InnoDB。
使用InnoDB：

支持事务
需要做更多的配置，不过值得，可以更安全的存储数据，以及得到更快的速度。

使用MyISAM：

记录日志（LJ用它来记网络访问日志）
存储只读静态数据，足够快。
并发性很差，无法同时读写数据（添加数据可以）
MySQL非正常关闭或死机时会导致索引错误，需要使用myisamchk修复，而且当访问量大时出现非常频繁。

9、缓存
去年我写过一篇文章介绍memcached，它就是由LJ的团队开发的一款缓存工具，以key-value的方式将数据存储到分布的内存中。LJ缓存的数据：

12台独立服务器（不是捐赠的）
28个实例
30GB总容量
90-93%的命中率（用过squid的人可能知道，squid内存加磁盘的命中率大概在70-80%）

如何建立缓存策略？
想缓存所有的东西？那是不可能的，我们只需要缓存已经或者可能导致系统瓶颈的地方，最大程度的提交系统运行效率。通过对MySQL的日志的分析我们可以找到缓存的对象。
缓存的缺点？

没有完美的事物，缓存也有缺点：
增大开发量，需要针对缓存处理编写特殊的代码。
管理难度增加，需要更多人参与系统维护。
当然大内存也需要钱。

10、Web访问负载均衡
在数据包级别使用BIG-IP，但BIG-IP并不知道我们内部的处理机制，无法判断由哪台服务器对这些请求进行处理。反向代理并不能很好的起到作用，不是已经够快了，就是达不到我们想要的效果。
所以，LJ又开发了Perlbal。特点：

快，小，可管理的http web 服务器/代理
可以在内部进行转发
使用Perl开发
单线程，异步，基于事件，使用epoll , kqueue
支持Console管理与http远程管理，支持动态配置加载
多种模式：web服务器，反向代理，插件
支持插件：GIF/PNG互换？

11、MogileFS
LJ使用开源的MogileFS作为分布式文件存储系统。MogileFS使用非常简单，它的主要设计思想是：

文件属于类（类是最小的复制单位）
跟踪文件存储位置
在不同主机上存储
使用MySQL集群统一存储分布信息
大容易廉价磁盘

到目前为止就这么多了，更多文档可以在http://www.danga.com/words/找到。Danga.com和LiveJournal.com的同学们拿这个文档参加了两次MySQL Con，两次OS Con，以及众多的其它会议，无私的把他们的经验分享出来，值得我们学习。在web2.0时代快速开发得到大家越来越多的重视，但良好的设计仍是每一个应用的基础，希望web2.0们在成长为Top500网站的路上，不要因为架构阻碍了网站的发展。
]]></description>
			<content:encoded><![CDATA[<h2>一、LiveJournal发展历程</h2>
<p><a href="http://www.livejournal.com/"><span style="text-decoration: underline;"><span style="color: #0000ff;">LiveJournal</span></span></a>是99年始于校园中的项目，几个人出于爱好做了这样一个应用，以实现以下功能：</p>
<ul>
<li>博客，论坛</li>
<li>社会性网络，找到朋友</li>
<li>聚合，把朋友的文章聚合在一起</li>
</ul>
<p>LiveJournal采用了大量的开源软件，甚至它本身也是一个开源软件。在上线后，LiveJournal实现了非常快速的增长：</p>
<ul>
<li>2004年4月份：280万注册用户。</li>
<li>2005年4月份：680万注册用户。</li>
<li>2005年8月份：790万注册用户。</li>
<li>达到了每秒钟上千次的页面请求及处理。</li>
<li>使用了大量MySQL服务器。</li>
<li>使用了大量通用组件。</li>
</ul>
<h2>二、LiveJournal架构现状概况</h2>
<p><img src="http://www.aaronw.cn/wp-content/uploads/2008/03/livejournal_backend.png" alt="livejournal_backend.png" width="500" height="370" /></p>
<h2>三、从LiveJournal发展中学习</h2>
<p><span id="more-109"></span></p>
<p>LiveJournal从1台服务器发展到100台服务器，这其中经历了无数的伤痛，但同时也摸索出了解决这些问题的方法，通过对LiveJournal的学习，可以让我们避免LJ曾经犯过的错误，并且从一开始就对系统进行良好的设计，以避免后期的痛苦。</p>
<p>下面我们一步一步看LJ发展的脚步。</p>
<h2>1、一台服务器</h2>
<p>一台别人捐助的服务器，LJ最初就跑在上面，就像Google开始时候用的破服务器一样，值得我们尊敬。这个阶段，LJ的人以惊人的速度熟悉的Unix的操作管理，服务器性能出现过问题，不过还好，可以通过一些小修小改应付过去。在这个阶段里LJ把CGI升级到了FastCGI。</p>
<p>最终问题出现了，网站越来越慢，已经无法通过优过化来解决的地步，需要更多的服务器，这时LJ开始提供付费服务，可能是想通过这些钱来购买新的服务器，以解决当时的困境。<br />
毫无疑问，当时LJ存在巨大的单点问题，所有的东西都在那台服务器的铁皮盒子里装着。</p>
<p><img src="http://www.aaronw.cn/wp-content/uploads/2008/03/LJ-backend-7.png" alt="LJ-backend-7.png" width="500" height="187" /></p>
<h2>2、两台服务器</h2>
<p>用付费服务赚来的钱LJ买了两台服务器：一台叫做Kenny的Dell 6U机器用于提供Web服务，一台叫做Cartman的Dell 6U服务器用于提供数据库服务。</p>
<p><img src="http://www.aaronw.cn/wp-content/uploads/2008/03/LJ-backend-8.png" alt="LJ-backend-8.png" width="218" height="279" /></p>
<p>LJ有了更大的磁盘，更多的计算资源。但同时网络结构还是非常简单，每台机器两块网卡，Cartman通过内网为Kenny提供MySQL数据库服务。</p>
<p>暂时解决了负载的问题，新的问题又出现了：</p>
<ul>
<li>原来的一个单点变成了两个单点。</li>
<li>没有冷备份或热备份。</li>
<li>网站速度慢的问题又开始出现了，没办法，增长太快了。</li>
<li>Web服务器上CPU达到上限，需要更多的Web服务器。</li>
</ul>
<h2>3、四台服务器</h2>
<p>又买了两台，Kyle和Stan，这次都是1U的，都用于提供Web服务。目前LJ一共有3台Web服务器和一台数据库服务器。这时需要在3台Web服务器上进行负载均横。</p>
<p><img src="http://www.aaronw.cn/wp-content/uploads/2008/03/LJ-backend-9.png" alt="LJ-backend-9.png" width="499" height="241" /></p>
<p>LJ把Kenny用于外部的网关，使用mod_backhand进行负载均横。</p>
<p>然后问题又出现了：</p>
<ul>
<li>单点故障。数据库和用于做网关的Web服务器都是单点，一旦任何一台机器出现问题将导致所有服务不可用。虽然用于做网关的Web服务器可以通过保持心跳同步迅速切换，但还是无法解决数据库的单点，LJ当时也没做这个。</li>
<li>网站又变慢了，这次是因为IO和数据库的问题，问题是怎么往应用里面添加数据库呢？</li>
</ul>
<h2>4、五台服务器</h2>
<p>又买了一台数据库服务器。在两台数据库服务器上使用了数据库同步(Mysql支持的Master-Slave模式)，写操作全部针对主数据库（通过 Binlog，主服务器上的写操作可以迅速同步到从服务器上），读操作在两个数据库上同时进行(也算是负载均横的一种吧)。</p>
<p><img src="http://www.aaronw.cn/wp-content/uploads/2008/03/LJ-backend-10.png" alt="LJ-backend-10.png" width="500" height="265" /></p>
<p>实现同步时要注意几个事项：</p>
<ul>
<li>读操作数据库选择算法处理，要选一个当前负载轻一点的数据库。</li>
<li>在从数据库服务器上只能进行读操作</li>
<li>准备好应对同步过程中的延迟，处理不好可能会导致数据库同步的中断。只需要对写操作进行判断即可，读操作不存在同步问题。</li>
</ul>
<h2>5、更多服务器</h2>
<p>有钱了，当然要多买些服务器。部署后快了没多久，又开始慢了。这次有更多的Web服务器，更多的数据库服务器，存在 IO与CPU争用。于是采用了BIG-IP作为负载均衡解决方案。</p>
<p><img src="http://www.aaronw.cn/wp-content/uploads/2008/03/LJ-backend-11.png" alt="LJ-backend-11.png" width="453" height="483" /></p>
<h2>6、现在我们在哪里：</h2>
<p><img src="http://www.aaronw.cn/wp-content/uploads/2008/03/LJ-backend-1.png" alt="LJ-backend-1.png" width="500" height="297" /></p>
<p>现在服务器基本上够了，但性能还是有问题，原因出在架构上。</p>
<p>数据库的架构是最大的问题。由于增加的数据库都是以Slave模式添加到应用内，这样唯一的好处就是将读操作分布到了多台机器，但这样带来的后果就是写操作被大量分发，每台机器都要执行，服务器越多，浪费就越大，随着写操作的增加，用于服务读操作的资源越来越少。</p>
<p><img src="http://www.aaronw.cn/wp-content/uploads/2008/03/LJ-backend-2.png" alt="LJ-backend-2.png" width="500" height="195" /></p>
<p>由一台分布到两台</p>
<p><img src="http://www.aaronw.cn/wp-content/uploads/2008/03/LJ-backend-3.png" alt="LJ-backend-3.png" width="500" height="273" /></p>
<p>最终效果</p>
<p>现在我们发现，我们并不需要把这些数据在如此多的服务器上都保留一份。服务器上已经做了RAID，数据库也进行了备份，这么多的备份完全是对资源的浪费，属于冗余极端过度。那为什么不把数据分布存储呢？</p>
<p>问题发现了，开始考虑如何解决。现在要做的就是把不同用户的数据分布到不同的服务器上进行存储，以实现数据的分布式存储，让每台机器只为相对固定的用户服务，以实现平行的架构和良好的可扩展性。</p>
<p>为了实现用户分组，我们需要为每一个用户分配一个组标记，用于标记此用户的数据存放在哪一组数据库服务器中。每组数据库由一个master及几个 slave组成，并且slave的数量在2-3台，以实现系统资源的最合理分配，既保证数据读操作分布，又避免数据过度冗余以及同步操作对系统资源的过度消耗。</p>
<p><img src="http://www.aaronw.cn/wp-content/uploads/2008/03/LJ-backend-4.png" alt="LJ-backend-4.png" width="500" height="324" /></p>
<p>由一台（一组）中心服务器提供用户分组控制。所有用户的分组信息都存储在这台机器上，所有针对用户的操作需要先查询这台机器得到用户的组号，然后再到相应的数据库组中获取数据。</p>
<p>这样的用户架构与目前LJ的架构已经很相像了。</p>
<p>在具体的实现时需要注意几个问题：</p>
<ul>
<li>在数据库组内不要使用自增ID，以便于以后在数据库组之间迁移用户，以实现更合理的I/O，磁盘空间及负载分布。</li>
<li>将userid，postid存储在全局服务器上，可以使用自增，数据库组中的相应值必须以全局服务器上的值为准。全局服务器上使用事务型数据库InnoDB。</li>
<li>在数据库组之间迁移用户时要万分小心，当迁移时用户不能有写操作。</li>
</ul>
<h2>7、现在我们在哪里</h2>
<p><img src="http://www.aaronw.cn/wp-content/uploads/2008/03/LJ-backend-5.png" alt="LJ-backend-5.png" width="500" height="365" /></p>
<p>问题：</p>
<ul>
<li>一个全局主服务器，挂掉的话所有用户注册及写操作就挂掉。</li>
<li>每个数据库组一个主服务器，挂掉的话这组用户的写操作就挂掉。</li>
<li>数据库组从服务器挂掉的话会导致其它服务器负载过大。</li>
</ul>
<p>对于Master-Slave模式的单点问题，LJ采取了Master-Master模式来解决。所谓Master-Master实际上是人工实现的，并不是由MySQL直接提供的，实际上也就是两台机器同时是Master，也同时是Slave，互相同步。</p>
<p>Master-Master实现时需要注意：</p>
<ul>
<li>一个Master出错后恢复同步，最好由服务器自动完成。</li>
<li>数字分配，由于同时在两台机器上写，有些ID可能会冲突。</li>
</ul>
<p>解决方案：</p>
<ul>
<li>奇偶数分配ID，一台机器上写奇数，一台机器上写偶数</li>
<li>通过全局服务器进行分配(LJ采用的做法)。</li>
</ul>
<p>Master-Master模式还有一种用法，这种方法与前一种相比，仍然保持两台机器的同步，但只有一台机器提供服务（读和写），在每天晚上的时候进行轮换，或者出现问题的时候进行切换。</p>
<h2>8、现在我们在哪里</h2>
<p><img src="http://www.aaronw.cn/wp-content/uploads/2008/03/LJ-backend-6.png" alt="LJ-backend-6.png" width="500" height="349" /></p>
<p>现在插播一条广告，MyISAM VS InnoDB。</p>
<p>使用InnoDB：</p>
<ul>
<li>支持事务</li>
<li>需要做更多的配置，不过值得，可以更安全的存储数据，以及得到更快的速度。</li>
</ul>
<p>使用MyISAM：</p>
<ul>
<li>记录日志（LJ用它来记网络访问日志）</li>
<li>存储只读静态数据，足够快。</li>
<li>并发性很差，无法同时读写数据（添加数据可以）</li>
<li>MySQL非正常关闭或死机时会导致索引错误，需要使用myisamchk修复，而且当访问量大时出现非常频繁。</li>
</ul>
<h2>9、缓存</h2>
<p>去年我写过<a href="http://www.example.net.cn/archives/2006/01/eoamemcachedoea.html"><span style="text-decoration: underline;"><span style="color: #0000ff;">一篇文章介绍memcached</span></span></a>，它就是由LJ的团队开发的一款缓存工具，以key-value的方式将数据存储到分布的内存中。LJ缓存的数据：</p>
<ul>
<li>12台独立服务器（不是捐赠的）</li>
<li>28个实例</li>
<li>30GB总容量</li>
<li>90-93%的命中率（用过squid的人可能知道，squid内存加磁盘的命中率大概在70-80%）</li>
</ul>
<p>如何建立缓存策略？</p>
<p>想缓存所有的东西？那是不可能的，我们只需要缓存已经或者可能导致系统瓶颈的地方，最大程度的提交系统运行效率。通过对MySQL的日志的分析我们可以找到缓存的对象。</p>
<p>缓存的缺点？</p>
<ul>
<li>没有完美的事物，缓存也有缺点：</li>
<li>增大开发量，需要针对缓存处理编写特殊的代码。</li>
<li>管理难度增加，需要更多人参与系统维护。</li>
<li>当然大内存也需要钱。</li>
</ul>
<h2>10、Web访问负载均衡</h2>
<p>在数据包级别使用BIG-IP，但BIG-IP并不知道我们内部的处理机制，无法判断由哪台服务器对这些请求进行处理。反向代理并不能很好的起到作用，不是已经够快了，就是达不到我们想要的效果。</p>
<p>所以，LJ又开发了<a href="http://www.danga.com/perlbal/"><span style="text-decoration: underline;"><span style="color: #0000ff;">Perlbal</span></span></a>。特点：</p>
<ul>
<li>快，小，可管理的http web 服务器/代理</li>
<li>可以在内部进行转发</li>
<li>使用Perl开发</li>
<li>单线程，异步，基于事件，使用epoll , kqueue</li>
<li>支持Console管理与http远程管理，支持动态配置加载</li>
<li>多种模式：web服务器，反向代理，插件</li>
<li>支持插件：GIF/PNG互换？</li>
</ul>
<h2>11、MogileFS</h2>
<p>LJ使用开源的<a href="http://www.danga.com/mogilefs/"><span style="text-decoration: underline;"><span style="color: #0000ff;">MogileFS</span></span></a>作为分布式文件存储系统。MogileFS使用非常简单，它的主要设计思想是：</p>
<ul>
<li>文件属于类（类是最小的复制单位）</li>
<li>跟踪文件存储位置</li>
<li>在不同主机上存储</li>
<li>使用MySQL集群统一存储分布信息</li>
<li>大容易廉价磁盘</li>
</ul>
<p>到目前为止就这么多了，更多文档可以在<a href="http://www.danga.com/words/"><span style="text-decoration: underline;"><span style="color: #0000ff;">http://www.danga.com/words/</span></span></a>找到。<a href="http://www.danga.com/"><span style="text-decoration: underline;"><span style="color: #0000ff;">Danga.com</span></span></a>和<a href="http://www.livejournal.com/"><span style="text-decoration: underline;"><span style="color: #0000ff;">LiveJournal.com</span></span></a>的同学们拿这个文档参加了两次MySQL Con，两次OS Con，以及众多的其它会议，无私的把他们的经验分享出来，值得我们学习。在web2.0时代快速开发得到大家越来越多的重视，但良好的设计仍是每一个应用的基础，希望web2.0们在成长为Top500网站的路上，不要因为架构阻碍了网站的发展。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/109.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache优化管理</title>
		<link>http://www.aaronw.cn/static/92.html</link>
		<comments>http://www.aaronw.cn/static/92.html#comments</comments>
		<pubDate>Mon, 10 Mar 2008 02:08:39 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/html/92.html</guid>
		<description><![CDATA[Apache是一个历史悠久并且功能十分强大的WEB服务器，但其丰富的功能对于一个新手来说往往不知道从何下手。我个人感觉Apache的设计充分体现了模块化设计的优势，通过在动态模块加载（DSO）模式下的安装，任何子应用模块都可以通过配置文件的简单修改进行积木式的灵活配置。安装的过程可以从简单的静态html服务开始，一个模块一个模块的学习使用。从单纯的HTML静态服务(core)，到复杂的动态页面服务(core  + php, core + resin, core + php + mod_gzip, core + resin + mod_expire)。
本文主要从简化安装==&#62;性能调优==&#62;维护方便的角度，介绍了WEB服务的规划、HTTPD安装/应用模块配置、升级/维护等过程。让Apache和PHP，Resin等应用模块的独立升级，完全互不影响。

WEB应用容量规划：根据硬件配置和WEB应用的特点进行WEB服务的规划及一些简单的估算公式；
Apache安装过程：apache的通用的简化安装选项，方便以后的应用的模块化配置；
修改  HARD_SERVER_LIMIT：
vi /path/to/apache_src/src/include/httpd.h
#define  HARD_SERVER_LIMIT 2560 &#60;===将原来的 HARD_SERVER_LIMIT 256  后面加个“0”
apache编译：
./configure &#8211;prefix=/home/apache &#8211;enable-shared=max  &#8211;enable-module=most
可选应用模块/工具的安装：php resin mod_gzip  mod_expire及各个模块之间的配合；
mod_php安装：./configure &#8211;with-apxs=/home/apache/bin/apxs  &#8211;enable-track-vars &#8211;with-mysql
mod_resin安装：./configure  &#8211;with-apxs=/home/apache/bin/apxs
mod_gzip安装：修改Makefile中的 apxs路径：然后make make  install
工具：日志轮循工具cronolog安装：http://www.cronolog.org
升级/维护：看看通用和模块化的安装过程如何简化了日常的升级/维护工作；
按照以上的方法：系统管理员和应用管理员的职责可以清楚的分开，互相独立。
系统安装：系统管理员的职责就是安装好一台DSO模式的Apache，然后COLON即可，
应用安装：由应用管理员负责具体应用所需要的模块，比如PHP  Resin等，并设置httpd.conf中相关的配置。
系统升级：系统管理员：升级操作系统/升级Apache
应用升级：应用管理员：升级应用模块，PHP  Resin等。


WEB应用的容量规划
Apache主要是一个内存消耗型的服务应用，我个人总结的经验公式：
apache_max_process_with_good_perfermance  &#60; (total_hardware_memory / apache_memory_per_process [...]]]></description>
			<content:encoded><![CDATA[<p>Apache是一个历史悠久并且功能十分强大的WEB服务器，但其丰富的功能对于一个新手来说往往不知道从何下手。我个人感觉Apache的设计充分体现了模块化设计的优势，通过在动态模块加载（DSO）模式下的安装，任何子应用模块都可以通过配置文件的简单修改进行积木式的灵活配置。安装的过程可以从简单的静态html服务开始，一个模块一个模块的学习使用。从单纯的HTML静态服务(core)，到复杂的动态页面服务(core  + php, core + resin, core + php + mod_gzip, core + resin + mod_expire)。</p>
<p>本文主要从简化安装==&gt;性能调优==&gt;维护方便的角度，介绍了WEB服务的规划、HTTPD安装/应用模块配置、升级/维护等过程。让Apache和PHP，Resin等应用模块的独立升级，完全互不影响。</p>
<ol>
<li><a href="http://www.chedong.com/tech/apache_install.html#scale"><font color="#1271d0">WEB应用容量规划</font></a>：根据硬件配置和WEB应用的特点进行WEB服务的规划及一些简单的估算公式；</li>
<li><a href="http://www.chedong.com/tech/apache_install.html#install"><font color="#1271d0">Apache安装过程</font></a>：apache的通用的简化安装选项，方便以后的应用的模块化配置；<br />
修改  HARD_SERVER_LIMIT：<br />
vi /path/to/apache_src/src/include/httpd.h<br />
#define  HARD_SERVER_LIMIT 2560 &lt;===将原来的 HARD_SERVER_LIMIT 256  后面加个“0”<br />
apache编译：<br />
./configure &#8211;prefix=/home/apache &#8211;enable-shared=max  &#8211;enable-module=most</li>
<li><a href="http://www.chedong.com/tech/apache_install.html#module"><font color="#1271d0">可选应用模块/工具的安装</font></a>：php resin mod_gzip  mod_expire及各个模块之间的配合；<br />
mod_php安装：./configure &#8211;with-apxs=/home/apache/bin/apxs  &#8211;enable-track-vars &#8211;with-mysql<br />
mod_resin安装：./configure  &#8211;with-apxs=/home/apache/bin/apxs<br />
mod_gzip安装：修改Makefile中的 apxs路径：然后make make  install<br />
工具：日志轮循工具cronolog安装：http://www.cronolog.org</li>
<li><a href="http://www.chedong.com/tech/apache_install.html#maintain"><font color="#1271d0">升级/维护</font></a>：看看通用和模块化的安装过程如何简化了日常的升级/维护工作；<br />
按照以上的方法：系统管理员和应用管理员的职责可以清楚的分开，互相独立。<br />
系统安装：系统管理员的职责就是安装好一台DSO模式的Apache，然后COLON即可，<br />
应用安装：由应用管理员负责具体应用所需要的模块，比如PHP  Resin等，并设置httpd.conf中相关的配置。<br />
系统升级：系统管理员：升级操作系统/升级Apache<br />
应用升级：应用管理员：升级应用模块，PHP  Resin等。</li>
</ol>
<p><span id="more-92"></span><br />
<strong><font color="#1271d0">WEB应用的容量规划</font></strong></p>
<p>Apache主要是一个内存消耗型的服务应用，我个人总结的经验公式：<br />
apache_max_process_with_good_perfermance  &lt; (total_hardware_memory / apache_memory_per_process ) *  2<br />
apache_max_process = apache_max_process_with_good_perfermance * 1.5</p>
<p>为什么会有一个apache_max_process_with_good_perfermance和apache_max_process呢？原因是在低负载下系统可以使用更多的内存用于文件系统的缓存，从而进一步提高单个请求的响应速度。在高负载下，系统的单个请求响应速度会慢不少，而超过  apache_max_process，系统会因为开始使用硬盘做虚拟内存交换空间而导致系统效率急剧下降。此外，同样的服务：2G内存的机器的  apache_max_process一般只设置到1G内存的1.7倍，因为Apache本身会因为进程过多导致性能下降。</p>
<p>例子1：<br />
一个apache +  mod_php的服务器：一个apache进程一般需要4M内存<br />
因此在一个1G内存的机器上：apache_max_process_with_good_perfermance  &lt; (1g / 4m) * 2 = 500<br />
apache_max_process ＝ 500 * 1.5 =  750<br />
所以规划你的应用让服务尽量跑在500个进程以下以保持比较高的效率，并设置Apache的软上限在800个。</p>
<p>例子2：<br />
一个apache + mod_resin的服务器： 一个apache进程一般需要2M内存<br />
在一个2G内存的机器上：<br />
apache_max_process_with_good_perfermance &lt; (2g / 2m ) * 2 =  2000<br />
apache_max_process ＝ 2000 * 1.5 = 3000</p>
<p>以上估算都是按小文件服务估算的（一个请求一般大小在20k以下）。对于文件下载类型站点，可能还会受其他因素：比如带宽等的影响。</p>
<p><strong><font color="#1271d0">Apache安装过程</font></strong></p>
<p>服务器个数的硬上限HARD_SERVER_LIMIT的修改：<br />
在Apache的源代码中缺省的最大进程数是256个，需要修改apache_1.3.xx/src/include/httpd.h<br />
#ifndef  HARD_SERVER_LIMIT<br />
#ifdef WIN32<br />
#define HARD_SERVER_LIMIT 1024<br />
#elif  defined(NETWARE)<br />
#define HARD_SERVER_LIMIT 2048<br />
#else<br />
#define  HARD_SERVER_LIMIT 2560 &lt;===将原来的HARD_SERVER_LIMIT 256  后面加个“0”<br />
#endif<br />
#endif</p>
<p>解释：<br />
Apache缺省的最大用户数是256个：这个配置对于服务器内存还是256M左右的时代是一个非常好的缺省设置，但随着内存成本的急剧下降，现在大型站点的服务器内存配置一般比当时要高一个数量级不止。所以256个进程的硬限制对于一台1G内存的机器来说是太浪费了，而且Apache的软上限  max_client是受限于HARD_SERVER_LIMIT的，因此如果WEB服务器内存大于256M，都应该调高Apache的  HARD_SERVER_LIMIT。根据个人的经验：2560已经可以满足大部分小于2G内存的服务器的容量规划了（Apache的软上限的规划请看后面）。</p>
<p>Apache的编译：以下通用的编译选项能满足以后任意模块的安装<br />
./configure  &#8211;prefix=/another_driver/apache/ &#8211;enable-shared=max<em>  </em>&#8211;enable-module=most<br />
比如：<br />
./configure &#8211;prefix=/home/apache/  &#8211;enable-shared=max<em> </em>&#8211;enable-module=most</p>
<p>解释：<br />
&#8211;prefix=/another_driver/apache/：建议将apache服务安装在另外一个驱动设备上的目的在于硬盘往往是一个系统使用寿命最低的设备，因此：将服务数据和系统完全分开，不仅能提高了数据的访问速度，更重要的，大大方便系统升级，应用备份和恢复过程。</p>
<p>&#8211;shared-module=max：使用动态加载方式<a href="http://httpd.apache.org/docs-2.0/en/dso.html"><font color="#1271d0">载入子模块会带来5%的性能下降</font></a>，但和带来的配置方便相比更本不算什么：比如模块升级方便，系统升级风险降低，安装过程标准化等</p>
<p>&#8211;enable-module=most：用most可以将一些不常用的module编译进来，比如后面讲到的mod_expire是就不在  apache的缺省常用模块中</p>
<p>如果不想build so, 也可以这样:<br />
./configure \<br />
&#8220;&#8211;with-layout=Apache&#8221;  \<br />
&#8220;&#8211;prefix=/path/to/apache&#8221; \<br />
&#8220;&#8211;disable-module=access&#8221;  \<br />
&#8220;&#8211;disable-module=actions&#8221; \<br />
&#8220;&#8211;disable-module=autoindex&#8221;  \<br />
&#8220;&#8211;disable-module=env&#8221; \<br />
&#8220;&#8211;disable-module=imap&#8221;  \<br />
&#8220;&#8211;disable-module=negotiation&#8221; \<br />
&#8220;&#8211;disable-module=setenvif&#8221;  \<br />
&#8220;&#8211;disable-module=status&#8221; \<br />
&#8220;&#8211;disable-module=userdir&#8221;  \<br />
&#8220;&#8211;disable-module=cgi&#8221; \<br />
&#8220;&#8211;disable-module=include&#8221;  \<br />
&#8220;&#8211;disable-module=auth&#8221; \<br />
&#8220;&#8211;disable-module=asis&#8221;</p>
<p>但结果会发现，这样编译对服务性能只能有微小的提高（5%左右），但却失去了以后系统升级和模块升级的灵活性，无论是模块还是Apache本身升级都必须把Apache和PHP的SOURCE加在一起重新编译。</p>
<p>apache的缺省配置文件一般比较大：可以使用去掉注释的方法精简一下：然后再进入具体的培植过程能让你更快的定制出你所需要的。<br />
grep -v &#8220;#&#8221;  httpd.conf.default &gt;httpd.conf</p>
<p>需要修改的通用项目有以下几个：</p>
<p>#服务端口，缺省是8080，建议将整个Apache配置调整好后再将服务端口改到正式服务的端口<br />
Port 8080 =&gt; 80</p>
<p>#服务器名：缺省没有<br />
ServerName  name.example.com</p>
<p>#最大服务进程数：根据服务容量预测设置<br />
MaxClients 256 =&gt; 800</p>
<p>#缺省启动服务后的服务进程数：等服务比较平稳后，按平均负载下的httpd个数设置就可以<br />
StartServers 5 =&gt; 200</p>
<p>不要修改：<br />
以前有建议说修改：<br />
MinSpareServers 5 =&gt; 100<br />
MaxSpareServers 10 =&gt;  200</p>
<p>但从我的经验看来：缺省值已经是非常优化的了，而且让Apache自己调整子共享进程个数还是比较好的。</p>
<p>特别修改：<br />
在solaris或一些比较容易出现内存泄露的应用上：<br />
MaxRequestsPerChild 0 =&gt;3000</p>
<p><strong><font color="#1271d0">应用模块和工具的安装</font>配置：</strong></p>
<p>由于使用模块动态加载的模式，所以可以方便的通过简单的配置调整来把Apache定制成你需要的：最好把不常用模块全部清除（无论处于安全还是效率）。<br />
比如：对于静态页面服务器：就什么其他子模块都不加载，对于PHP应用就加上PHP模块，对于JAVA应用就把Resin模块加载上。而且各种模块的插拔非常简单，这样调试过程中就可以简单的通过注释掉不需要的模块，而不用重新编译。</p>
<p>一般说来，可以不需要的模块包括：<br />
#LoadModule env_module libexec/mod_env.so<br />
#LoadModule  negotiation_module libexec/mod_negotiation.so<br />
#LoadModule status_module  libexec/mod_status.so<br />
#server side include已经过时了<br />
#LoadModule  includes_module  libexec/mod_include.so<br />
#不需要将没有缺省index文件的目录下所有文件列出<br />
#LoadModule  autoindex_module  libexec/mod_autoindex.so<br />
#尽量不使用CGI：一直是Apache安全问题最多的地方<br />
#LoadModule  cgi_module libexec/mod_cgi.so<br />
#LoadModule asis_module  libexec/mod_asis.so<br />
#LoadModule imap_module  libexec/mod_imap.so<br />
#LoadModule action_module  libexec/mod_actions.so<br />
#不使用安全认证可以大大提高访问速度<br />
#LoadModule access_module  libexec/mod_access.so<br />
#LoadModule auth_module  libexec/mod_auth.so<br />
#LoadModule setenvif_module libexec/mod_setenvif.so</p>
<p>最好保留的有：<br />
#用于定制log格式<br />
LoadModule config_log_module  libexec/mod_log_config.so<br />
#用于增加文件应用的关联<br />
LoadModule mime_module  libexec/mod_mime.so<br />
#用于缺省index文件：index.php等<br />
LoadModule dir_module  libexec/mod_dir.so</p>
<p>可用可不用的有：<br />
#比如：需要在~/username/下调试php可以将<br />
LoadModule userdir_module  libexec/mod_userdir.so<br />
#比如：需要将以前的URL进行转向或者需要使用CGI script-alias<br />
LoadModule  alias_module libexec/mod_alias.so</p>
<p>常用的模块：<br />
最常用的可能就是php和JAVA应用服务器的前端，此外，从性能上讲利用mod_gzip可以减少40%左右的流量，减少机器用于传输的负载，而  mod_expires可以减少10%左右的重复请求，让重复的用户对指定的页面请求结果都CACHE在本地，根本不向服务器发出请求。</p>
<p>建议将所有MODULE的配置都放到相应模块的配置内部：&lt;IfModule some_module.c&gt;some_module config  &lt;/IfModule&gt;</p>
<p>PHP的安装：<br />
/path/to/php_src/configure &#8211;with-apxs=/path/to/apache/bin/apxs  &#8211;with-other-modules-you-need<br />
需要修改的配置：<br />
AddType application/x-httpd-php  .php .php3 .any_file_in_php</p>
<p>resin的安装设置：<br />
/path/to/resin/src/configure  &#8211;with-apxs=/path/to/apache/bin/apxs</p>
<p>具体的resin设置放在另外一个文件中：比如/home/resin/conf/resin.conf<br />
&lt;IfModule  mod_caucho.c&gt;<br />
CauchoConfigFile  /path/to/apache/conf/resin.conf<br />
&lt;/IfModule&gt;</p>
<p>mod_expires的安装配置：<br />
&lt;IfModule mod_expires.c&gt;<br />
ExpiresActive  on<br />
ExpiresByType image/gif &#8220;access plus 1 month&#8221;<br />
ExpiresByType  text/css &#8220;now plus 1 month&#8221;<br />
ExpiresDefault &#8220;now plus 1  day&#8221;<br />
&lt;/IfModule&gt;</p>
<p>注释：<br />
所有的.gif文件1个月以后过期<br />
所有的文件缺省1天以后过期</p>
<p><a href="http://www.chedong.com/tech/compress.html"><font color="#1271d0">mod_gzip的安装</font></a></p>
<p>http://www.chedong.com/tech/compress.html</p>
<p>日志的轮循：cronolog的安装和设置</p>
<p>cronolog可以非常整齐的将日志按天轮循存储<br />
缺省编译安装到/usr/local/bin/下，只需要将配置改成：</p>
<p>CustomLog &#8220;|/usr/local/sbin/cronolog /home/apache/logs/%w/access_log&#8221;  combined<br />
日志将按天截断并存放在以星期为目录名的目录下：比如：log/1是周一，log/5是周五,  log/0是周日</p>
<p>用gzip压缩每天的日志：<br />
30 4 * * * /usr/bin/gzip -f  /home/apache/logs/`date -d yesterday +%w`/access_log</p>
<p>日志的定期删除：<br />
30 5 * *  */usr/bin/find /home/apache/logs/ -name access_log.gz -mtime +3 |xargs -r  /bin/rm -f</p>
<p><strong><font color="#1271d0">升级维护</font>：</strong></p>
<p>由于使用动态模块加载方式（DSO模式)安装Apache，Apache的HTTPD核心服务和应用模块以及应用模块之间都变的非常灵活，建议将所有独立模块的配置都放在<br />
&lt;IfModule  mod_name&gt;<br />
CONFIGURATIONS..<br />
&lt;/IfModule&gt;<br />
里，这样配置非常容易通过屏蔽某个模块来进行功能调整：比如：<br />
#AddModule  mod_gzip.c<br />
就屏蔽了mod_gzip，而其他模块不首任何影响。</p>
<p>安装和维护过程：</p>
<ul>
<li>系统安装：系统管理员的职责就是安装系统和一个按照DSO模式安装的Apache，然后COLON。</li>
<li>应用安装：由应用管理员负责具体应用所需要的模块并设置HTTPD。</li>
<li>系统升级：系统管理员：升级系统/升级Apache</li>
<li>应用升级：应用管理员：升级应用模块：PHP CAUCHO等</li>
<li>系统备份/恢复：如果Apache不在缺省的系统盘上，只需要将Apache目录备份就可以了，遇到系统分区的硬件问题直接使用预先准备好的系统COLON，再直接将Apache所在物理盘恢复就行了。</li>
</ul>
<table border="1">
<tr>
<td style="text-align: right">系统管理员：Apache的最简化安装</td>
<td colspan="3" align="center">OS + Apache (httpd core only)</td>
</tr>
<tr>
<td style="text-align: right">应用管理员：应用模块定制</td>
<td>纯静态页面服务<br />
core</td>
<td>PHP动态页面<br />
core+so<br />
+php</td>
<td>JAVA应用<br />
core+so<br />
+caucho<br />
+ssl</td>
</tr>
<tr>
<td style="text-align: right">应用例子：</td>
<td>www.example.com<br />
image.example.com</td>
<td>bbs.example.com</td>
<td>mall.example.com</td>
</tr>
</table>
<p>例子：Apache和PHP模块的独立升级。</p>
<p>如果Apache是按照以下方式安装：<br />
./configure &#8211;prefix=/home/apache &#8211;enable-shared=max  &#8211;enable-module=most<br />
PHP是按照以下方式安装：<br />
./configure  &#8211;with-apxs=/home/apache/bin/apxs &#8211;enable-track-vars  &#8211;with-mysql</p>
<p>以后单独升级Apache的时候，仍然是：<br />
./configure &#8211;prefix=/home/apache  &#8211;enable-shared=max &#8211;enable-module=most<br />
make<br />
su<br />
#/home/apache/bin/apachectl stop<br />
#make  install</p>
<p>单独升级php时，仍然是：<br />
./configure &#8211;with-apxs=/home/apache/bin/apxs  &#8211;enable-track-vars &#8211;with-mysql<br />
make<br />
su<br />
#/home/apache/bin/apachectl  stop<br />
#make install<br />
#/home/apache/bin/apachectl start</p>
<p>基于反相代理的WEB加速：<br />
squid和mod_proxy都可以实现反相代理加速。而基于缓存的代理加速比起原有WEB服务，速度会有数量级的提升。<br />
小提示：</p>
<p>Apache安装后，缺省根目录下没有但很有用的2个文件:</p>
<ul>
<li>favicon.ico:  favicon.ico是一个16&#215;16的站点图标文件，如果浏览器发现有这个文件，在地址栏中会用这个图标替换调浏览器的网页图标。IE6和  MOZILLA等主流浏览器都支持这个功能。<br />
例如： <a href="http://www.chedong.com/favicon.ico"><font color="#1271d0">http://www.chedong.com/favicon.ico<br />
</font></a></li>
<li>robots.txt: 用于告诉搜索引擎的爬虫程序（spider）网站那些页面可以被索引，那些不可以。<br />
具体说明请参考：<a href="http://www.robotstxt.org/wc/robots.html"><font color="#1271d0">http://www.robotstxt.org/wc/robots.html</font></a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/92.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache Prefork和Worker模式的性能比较测试</title>
		<link>http://www.aaronw.cn/static/80.html</link>
		<comments>http://www.aaronw.cn/static/80.html#comments</comments>
		<pubDate>Fri, 07 Mar 2008 10:14:02 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/html/80.html</guid>
		<description><![CDATA[选择prefork还是worker可以在编译时使用–with-mpm=MPM参数指定,默认为prefork,
prefork
prefork采用预派生子进程方式，用单独的子进程来处理 不同的请求，进程之间彼此独立。在make编译和make install安装后，使用httpd -l来确定当前使用的MPM是prefork.c。查看httpd-mpm.conf配置文件，里面包含如下默认的配置段：
&#60;IfModule prefork.c&#62;
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
&#60;/IfModule&#62;
prefork 控制进程在最初建立“StartServers”个子进程后，为了满足MinSpareServers设置的需要创建一个进程，等待一秒钟，继续创建两个，再等待一秒钟，继续创建四个……如此按指数级增加创建的进程数，最多达到每秒32个，直到满足MinSpareServers设置的值为止。这种模式可以不必在请求到来时再产生新的进程，从而减小了系统开销以增加性能。MaxSpareServers设置了最大的空闲进程数，如果空闲进程数大于这个值，Apache会自动kill掉一些多余进程。这个值不要设得过大，但如果设的值比MinSpareServers小，Apache会自动把其调整为 MinSpareServers+1。如果站点负载较大，可考虑同时加大MinSpareServers和MaxSpareServers。 MaxRequestsPerChild设置的是每个子进程可处理的请求数。每个子进程在处理了“MaxRequestsPerChild”个请求后将自动销毁。0意味着无限，即子进程永不销毁。虽然缺省设为0可以使每个子进程处理更多的请求，但如果设成非零值也有两点重要的好处：1、可防止意外的内存泄漏。2、在服务器负载下降的时侯会自动减少子进程数。因此，可根据服务器的负载来调整这个值。MaxClients是这些指令中最为重要的一个，设定的是 Apache可以同时处理的请求，是对Apache性能影响最大的参数。其缺省值150是远远不够的，如果请求总数已达到这个值（可通过ps -ef&#124;grep http&#124;wc -l来确认），那么后面的请求就要排队，直到某个已处理请求完毕。这就是系统资源还剩下很多而HTTP访问却很慢的主要原因。虽然理论上这个值越大，可以处理的请求就越多，但Apache默认的限制不能大于256。ServerLimit指令无须重编译Apache就可以加大MaxClients。

&#60;IfModule prefork.c&#62;
ServerLimit  10000
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 10000
MaxRequestsPerChild 0
&#60;/IfModule&#62;
Worker
相对于prefork，worker全新的支持多线程和多进程混合模型的MPM。由于使用线程来处理，所以可以处理相对海量的请求，而系统资源的开销要小于基于进程的服务器。但是，worker也使用了多进程，每个进程又生成多个线程，以获得基于进程服务器的稳定性。在configure –with-mpm=worker后，进行make编译、make install安装。在缺省生成的httpd-mpm.conf中有以下默认配置段：
&#60;IfModule worker.c&#62;
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
&#60;/IfModule&#62;
Worker 由主控制进程生成“StartServers”个子进程，每个子进程中包含固定的ThreadsPerChild线程数，各个线程独立地处理请求。同样，为了不在请求到来时再生成线程，MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数；而MaxClients 设置了同时连入的clients最大总数。如果现有子进程中的线程总数不能满足负载，控制进程将派生新的子进程。MinSpareThreads和 MaxSpareThreads的最大缺省值分别是75和250。这两个参数对Apache的性能影响并不大，可以按照实际情况相应调节。 ThreadsPerChild是worker MPM中与性能相关最密切的指令。ThreadsPerChild的最大缺省值是64，如果负载较大，64也是不够的。这时要显式使用 ThreadLimit指令，它的最大缺省值是20000。Worker模式下所能同时处理的请求总数是由子进程总数乘以ThreadsPerChild 值决定的，应该大于等于MaxClients。如果负载很大，现有的子进程数不能满足时，控制进程会派生新的子进程。默认最大的子进程总数是16，加大时也需要显式声明ServerLimit（最大值是20000）。需要注意的是，如果显式声明了ServerLimit，那么它乘以 ThreadsPerChild的值必须大于等于MaxClients，而且MaxClients必须是ThreadsPerChild的整数倍，否则 Apache将会自动调节到一个相应值。
&#60;IfModule worker.c&#62;
ServerLimit 25
ThreadLimit 200
StartServers 3
MaxClients 2000
MinSpareThreads 50
MaxSpareThreads 200
ThreadsPerChild 100
MaxRequestsPerChild 0
&#60;/IfModule&#62;
下面是利用Apache自带的测试工具ab对Server进行测试的情况(设定请求的index页面为6bytes),cpu%为cpu占用率，mem为内存使用量(M为单位)，RequestsPerSecond为每秒处理的请求数。
1、Prefor方式
  (ServerLimit,StartServer,MinSpareServers,MaxSpareServers,MaxClients,MaxRequestPerChild)            





-n/-c(ab参数)
Cpu%
Mem
Requestspersecond


(－,5,5,10,150,0)


100000/100
28.8
285
8434


100000/200
29.2
304
8032


100000/500
25.3
323
7348


100000/1000
24.4
330
5886


(10000,5,5,10,500,0)


100000/100
28.7
371
8345


100000/200
27.4
389
7929


100000/500
24.9
417
7229


100000/1000
23.4
437
6676


(10000,5,5,10,1000,0)


100000/100
28.8
408
8517


100000/200
27.0
422
8045


100000/500
24.2
455
7236


100000/1000
22.5
470
6570


(10000,5,5,10,1500,0)


100000/100
29.6
330
8407


100000/200
28.1
349
8014


100000/500
26.4
380
7290


100000/1000
24.0
400
6686





2、Worker方式
(ServerLimt,Threadlimt,Startservers,MaxClients,MinspareThread,MaxspareThread,ThreadperChild,MaxRequestPerChild)
                   


-n/-c(ab参数)
cpu%
mem
RequestsperSecond


(50,500,5,10000,50,200,200,0)


100000/100 
18.6
188
6020


100000/200
20.1
195
5892


100000/500
19.8
209
5708


100000/1000
22.2
218
6081


(100,500,5,10000,50,200,100,0)


100000/100 
24.5
240
6919


100000/200
23.6
247
6798


100000/500
24.6
254
6827


100000/1000
22.3
271
6114


(200,500,5,10000,50,200,50,0)


100000/100 
27.3
301
7781


100000/200
27.4
307
7789


100000/500
26.0
320
7141


100000/1000
21.8
344
6110


相对来说，prefork方式速度要稍高于worker，然而它需要的cpu和memory资源也稍多于woker。
]]></description>
			<content:encoded><![CDATA[<p>选择prefork还是worker可以在编译时使用–with-mpm=MPM参数指定,默认为prefork,</p>
<p><strong>prefork</strong></p>
<p>prefork采用预派生子进程方式，用单独的子进程来处理 不同的请求，进程之间彼此独立。在make编译和make install安装后，使用httpd -l来确定当前使用的MPM是prefork.c。查看httpd-mpm.conf配置文件，里面包含如下默认的配置段：</p>
<p>&lt;IfModule prefork.c&gt;<br />
StartServers 5<br />
MinSpareServers 5<br />
MaxSpareServers 10<br />
MaxClients 150<br />
MaxRequestsPerChild 0<br />
&lt;/IfModule&gt;<br />
prefork 控制进程在最初建立“StartServers”个子进程后，为了满足MinSpareServers设置的需要创建一个进程，等待一秒钟，继续创建两个，再等待一秒钟，继续创建四个……如此按指数级增加创建的进程数，最多达到每秒32个，直到满足MinSpareServers设置的值为止。这种模式可以不必在请求到来时再产生新的进程，从而减小了系统开销以增加性能。MaxSpareServers设置了最大的空闲进程数，如果空闲进程数大于这个值，Apache会自动kill掉一些多余进程。这个值不要设得过大，但如果设的值比MinSpareServers小，Apache会自动把其调整为 MinSpareServers+1。如果站点负载较大，可考虑同时加大MinSpareServers和MaxSpareServers。 MaxRequestsPerChild设置的是每个子进程可处理的请求数。每个子进程在处理了“MaxRequestsPerChild”个请求后将自动销毁。0意味着无限，即子进程永不销毁。虽然缺省设为0可以使每个子进程处理更多的请求，但如果设成非零值也有两点重要的好处：1、可防止意外的内存泄漏。2、在服务器负载下降的时侯会自动减少子进程数。因此，可根据服务器的负载来调整这个值。MaxClients是这些指令中最为重要的一个，设定的是 Apache可以同时处理的请求，是对Apache性能影响最大的参数。其缺省值150是远远不够的，如果请求总数已达到这个值（可通过ps -ef|grep http|wc -l来确认），那么后面的请求就要排队，直到某个已处理请求完毕。这就是系统资源还剩下很多而HTTP访问却很慢的主要原因。虽然理论上这个值越大，可以处理的请求就越多，但Apache默认的限制不能大于256。ServerLimit指令无须重编译Apache就可以加大MaxClients。<br />
<span id="more-80"></span><br />
&lt;IfModule prefork.c&gt;</p>
<p>ServerLimit  10000<br />
StartServers 5<br />
MinSpareServers 5<br />
MaxSpareServers 10<br />
MaxClients 10000<br />
MaxRequestsPerChild 0<br />
&lt;/IfModule&gt;</p>
<p><strong>Worker</strong><br />
相对于prefork，worker全新的支持多线程和多进程混合模型的MPM。由于使用线程来处理，所以可以处理相对海量的请求，而系统资源的开销要小于基于进程的服务器。但是，worker也使用了多进程，每个进程又生成多个线程，以获得基于进程服务器的稳定性。在configure –with-mpm=worker后，进行make编译、make install安装。在缺省生成的httpd-mpm.conf中有以下默认配置段：<br />
&lt;IfModule worker.c&gt;<br />
StartServers 2<br />
MaxClients 150<br />
MinSpareThreads 25<br />
MaxSpareThreads 75<br />
ThreadsPerChild 25<br />
MaxRequestsPerChild 0<br />
&lt;/IfModule&gt;<br />
Worker 由主控制进程生成“StartServers”个子进程，每个子进程中包含固定的ThreadsPerChild线程数，各个线程独立地处理请求。同样，为了不在请求到来时再生成线程，MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数；而MaxClients 设置了同时连入的clients最大总数。如果现有子进程中的线程总数不能满足负载，控制进程将派生新的子进程。MinSpareThreads和 MaxSpareThreads的最大缺省值分别是75和250。这两个参数对Apache的性能影响并不大，可以按照实际情况相应调节。 ThreadsPerChild是worker MPM中与性能相关最密切的指令。ThreadsPerChild的最大缺省值是64，如果负载较大，64也是不够的。这时要显式使用 ThreadLimit指令，它的最大缺省值是20000。Worker模式下所能同时处理的请求总数是由子进程总数乘以ThreadsPerChild 值决定的，应该大于等于MaxClients。如果负载很大，现有的子进程数不能满足时，控制进程会派生新的子进程。默认最大的子进程总数是16，加大时也需要显式声明ServerLimit（最大值是20000）。需要注意的是，如果显式声明了ServerLimit，那么它乘以 ThreadsPerChild的值必须大于等于MaxClients，而且MaxClients必须是ThreadsPerChild的整数倍，否则 Apache将会自动调节到一个相应值。<br />
&lt;IfModule worker.c&gt;<br />
ServerLimit 25<br />
ThreadLimit 200<br />
StartServers 3<br />
MaxClients 2000<br />
MinSpareThreads 50<br />
MaxSpareThreads 200<br />
ThreadsPerChild 100<br />
MaxRequestsPerChild 0<br />
&lt;/IfModule&gt;</p>
<p>下面是利用Apache自带的测试工具ab对Server进行测试的情况(设定请求的index页面为6bytes),cpu%为cpu占用率，mem为内存使用量(M为单位)，RequestsPerSecond为每秒处理的请求数。<br />
1、Prefor方式<br />
  <font color="#0000ff">(ServerLimit,StartServer,MinSpareServers,MaxSpareServers,MaxClients,MaxRequestPerChild)</font>            </p>
<table border="1" cellSpacing="0">
<tr>
<td height="18" colSpan="4" width="357">
<table border="1" width="255" cellPadding="1" cellSpacing="1">
<tr>
<td><font color="#000000">-n/-c(ab参数)</font></td>
<td>Cpu%</td>
<td>Mem</td>
<td>Requestspersecond</td>
</tr>
<tr>
<td colSpan="4"><font color="#0000ff">(－,5,5,10,150,0)</font></td>
</tr>
<tr>
<td>100000/100</td>
<td>28.8</td>
<td>285</td>
<td>8434</td>
</tr>
<tr>
<td>100000/200</td>
<td>29.2</td>
<td>304</td>
<td>8032</td>
</tr>
<tr>
<td>100000/500</td>
<td>25.3</td>
<td>323</td>
<td>7348</td>
</tr>
<tr>
<td>100000/1000</td>
<td>24.4</td>
<td>330</td>
<td>5886</td>
</tr>
<tr>
<td colSpan="4"><font color="#0000ff">(10000,5,5,10,500,0)</font></td>
</tr>
<tr>
<td>100000/100</td>
<td>28.7</td>
<td>371</td>
<td>8345</td>
</tr>
<tr>
<td>100000/200</td>
<td>27.4</td>
<td>389</td>
<td>7929</td>
</tr>
<tr>
<td>100000/500</td>
<td>24.9</td>
<td>417</td>
<td>7229</td>
</tr>
<tr>
<td>100000/1000</td>
<td>23.4</td>
<td>437</td>
<td>6676</td>
</tr>
<tr>
<td colSpan="4"><font color="#0000ff">(10000,5,5,10,1000,0)</font></td>
</tr>
<tr>
<td>100000/100</td>
<td>28.8</td>
<td>408</td>
<td>8517</td>
</tr>
<tr>
<td>100000/200</td>
<td>27.0</td>
<td>422</td>
<td>8045</td>
</tr>
<tr>
<td>100000/500</td>
<td>24.2</td>
<td>455</td>
<td>7236</td>
</tr>
<tr>
<td>100000/1000</td>
<td>22.5</td>
<td>470</td>
<td>6570</td>
</tr>
<tr>
<td colSpan="4"><font color="#0000ff">(10000,5,5,10,1500,0)</font></td>
</tr>
<tr>
<td>100000/100</td>
<td>29.6</td>
<td>330</td>
<td>8407</td>
</tr>
<tr>
<td>100000/200</td>
<td>28.1</td>
<td>349</td>
<td>8014</td>
</tr>
<tr>
<td>100000/500</td>
<td>26.4</td>
<td>380</td>
<td>7290</td>
</tr>
<tr>
<td>100000/1000</td>
<td>24.0</td>
<td>400</td>
<td>6686</td>
</tr>
</table>
</td>
</tr>
</table>
<p>2、Worker方式<br />
(<font color="#0000ff">ServerLimt,Threadlimt,Startservers,MaxClients,MinspareThread,MaxspareThread,ThreadperChild,MaxRequestPerChild)</font><br />
                   </p>
<table border="1" width="281" cellPadding="1" cellSpacing="1">
<tr>
<td>-n/-c(ab参数)</td>
<td>cpu%</td>
<td>mem</td>
<td>RequestsperSecond</td>
</tr>
<tr>
<td colSpan="4"><font color="#0000ff">(50,500,5,10000,50,200,200,0)</font></td>
</tr>
<tr>
<td>100000/100 </td>
<td>18.6</td>
<td>188</td>
<td>6020</td>
</tr>
<tr>
<td>100000/200</td>
<td>20.1</td>
<td>195</td>
<td>5892</td>
</tr>
<tr>
<td>100000/500</td>
<td>19.8</td>
<td>209</td>
<td>5708</td>
</tr>
<tr>
<td>100000/1000</td>
<td>22.2</td>
<td>218</td>
<td>6081</td>
</tr>
<tr>
<td colSpan="4"><font color="#0000ff">(100,500,5,10000,50,200,100,0)</font></td>
</tr>
<tr>
<td>100000/100 </td>
<td>24.5</td>
<td>240</td>
<td>6919</td>
</tr>
<tr>
<td>100000/200</td>
<td>23.6</td>
<td>247</td>
<td>6798</td>
</tr>
<tr>
<td>100000/500</td>
<td>24.6</td>
<td>254</td>
<td>6827</td>
</tr>
<tr>
<td>100000/1000</td>
<td>22.3</td>
<td>271</td>
<td>6114</td>
</tr>
<tr>
<td colSpan="4"><font color="#0000ff">(200,500,5,10000,50,200,50,0)</font></td>
</tr>
<tr>
<td>100000/100 </td>
<td>27.3</td>
<td>301</td>
<td>7781</td>
</tr>
<tr>
<td>100000/200</td>
<td>27.4</td>
<td>307</td>
<td>7789</td>
</tr>
<tr>
<td>100000/500</td>
<td>26.0</td>
<td>320</td>
<td>7141</td>
</tr>
<tr>
<td>100000/1000</td>
<td>21.8</td>
<td>344</td>
<td>6110</td>
</tr>
</table>
<p>相对来说，prefork方式速度要稍高于worker，然而它需要的cpu和memory资源也稍多于woker。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/80.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP &amp; memcached</title>
		<link>http://www.aaronw.cn/static/77.html</link>
		<comments>http://www.aaronw.cn/static/77.html#comments</comments>
		<pubDate>Fri, 07 Mar 2008 10:10:57 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/html/77.html</guid>
		<description><![CDATA[strong>一、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 解开包、编译、安装：
# 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
安装完成之后，memcached 应该在 /usr/bin/memcached。

三、运行 memcached 守护程序
运行 memcached 守护程序很简单，只需一个命令行即可，不需要修改任何配置文件（也没有配置文件给你修改  ）：
/usr/bin/memcached -d -m 128 -l 192.168.1.1 -p [...]]]></description>
			<content:encoded><![CDATA[<p>strong>一、memcached 简介</strong></p>
<p>在很多场合，我们都会听到 <a href="http://www.danga.com/memcached/">memcached</a> 这个名字，但很多同学只是听过，并没有用过或实际了解过，只知道它是一个很不错的东东。这里简单介绍一下，memcached 是高效、快速的分布式内存对象缓存系统，主要用于加速 WEB 动态应用程序。</p>
<p><strong>二、memcached 安装</strong></p>
<p>首先是下载 memcached 了，目前最新版本是 1.1.12，直接从官方网站即可下载到 <a href="http://www.danga.com/memcached/dist/memcached-1.1.12.tar.gz">memcached-1.1.12.tar.gz</a>。除此之外，memcached 用到了 <a href="http://monkey.org/~provos/libevent/">libevent</a>，我<a href="http://monkey.org/~provos/libevent-1.1a.tar.gz">下载的是 libevent-1.1a.tar.gz</a>。</p>
<p>接下来是分别将 libevent-1.1a.tar.gz 和 memcached-1.1.12.tar.gz 解开包、编译、安装：</p>
<pre class="code"># 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</pre>
<p>安装完成之后，memcached 应该在 /usr/bin/memcached。<br />
<span id="more-77"></span><br />
<strong>三、运行 memcached 守护程序</strong></p>
<p>运行 memcached 守护程序很简单，只需一个命令行即可，不需要修改任何配置文件（也没有配置文件给你修改 <img src="http://nio.infor96.com/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /> ）：</p>
<pre class="code">/usr/bin/memcached -d -m 128 -l 192.168.1.1 -p 11211 -u httpd</pre>
<p>参数解释：</p>
<pre class="code">-d 以守护程序（daemon）方式运行 memcached；
-m 设置 memcached 可以使用的内存大小，单位为 M；
-l 设置监听的 IP 地址，如果是本机的话，通常可以不设置此参数；
-p 设置监听的端口，默认为 11211，所以也可以不设置此参数；
-u 指定用户，如果当前为 root 的话，需要使用此参数指定用户。</pre>
<p>当然，还有其它参数可以用，<code>man memcached</code> 一下就可以看到了。</p>
<p><strong>四、memcached 的工作原理</strong></p>
<p>首先 memcached 是以守护程序方式运行于一个或多个服务器中，随时接受客户端的连接操作，客户端可以由各种语言编写，目前已知的客户端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等。PHP 等客户端在与 memcached 服务建立连接之后，接下来的事情就是存取对象了，每个被存取的对象都有一个唯一的标识符 key，存取操作均通过这个 key 进行，保存到 memcached 中的对象实际上是放置内存中的，并不是保存在 cache 文件中的，这也是为什么 memcached 能够如此高效快速的原因。注意，这些对象并不是持久的，服务停止之后，里边的数据就会丢失。</p>
<p><img src="http://nio.infor96.com/wp-content/uploads/2006/11/image001.png" alt="image001.png" /></p>
<p><strong>三、PHP 如何作为 memcached 客户端</strong></p>
<p>有两种方法可以使 PHP 作为 memcached 客户端，调用 memcached 的服务进行对象存取操作。</p>
<p>第一种，PHP 有一个叫做 <a href="http://www.php.net/manual/en/ref.memcache.php">memcache 的扩展</a>，Linux 下编译时需要带上 <em>–enable-memcache[=DIR]</em> 选项，Window 下则在 php.ini 中去掉 php_memcache.dll 前边的注释符，使其可用。</p>
<p>除此之外，还有一种方法，可以避开扩展、重新编译所带来的麻烦，那就是直接使用 <a href="http://wikipedia.sourceforge.net/doc/memcached-client/_includes_memcached-client_php.html">php-memcached-client</a>。</p>
<p>本文选用第二种方式，虽然效率会比扩展库稍差一些，但问题不大。</p>
<p><strong>四、PHP memcached 应用示例</strong></p>
<p>首先 <a href="http://nio.infor96.com/wp-content/uploads/2006/04/memcached-client.zip">下载 memcached-client.php</a>，在下载了 memcached-client.php 之后，就可以通过这个文件中的类“memcached”对 memcached 服务进行操作了。其实代码调用非常简单，主要会用到的方法有 add()、get()、replace() 和 delete()，方法说明如下：</p>
<p><code>add ($key, $val, $exp = 0)</code><br />
往 memcached 中写入对象，$key 是对象的唯一标识符，$val 是写入的对象数据，$exp 为过期时间，单位为秒，默认为不限时间；</p>
<p><code>get ($key)</code><br />
从 memcached 中获取对象数据，通过对象的唯一标识符 $key 获取；</p>
<p><code>replace ($key, $value, $exp=0)</code><br />
使用 $value 替换 memcached 中标识符为 $key 的对象内容，参数与 add() 方法一样，只有 $key 对象存在的情况下才会起作用；</p>
<p><code>delete ($key, $time = 0)</code><br />
删除 memcached 中标识符为 $key 的对象，$time 为可选参数，表示删除之前需要等待多长时间。</p>
<p>下面是一段简单的测试代码，代码中对标识符为 &#8216;mykey&#8217; 的对象数据进行存取操作：</p>
<pre class="code"><code><span style="color: #000000">
&lt;pre&gt;
<span style="color: #0000bb">&lt;?php
</span><span style="color: #ff8000">//  包含 memcached 类文件
</span><span style="color: #007700">require_once(</span><span style="color: #dd0000">'memcached-client.php'</span><span style="color: #007700">);
</span><span style="color: #ff8000">//  选项设置
</span><span style="color: #0000bb">$options </span><span style="color: #007700">= array(
    </span><span style="color: #dd0000">'servers' </span><span style="color: #007700">=&gt; array(</span><span style="color: #dd0000">'192.168.1.1:11211'</span><span style="color: #007700">), </span><span style="color: #ff8000">//memcached 服务的地址、端口，可用多个数组元素表示多个 memcached 服务
    </span><span style="color: #dd0000">'debug' </span><span style="color: #007700">=&gt; </span><span style="color: #0000bb">true</span><span style="color: #007700">,  </span><span style="color: #ff8000">//是否打开 debug
    </span><span style="color: #dd0000">'compress_threshold' </span><span style="color: #007700">=&gt; </span><span style="color: #0000bb">10240</span><span style="color: #007700">,  </span><span style="color: #ff8000">//超过多少字节的数据时进行压缩
    </span><span style="color: #dd0000">'persistant' </span><span style="color: #007700">=&gt; </span><span style="color: #0000bb">false  </span><span style="color: #ff8000">//是否使用持久连接
    </span><span style="color: #007700">);
</span><span style="color: #ff8000">//  创建 memcached 对象实例
</span><span style="color: #0000bb">$mc </span><span style="color: #007700">= new </span><span style="color: #0000bb">memcached</span><span style="color: #007700">(</span><span style="color: #0000bb">$options</span><span style="color: #007700">);
</span><span style="color: #ff8000">//  设置此脚本使用的唯一标识符
</span><span style="color: #0000bb">$key </span><span style="color: #007700">= </span><span style="color: #dd0000">'mykey'</span><span style="color: #007700">;
</span><span style="color: #ff8000">//  往 memcached 中写入对象
</span><span style="color: #0000bb">$mc</span><span style="color: #007700">-&gt;</span><span style="color: #0000bb">add</span><span style="color: #007700">(</span><span style="color: #0000bb">$key</span><span style="color: #007700">, </span><span style="color: #dd0000">'some random strings'</span><span style="color: #007700">);
</span><span style="color: #0000bb">$val </span><span style="color: #007700">= </span><span style="color: #0000bb">$mc</span><span style="color: #007700">-&gt;</span><span style="color: #0000bb">get</span><span style="color: #007700">(</span><span style="color: #0000bb">$key</span><span style="color: #007700">);
echo </span><span style="color: #dd0000">"n"</span><span style="color: #007700">.</span><span style="color: #0000bb">str_pad</span><span style="color: #007700">(</span><span style="color: #dd0000">'$mc-&gt;add() '</span><span style="color: #007700">, </span><span style="color: #0000bb">60</span><span style="color: #007700">, </span><span style="color: #dd0000">'_'</span><span style="color: #007700">).</span><span style="color: #dd0000">"n"</span><span style="color: #007700">;
</span><span style="color: #0000bb">var_dump</span><span style="color: #007700">(</span><span style="color: #0000bb">$val</span><span style="color: #007700">);
</span><span style="color: #ff8000">//  替换已写入的对象数据值
</span><span style="color: #0000bb">$mc</span><span style="color: #007700">-&gt;</span><span style="color: #0000bb">replace</span><span style="color: #007700">(</span><span style="color: #0000bb">$key</span><span style="color: #007700">, array(</span><span style="color: #dd0000">'some'</span><span style="color: #007700">=&gt;</span><span style="color: #dd0000">'haha'</span><span style="color: #007700">, </span><span style="color: #dd0000">'array'</span><span style="color: #007700">=&gt;</span><span style="color: #dd0000">'xxx'</span><span style="color: #007700">));
</span><span style="color: #0000bb">$val </span><span style="color: #007700">= </span><span style="color: #0000bb">$mc</span><span style="color: #007700">-&gt;</span><span style="color: #0000bb">get</span><span style="color: #007700">(</span><span style="color: #0000bb">$key</span><span style="color: #007700">);
echo </span><span style="color: #dd0000">"n"</span><span style="color: #007700">.</span><span style="color: #0000bb">str_pad</span><span style="color: #007700">(</span><span style="color: #dd0000">'$mc-&gt;replace() '</span><span style="color: #007700">, </span><span style="color: #0000bb">60</span><span style="color: #007700">, </span><span style="color: #dd0000">'_'</span><span style="color: #007700">).</span><span style="color: #dd0000">"n"</span><span style="color: #007700">;
</span><span style="color: #0000bb">var_dump</span><span style="color: #007700">(</span><span style="color: #0000bb">$val</span><span style="color: #007700">);
</span><span style="color: #ff8000">//  删除 memcached 中的对象
</span><span style="color: #0000bb">$mc</span><span style="color: #007700">-&gt;</span><span style="color: #0000bb">delete</span><span style="color: #007700">(</span><span style="color: #0000bb">$key</span><span style="color: #007700">);
</span><span style="color: #0000bb">$val </span><span style="color: #007700">= </span><span style="color: #0000bb">$mc</span><span style="color: #007700">-&gt;</span><span style="color: #0000bb">get</span><span style="color: #007700">(</span><span style="color: #0000bb">$key</span><span style="color: #007700">);
echo </span><span style="color: #dd0000">"n"</span><span style="color: #007700">.</span><span style="color: #0000bb">str_pad</span><span style="color: #007700">(</span><span style="color: #dd0000">'$mc-&gt;delete() '</span><span style="color: #007700">, </span><span style="color: #0000bb">60</span><span style="color: #007700">, </span><span style="color: #dd0000">'_'</span><span style="color: #007700">).</span><span style="color: #dd0000">"n"</span><span style="color: #007700">;
</span><span style="color: #0000bb">var_dump</span><span style="color: #007700">(</span><span style="color: #0000bb">$val</span><span style="color: #007700">);
</span><span style="color: #0000bb">?&gt;
</span>&lt;/pre&gt;</span> </code></pre>
<p>是不是很简单，在实际应用中，通常会把数据库查询的结果集保存到 memcached 中，下次访问时直接从 memcached 中获取，而不再做数据库查询操作，这样可以在很大程度上减轻数据库的负担。通常会将 SQL 语句 md5() 之后的值作为唯一标识符 key。下边是一个利用 memcached 来缓存数据库查询结果集的示例（此代码片段紧接上边的示例代码）：</p>
<pre class="code"><code><span style="color: #000000">
<span style="color: #0000bb">&lt;?php
$sql </span><span style="color: #007700">= </span><span style="color: #dd0000">'SELECT * FROM users'</span><span style="color: #007700">;
</span><span style="color: #0000bb">$key </span><span style="color: #007700">= </span><span style="color: #0000bb">md5</span><span style="color: #007700">(</span><span style="color: #0000bb">$sql</span><span style="color: #007700">);   </span><span style="color: #ff8000">//memcached 对象标识符
</span><span style="color: #007700">if ( !(</span><span style="color: #0000bb">$datas </span><span style="color: #007700">= </span><span style="color: #0000bb">$mc</span><span style="color: #007700">-&gt;</span><span style="color: #0000bb">get</span><span style="color: #007700">(</span><span style="color: #0000bb">$key</span><span style="color: #007700">)) ) {
    </span><span style="color: #ff8000">//  在 memcached 中未获取到缓存数据，则使用数据库查询获取记录集。
    </span><span style="color: #007700">echo </span><span style="color: #dd0000">"n"</span><span style="color: #007700">.</span><span style="color: #0000bb">str_pad</span><span style="color: #007700">(</span><span style="color: #dd0000">'Read datas from MySQL.'</span><span style="color: #007700">, </span><span style="color: #0000bb">60</span><span style="color: #007700">, </span><span style="color: #dd0000">'_'</span><span style="color: #007700">).</span><span style="color: #dd0000">"n"</span><span style="color: #007700">;
    </span><span style="color: #0000bb">$conn </span><span style="color: #007700">= </span><span style="color: #0000bb">mysql_connect</span><span style="color: #007700">(</span><span style="color: #dd0000">'localhost'</span><span style="color: #007700">, </span><span style="color: #dd0000">'test'</span><span style="color: #007700">, </span><span style="color: #dd0000">'test'</span><span style="color: #007700">);
    </span><span style="color: #0000bb">mysql_select_db</span><span style="color: #007700">(</span><span style="color: #dd0000">'test'</span><span style="color: #007700">);
    </span><span style="color: #0000bb">$result </span><span style="color: #007700">= </span><span style="color: #0000bb">mysql_query</span><span style="color: #007700">(</span><span style="color: #0000bb">$sql</span><span style="color: #007700">);
    while (</span><span style="color: #0000bb">$row </span><span style="color: #007700">= </span><span style="color: #0000bb">mysql_fetch_object</span><span style="color: #007700">(</span><span style="color: #0000bb">$result</span><span style="color: #007700">))
        </span><span style="color: #0000bb">$datas</span><span style="color: #007700">[] = </span><span style="color: #0000bb">$row</span><span style="color: #007700">;
    </span><span style="color: #ff8000">//  将数据库中获取到的结果集数据保存到 memcached 中，以供下次访问时使用。
    </span><span style="color: #0000bb">$mc</span><span style="color: #007700">-&gt;</span><span style="color: #0000bb">add</span><span style="color: #007700">(</span><span style="color: #0000bb">$key</span><span style="color: #007700">, </span><span style="color: #0000bb">$datas</span><span style="color: #007700">);
} else {
    echo </span><span style="color: #dd0000">"n"</span><span style="color: #007700">.</span><span style="color: #0000bb">str_pad</span><span style="color: #007700">(</span><span style="color: #dd0000">'Read datas from memcached.'</span><span style="color: #007700">, </span><span style="color: #0000bb">60</span><span style="color: #007700">, </span><span style="color: #dd0000">'_'</span><span style="color: #007700">).</span><span style="color: #dd0000">"n"</span><span style="color: #007700">;
}
</span><span style="color: #0000bb">var_dump</span><span style="color: #007700">(</span><span style="color: #0000bb">$datas</span><span style="color: #007700">);
</span><span style="color: #0000bb">?&gt;</span>
</span> </code></pre>
<p>可以看出，使用 memcached 之后，可以减少数据库连接、查询操作，数据库负载下来了，脚本的运行速度也提高了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/77.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>好玩的js！</title>
		<link>http://www.aaronw.cn/static/74.html</link>
		<comments>http://www.aaronw.cn/static/74.html#comments</comments>
		<pubDate>Fri, 07 Mar 2008 09:57:03 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/html/74.html</guid>
		<description><![CDATA[ javascript:R=0; x1=.1; y1=.05; x2=.25; y2=.24; x3=1.6;
y3=.24; x4=300; y4=200; x5=300; y5=200;
DI=document.images; DIL=DI.length;
function A()
{
for(i=0; i-DIL; i++)
{
DIS=DI[ i ].style;
DIS.position=&#8217;absolute&#8217;;
DIS.left=Math.sin(R*x1+i*x2+x3)*x4+x5;
DIS.top=Math.cos(R*y1+i*y2+y3)*y4+y5
}
R++
}
setInterval(&#8216;A()&#8217;,5);
void(0);
打开一个网站，然后直接把这段js贴在url后面，就能出现奇迹，呵呵！
]]></description>
			<content:encoded><![CDATA[<p> javascript:R=0; x1=.1; y1=.05; x2=.25; y2=.24; x3=1.6;<br />
y3=.24; x4=300; y4=200; x5=300; y5=200;<br />
DI=document.images; DIL=DI.length;<br />
function A()<br />
{<br />
for(i=0; i-DIL; i++)<br />
{<br />
DIS=DI[ i ].style;<br />
DIS.position=&#8217;absolute&#8217;;<br />
DIS.left=Math.sin(R*x1+i*x2+x3)*x4+x5;<br />
DIS.top=Math.cos(R*y1+i*y2+y3)*y4+y5<br />
}<br />
R++<br />
}<br />
setInterval(&#8216;A()&#8217;,5);<br />
void(0);</p>
<p>打开一个网站，然后直接把这段js贴在url后面，就能出现奇迹，呵呵！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/74.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>memcache分析调试</title>
		<link>http://www.aaronw.cn/static/73.html</link>
		<comments>http://www.aaronw.cn/static/73.html#comments</comments>
		<pubDate>Fri, 07 Mar 2008 09:47:58 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/html/73.html</guid>
		<description><![CDATA[ 1.关于本文档
       本文档所有的分析都是在1.2版本之上,偶尔会提到比较1.1版本.其他版本没有阅读.
        一个星期时间的工作,不可能对memcache有很深刻的分析.文档本身的目的在于为以后的研究准备一个总结资料.刚接触memcache时,对其设计分布式的思路感到十分欣喜,因为在中间层以极小的代价实现简单分布式无疑成为一些要求不是很高的分布式应用的一个很好的设计思路,这个特性决定 memcache本身在分布式应用中,单个结点之间是Server相互独立,不会存在同级之间的通信.一个结点拒绝访问,如果没有相应的冗余策略,将导致该结点的数据丢失.同时,memcache的Server结点对数据的存储操作都是在内存中完成,而memcache对内存分配和回收采用了曾在 SunOS实现的分页机制,预分配一个大内存(默认是 &#60;= 200M),然后分页切块,对每个数据对象的存储便在所切的块中进行操作.这个特点决定memcache没有设计到任何磁盘IO操作,那么所有的关于 memcache的性能瓶颈都在网络通信部分,而memcache正是将这一部分抛给了一个中间层完成.可以说真正的memcache是一个单进程,单线程,监听某个网络端口的daemon(或非daemon),是一个轻量级的应用服务进程.这些特性决定了memcache的应用范围,性能瓶颈和优化策略.
       本文档的目的也就诣在探讨查看memcache源码后的一些观点.
       文档分为六个部分:
       1.  文档介绍.主要介绍文档组织和文档目的.
       2.  memcache的代码分析.分析memcache的源代码,指出核心的数据结构和算法.
       3.  memcache的使用优化.分析memcache的特点,结合实际应用给出一些优化memcache的策略.
       4.  memcache的测试分析.初略测试了memcache,给出优化方案的例证.
       5.  memcache的中间层客户端编写.分析memcache的通信协议,模拟编写了一个简单的memcache中间层客户端.
       6.  libevent简介.memcache采用的是libevent进行网络IO处理,libevent作为一种新的网络IO方式以高效的方法(epoll/kqueue)组织IO.
       其中第六章可以不看.对于系统管理员,需要查看第一,三,四部分;进行二次开发的程序员可以查看第一,二,四,五,六部分.

2.memcache代码分析
       1. memcache main流程

图2.1 memcache main流程
      [...]]]></description>
			<content:encoded><![CDATA[<p> 1.关于本文档<br />
       本文档所有的分析都是在1.2版本之上,偶尔会提到比较1.1版本.其他版本没有阅读.<br />
        一个星期时间的工作,不可能对memcache有很深刻的分析.文档本身的目的在于为以后的研究准备一个总结资料.刚接触memcache时,对其设计分布式的思路感到十分欣喜,因为在中间层以极小的代价实现简单分布式无疑成为一些要求不是很高的分布式应用的一个很好的设计思路,这个特性决定 memcache本身在分布式应用中,单个结点之间是Server相互独立,不会存在同级之间的通信.一个结点拒绝访问,如果没有相应的冗余策略,将导致该结点的数据丢失.同时,memcache的Server结点对数据的存储操作都是在内存中完成,而memcache对内存分配和回收采用了曾在 SunOS实现的分页机制,预分配一个大内存(默认是 &lt;= 200M),然后分页切块,对每个数据对象的存储便在所切的块中进行操作.这个特点决定memcache没有设计到任何磁盘IO操作,那么所有的关于 memcache的性能瓶颈都在网络通信部分,而memcache正是将这一部分抛给了一个中间层完成.可以说真正的memcache是一个单进程,单线程,监听某个网络端口的daemon(或非daemon),是一个轻量级的应用服务进程.这些特性决定了memcache的应用范围,性能瓶颈和优化策略.<br />
       本文档的目的也就诣在探讨查看memcache源码后的一些观点.<br />
       文档分为六个部分:<br />
       1.  文档介绍.主要介绍文档组织和文档目的.<br />
       2.  memcache的代码分析.分析memcache的源代码,指出核心的数据结构和算法.<br />
       3.  memcache的使用优化.分析memcache的特点,结合实际应用给出一些优化memcache的策略.<br />
       4.  memcache的测试分析.初略测试了memcache,给出优化方案的例证.<br />
       5.  memcache的中间层客户端编写.分析memcache的通信协议,模拟编写了一个简单的memcache中间层客户端.<br />
       6.  libevent简介.memcache采用的是libevent进行网络IO处理,libevent作为一种新的网络IO方式以高效的方法(epoll/kqueue)组织IO.<br />
       其中第六章可以不看.对于系统管理员,需要查看第一,三,四部分;进行二次开发的程序员可以查看第一,二,四,五,六部分.<br />
<span id="more-73"></span><br />
2.memcache代码分析<br />
       1. memcache main流程<br />
<a target="_blank" href="http://wf.xplore.cn/pics/memcache_f1.jpg"><img border="0" src="http://wf.xplore.cn/pics/memcache_f1.jpg" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" class="insertimage" /></a><br />
图2.1 memcache main流程<br />
       libevent的事件处理机制在main进程里体现在处理网络IO上.在TCP memcache的服务流程里,也是利用event处理事件的.<br />
       2. memcache服务流程(TCP)<br />
<a target="_blank" href="http://wf.xplore.cn/pics/memcache_f2.jpg"><img border="0" src="http://wf.xplore.cn/pics/memcache_f2.jpg" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" class="insertimage" /></a><br />
图2.2 memcache服务流程图(TCP)<br />
       3. memcache状态转换和通信协议处理<br />
<a target="_blank" href="http://wf.xplore.cn/pics/memcache_f3.jpg"><img border="0" src="http://wf.xplore.cn/pics/memcache_f3.jpg" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" class="insertimage" /></a>  <br />
图2.3 memcache状态转换和通信协议处理<br />
       需要说明的是,这里需要排除所有出错处理.很显然,不管是哪种操作下,一旦出错,信息需要通过conn_write状态往client写入出错信息的,那么在string_out时,必定转入conn_write状态.<br />
       而且,很多细节也没有在流程图中给出,如统计信息的处理,超时后get操作时删除等等.对于在memcache协议中定义的其他操作,如stats, version,quit,flush_all,own,disown等等由于使用很少,在流程中没有详细给出,可以查看源代码.<br />
       4.  memcache核心数据结构<br />
               1. item结构<br />
       item是存储在memcache的key-value对的抽象.由于组织item存放是按照LRU算法组织的.那么在其中有几个成员在修改源代码时必须注意,time是最近访问时间.exptime是item消亡时间.item是一个双向列表.同时还挂在一个Hash table上.<br />
               2. conn结构<br />
       conn结构是联系上下文的关键对象.对于每个连接的到来,都有一个conn结构与其对应,并且对应到某个连接状态,进入状态转换而完成操作.<br />
       conn在程序开始也进行了一次预分配,分配200个连接空间.当200个使用完之后便是按需分配,到达一个分配一个.<br />
       conn和item,iovec(内核级别缓冲结构)关联.<br />
               3. slabclass_t结构<br />
       slabclass_t保存了分级大小的空间槽,以分别适用于不同大小的item存放.取决于两个命令行参数,-f和-n.在应用 slabclass_t时,定义的是一个数组,该数组长度取决于增长的指数级别和初始值大小(32+chunk_size),每个空间槽是不允许大于1M 的,也就是1048576.<br />
               4. settings结构<br />
        系统获取的命令行参数保存的地方.<br />
               5. stats结构:<br />
       统计信息保存地方,可以考虑对其进行操作以适应不同的统计信息处理,如获取某个时间段的get命中率等等操作.<br />
       5.  memcache核心算法<br />
       事件触发处理连接,LRU算法挂载item,加锁并事后处理删除操作,预分配空间和按需请求不够空间策略获取存储空间,freelist方式管理空闲空间.名为new_hash的hash算法计算key的hash值(<a target="_blank" href="http://burtleburtle.net/bob/hash/evahash.html%29.">http://burtleburtle.net/bo&#8230;</a></p>
<p>3.memcache使用优化<br />
       在优化memcache的工作之前,需要了解memcache体系的工作流程.一个分布式的memcache的运作是需要三个部分的,多台提供 memcache服务的servers(简称S),一个进行分布式映射的中间层lib(其实这个也可以当作客户端的一部分,简称L),和进行 memcache请求的客户端(简称C).<br />
       在memcache工作时,有以下四个步骤:<br />
       1.  C通过带有特性化的Key值的命令串,向L请求memcache服务,L将命令串进行分解,并通过对key的某种Hash算法决定S的地址<br />
       2.  L将分解的(Comm Key-Value)或者(Comm Key)向相关的S请求memcache服务.<br />
       3.  相关的S根据memcache协议向L返回服务结果.<br />
       4.  L将结果进行聚集包装后返回给C一个人性化的响应.<br />
       这个流程可以用图3.1进行描述.<br />
<a target="_blank" href="http://wf.xplore.cn/pics/memcache_w1.jpg"><img border="0" src="http://wf.xplore.cn/pics/memcache_w1.jpg" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" class="insertimage" /></a><br />
图3.1 memcache工作步骤<br />
       在每个S端,请求处理的Key-Value对当作一个对象(不过这个对象的结构是单一的),再进行另一步hash之后,存储在内存里.存储算法在第二部分有详细的描述.这种通过双层hash来分开处理分布式和缓存两个功能的方法值得学习.<br />
       从上面的分析可以看出,分布式的memcache服务是需要很大的网络开销的.对于一般的应用而言,是否都要进行memcache的优化,甚至是否需要用到memcache,都需要进行权衡分析.如果只是本地小规模的应用,在数据库可承受的范围内,是宁愿采用数据库+文件缓存的方式.1.1版本的 memcache走TCP模式在本地应用的处理速度甚至比不上Mysql数据的Unix域套接口的处理速度的一半,当然会更加比不上在程序内部直接操作内存了.虽然1.2版本的memcache已经提供了-s参数指定Unix域套口和-u指定udp模式.而且如果不需要用到分布式的话,不推荐使用 memcache,除非你的内存足够大到浪费的程度.<br />
       因此,在进行优化之前,需要看看是否真的需要优化memcache,是否真正需要用到memcache.<br />
       优化可以从以下几个方面进行：<br />
       1.  命中率.<br />
       对于缓存服务而言,命中率是至关重要的.命中率的提升可以通过多种方案实现.其一,提高服务获取的内存总量.这无疑是增加命中的最直接的办法,将缓存数据完全放入数据池中.只要连接不失效,就一定命中.其二,提高空间利用率,这实际上也是另一种方式的增加内存总量.具体实现在下一个方面给出.其三,对于一些很特别的memcache应用,可以采用多个memcache服务进行侦听,分开处理,针对服务提供的频繁度划分服务内存,相当于在应用一级别上再来一次LRU.其四,对于整体命中率,可以采取有效的冗余策略,减少分布式服务时某个server发生服务抖动的情况.如,14台机器实现分布式 memcache,划分两组服务,其中一组13台做一个分布式的memcache,一组1台做整个的memcache备份.对于update操作,需要进行两边,get操作只需要一遍,一旦访问失效,则访问备份服务器.这样,对于备份服务器需要内存比较大,而且只适应于读操作大于写操作的应用中.这可以认为是RAID3,当然,也可以采用RAID1完全镜像.<br />
       2.  空间利用率.<br />
       对于使用memcache做定长数据缓存服务而言,是可以在空间利用率上进行优化.甚至最简单的办法可以不用更改memcache的源码遍可以完成由- f和-n参数的配合可以做到定长优化,不过极可能需要浪费掉预分配的199M内存空间.当然前提是memcache的版本是1.2,同时如果使用的是 1.2.0和1.2.1的话,需要更改掉一个BUG,那就是getopt时将opt串中最后一个”s”改成”n”,希望memcache能在以后的版本发现这个BUG.例如,如果key是一个定长id(如一个8位的流水号00000001),value是一个定长的串(如16位的任意字符串),对应于一个 chunk_size可以这么计算:chunk_size = sizeof(item) + nkey + *nsuffix + nbytes = 32 + 9 + (flag的数位长度 )2+ (16)的数位长度) 2+(两换行的长度)4 + 17 = 40 + 10 + 16 = 66,那么可以通过 -f 1.000001 -n  `expr 66 &#8211; 32`,即 -f 1.000001 -n 34 来启动memcache.这种情况下,会浪费掉memcache预先分配的200M空间中的199M.从第2个预分配等级到第200个预分配等级将不会用到.然而,存在解决办法,那就是在编译memcache是加入编译参数-DDONT_PREALLOC_SLABS,或者在源代码中加入#define DONT_PREALLOC_SLABS即可,只是会去除memcache的预分配内存机制.<br />
       如果需要memcache的预分配内存机制,那么需要对其源代码进行修改.修改如下:  </p>
<p class="quote-title">引用</p>
<p class="quote-content">   1. 在slabs.c中,将函数slabs_clsid改成:<br />
     unsigned int slabs_clsid(size_t size)<br />
     {   unsigned int res = POWER_SMALLEST;<br />
       if(size==0)<br />
                 return 0;<br />
       res = (size)%power_largest;<br />
       return res;<br />
     }<br />
   2. 在item.c中,将函数 item_make_header改为:<br />
     int item_make_header(char *key, uint8_t nkey, int flags, int nbytes,<br />
                    char *suffix, int *nsuffix)<br />
     {<br />
           *nsuffix = sprintf(suffix, &#8221; %u %u\r\n&#8221;, flags, nbytes &#8211; 2);<br />
           return sizeof(item)+ nkey + *nsuffix + nbytes + hash(key,nkey,0);<br />
     }<br />
   3. 在item.c中,将函数 item_free改为:<br />
     void item_free(item *it)<br />
     {  unsigned int ntotal = it-&gt;slabs_clsid;<br />
           assert((it-&gt;it_flags &amp; ITEM_LINKED) == 0);<br />
           assert(it != heads[it-&gt;slabs_clsid]);<br />
           assert(it != tails[it-&gt;slabs_clsid]);<br />
           assert(it-&gt;refcount == 0);</p>
<p>           it-&gt;slabs_clsid = 0;<br />
           it-&gt;it_flags |= ITEM_SLABBED;<br />
           slabs_free(it, ntotal);<br />
     }<br />
       做一个轮流存储的机制使用预分配的内存,这样的好处是其他地方不需要做任何修改就可以了,当然你可以在源代码中加入上面的代码,并将它们放在一个自定义的宏后面.<br />
       3.  加速比.<br />
       加速比,也即事件的处理效率.是否可以修改libevent的事件处理效率,需要研究.如果内存空间很大,可以将freeconn的数值调大,增加预分配的conn内存大小.<br />
       是否可以将memcache做成多线程处理,但在处理多线程数据同步是个问题.<br />
        如果有时间,愿意来试试这个策略.<br />
       4.  安全性能.<br />
       memcache还存在一个比较显著的问题,那就是其安全性能.只要了解memcache监听的端口,对于能够使用分布式memcache进行数据通信的网络环境的机器,都可以通过memcache协议于memcache服务器进行通信,获取或种植数据.不能保证种植进内存里的数据不会被别有心意的人再利用.也不能保证服务器的内存不被漫天遍地的垃圾数据所堆积,造成命中极低.<br />
       memcache的设计理念在一个轻字,如果对每次Client的通讯需要校验身份,那么恐怕memcache也就达不到其想要的效果了.存在解决办法缓解这个问题,一般而言,需要使用memcache服务的机器,可以在Server维持一张红色列表.这张表上的机器便可以获取服务.很显然, memcache并非任意Client都能访问,只有信任的机器访问,那么为什么不将这些信任的机器放在一个/etc/mem_passwd下呢.<br />
       还有,memcached走udp时,很大几率接受到upd时,都会使服务死掉,特别是set,add,replace时,这个问题需要去考究一下.不过没有时间了.</p>
<p>4.memcache测试分析<br />
       服务器端memcache在命令行运行的参数:</p>
<p class="quote-title">引用</p>
<p class="quote-content"># memcached –d –m 512 –l *.*.*.* -u ** -f 1.00001 –n 16 –c 10000 -vv</p>
<p>       1.  读写memcache指令测试<br />
       在利用了memcache官方推荐的c客户端libmemcache和自己编写的一个简单客户端测试之后,在set/get/add/del指令的运行速度如表4.1和图4.1所示:<br />
<a target="_blank" href="http://wf.xplore.cn/pics/memcache_t1.jpg"><img border="0" src="http://wf.xplore.cn/pics/memcache_t1.jpg" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" class="insertimage" /></a><br />
表4.1 memcache的指令运行速度<br />
图4.1 memcache的指令运行速度<br />
       2.  并发连接<br />
       由于在memcache服务器端,一个结点运行的是单进程单线程的daemon(或非daemon)服务,同时对于采用了libevent处理网络IO 而言,其并发连接的数目是和libevent采用的机制相关连的.很显然,accept函数在接收到connection后将Client的socket 放进event库中,等待处理.而libevent库在LINUX中使用的是epoll,监听EPOLLIT水平触发.因此从理论上讲,memcache 的并发连接可以达到infinite,前提是event池和内存空间足够大.而没有和linux的线程处理有关系.事实上,在后面的测试中便可发现,在单结点连接压力测试时,瞬时并发连接可以达到5000多个.只是等待触发时间上的长短和有效无效的区别.<br />
       在表4.2中可以清晰的看到并发连接的一些数据.<br />
       3.  服务端系统负载<br />
       通过自己编写的服务器端,对单结点的memcache进行了连接压力测试.其中测试用例的编写是这样的:启用七个客户端,每个客户端串行运行1000个进程,每个进程开3000线程,每个线程执行10次memcache的读操作或者写操作(操作相同).客户端并发连接.<br />
       1.  客户端(7)的环境:Intel(R) Xeon(R) CPU 5120 @ 1.86GHz,4G memory.<br />
       2.  服务器端(1)的环境:Intel(R) Xeon(R) CPU 5120 @ 1.86GHz,4G memory.<br />
       3.  网络环境:100M网卡,Cisco交换机.<br />
       4.  数据记录:见表4.2和图4.2.<br />
<a target="_blank" href="http://wf.xplore.cn/pics/memcache_t2.jpg"><img border="0" src="http://wf.xplore.cn/pics/memcache_t2.jpg" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" class="insertimage" /></a><br />
表4.2 memcache连接和系统负载<br />
图4.2 memcache连接和系统负载<br />
       很显然,memcache的运行在系统cpu的消耗上占十分少的比重,即便是很恐怖的并发连接也不会给系统带来多大的负载,因为其磁盘IO free(所有操作都在内存中)和相应的内存分配机制决定其占用cpu的极少,而相反,在网络IO上却花费很大的时间.<br />
       4.  空间分配,命中率<br />
       由于本地测试式的get数据非常固定,因此命中率基本为100%.在10.68.1.31上运行了一个有前端应用的memcachce服务器,运行时间已经有364个多小时了.<br />
       因此通过10.68.1.31上的数据说明(版本为1.1.13).通过memcache的统计协议可以清楚的看到其命中率高达95.9%,如表4.3所示:<br />
<a target="_blank" href="http://wf.xplore.cn/pics/memcache_t3.jpg"><img border="0" src="http://wf.xplore.cn/pics/memcache_t3.jpg" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" class="insertimage" /></a><br />
表4.3 memcache空间分配和命中</p>
<p>5.memcache客户端编写<br />
       1.  <a target="_blank" href="http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt">memcache协议</a><br />
       在memcache协议中规定了Client和Server的通信规则.<br />
       在源码分析中,主要分析了update/get/del/incr/decr几类的处理过程.其具体的规则可以在官方文档中有说明(),这里做简单的解释.</p>
<p class="quote-title">引用</p>
<p class="quote-content">1．  Update(set/add/replace):<br />
Client请求规则：<br />
<command></command><key></key><flag></flag><exptime></exptime><bytes></bytes>\r\n<br />
<data></data>\r\n<br />
Server响应规则：<br />
STORED\r\n 或者 NOT_STORED\r\n</p>
<p>其中，<command></command>是set,add,replace三种中的一种;<br />
<key></key>是client请求存储的键值;<br />
<flag></flag>是任意16bit长的unsigned int值,在get操作时,也将伴随data一起返回,可以用来存储某些认证信息或者描述信息;<br />
<exptime></exptime>是key－value对象的消亡时间,如果为0,则代表永不消亡;<br />
<bytes></bytes>是数据<data></data>的长度,千万小心,这个很重要,在memcache源代码里,直接读取这个数值来当作数据的长度,而不是用strlen计算的.这个显而易见,因为数据中有可能存在/r/n符号,也就是协议中规定的分隔符.如果出现,则严格按<bytes></bytes>长度取数据;<br />
<data></data>也就是value值,可以包含\r\n值.</p>
<p>STORED代表update操作成功，NOT_STORED代表update操作失败.</p>
<p>2．  Get(get/bget)<br />
Client请求规则：<br />
<command></command><key></key>*\r\n<br />
Server响应规则：<br />
VALUE <key></key><flag></flag><bytes></bytes>\r\n<br />
<data></data>\r\n<br />
END\r\n</p>
<p>Get/bget操作可以一次操作多个key值,server的响应格式中的关键字可以参看上面的解释,END代表数据显示结束.如果没有数据,则只有一个END\r\n.</p>
<p>3．  Delete(delete)<br />
Client请求规则：<br />
delete <key></key><time></time>\r\n<br />
Server响应规则：<br />
DELETED\r\n 或者 NOT_DELETED\r\n</p>
<p>其中，<time></time>是真正删除从server端删除的时间(sec),在时间未到前,server只将其放入一个delete队列里,其他诸如add/replace/get操作不能成功.</p>
<p>4．  Incr/decr(incr/decr)<br />
Client请求规则：<br />
<command></command><key></key><value></value>\r\n<br />
Server响应规则：<br />
   NOT_FOUND\r\n 或者 <value></value>\r\n</p>
<p>   其中,client请求的<value></value>是将要在<key></key>对应的value上增减的值;<br />
   Server的<value></value>是增减后的新值.</p>
<p>5．  其他(如stats/quit等)<br />
可以去看协议原文,使用不是太多.<br />
       2.  针对协议的一个简单实现<br />
       在这个例子中简单实现了一个能进行update/get/delete操作测试用例,只是简单socket的应用而已.如果可以,模仿这个写一个简单的客户端应该难度不大.</p>
<p class="quote-title">引用</p>
<p class="quote-content">/****************************************\<br />
*            mem_benchmark_conn2.c<br />
*<br />
*  Mon Mar 7 10:52:30 2007<br />
*  Copyright  2007  Spark Zheng<br />
*  Mail<br />
*  v0.1 Mar 5 2007 file:mem_benchmark_conn.c<br />
\****************************************/</p>
<p>#include &lt; stdio.h&gt;<br />
#include &lt; stdlib.h&gt;<br />
#include &lt; string.h&gt;<br />
#include &lt; ctype.h&gt;</p>
<p>#include &lt; unistd.h&gt;<br />
#include &lt; pthread.h&gt;<br />
#include &lt; time.h&gt;<br />
#include &lt; sys/types.h&gt;<br />
#include &lt; sys/time.h&gt;<br />
#include &lt; sys/resource.h&gt;<br />
//#include &lt; sys/socket.h&gt;<br />
//#include &lt; netdb.h&gt;<br />
//#include &lt; arpa/inet.h&gt;</p>
<p>#ifndef MEM_SERVER<br />
#define MEM_SERVER &#8220;10.210.71.25&#8243;<br />
#endif</p>
<p>#ifndef MEM_PORT<br />
#define MEM_PORT 11211<br />
#endif</p>
<p>void p_usage(void);<br />
void *conn_mem(void);<br />
int NonbSocket(const char *server, int port);<br />
int mem_set(int sock,const char *key,const char *value);<br />
int mem_add(int sock,const char *key,const char *value);<br />
int mem_get(int sock,const char *key,char *value);<br />
int mem_del(int sock,const char *key);</p>
<p>int main(int argc,char **argv)<br />
{<br />
       int conn=0;<br />
       int i=0;<br />
       pthread_t ptid[10000];<br />
       struct rlimit rlim;<br />
       struct timeval tv1,tv2;</p>
<p>       if(argc &lt; 2)<br />
       {<br />
               p_usage();<br />
               exit(255);<br />
       }</p>
<p>       conn = atoi(argv[1]);</p>
<p>       if(getrlimit(RLIMIT_NOFILE,&amp;rlim) != 0)<br />
       {<br />
               fprintf(stderr,&#8221;getrlimit error in line %d\n&#8221;,__LINE__);<br />
               exit(254);<br />
       }</p>
<p>       if((conn &gt; rlim.rlim_cur) &amp;&amp; (2*conn &gt; 1024))<br />
       {<br />
               rlim.rlim_cur = 2*conn;<br />
       }<br />
       if(rlim.rlim_cur &gt; rlim.rlim_max)<br />
       {<br />
               rlim.rlim_max = rlim.rlim_cur;<br />
       }</p>
<p>       if(setrlimit(RLIMIT_NOFILE,&amp;rlim) != 0)<br />
       {<br />
               fprintf(stderr,&#8221;setrlimit error in line %d\n&#8221;,__LINE__);<br />
               exit(254);<br />
       }</p>
<p>       gettimeofday(&amp;tv1,NULL);</p>
<p>       while(i++ &lt; conn)<br />
       {<br />
               if(pthread_create(&amp;ptid[i],NULL,(void *)conn_mem,NULL) != 0)<br />
               {<br />
                       perror(&#8220;pthread_create error\n&#8221;);<br />
                       exit(253);<br />
               }<br />
       }</p>
<p>       i=0;</p>
<p>       while(i++ &lt; conn)<br />
       {<br />
               if(pthread_join(ptid[i],NULL) != 0)<br />
               {<br />
                       perror(&#8220;pthread_join error\n&#8221;);<br />
                       exit(253);<br />
               }<br />
       }</p>
<p>       gettimeofday(&amp;tv2,NULL);</p>
<p>       printf(&#8220;time is %f,conn is %f persecond\n&#8221;,((tv2.tv_sec-tv1.tv_sec)+(tv2.tv_usec-tv1.tv_usec)/1000000.0),conn/((tv2.tv_sec-tv1.tv_sec)+(tv2.tv_usec-tv1.tv_usec)/1000000.0));</p>
<p>       return 0;<br />
}</p>
<p>void p_usage(void)<br />
{<br />
       printf(&#8220;Usage:./mem_benchmark_conn &lt; conn_num &gt;\n&#8221;);<br />
       printf(&#8220;Notice: the conn_num must &lt;= 10000\n&#8221;);<br />
       return;<br />
}</p>
<p>void *conn_mem(void)<br />
{<br />
       int sock;<br />
       char *key = &#8220;test_a&#8221;;<br />
       char *value = &#8220;this is a&#8221;;</p>
<p>       if((sock=NonbSocket(MEM_SERVER,MEM_PORT)) &lt; 0)<br />
       {<br />
               fprintf(stderr,&#8221;socket error in line %d\n&#8221;,__LINE__);<br />
               return NULL;<br />
       }</p>
<p>int i=0;<br />
while(i++ &lt; 10)<br />
{<br />
///*<br />
       mem_set(sock,key,value);<br />
//*/<br />
/*<br />
       char *key2=&#8221;test_b&#8221;;<br />
       char *value2=&#8221;this is b&#8221;;<br />
       mem_add(sock,key2,value2);<br />
*/<br />
/*<br />
       char buf[101];<br />
       mem_get(sock,key,buf);<br />
       printf(&#8220;get value for %s is %s\n&#8221;,key,buf);<br />
*/<br />
/*<br />
       char *key3=&#8221;test_c&#8221;;<br />
       mem_del(sock,key);<br />
*/<br />
}<br />
       close(sock);</p>
<p>       return NULL;<br />
}</p>
<p>int mem_set(int sock,const char *key,const char *value)<br />
{<br />
       char set[101];<br />
       char recv_buf[101];</p>
<p>       sprintf(set,&#8221;set %s 0 0 %d\r\n%s\r\n&#8221;,key,strlen(value),value);</p>
<p>       if(write(sock,set,strlen(set)) &lt; 0)<br />
       {<br />
               fprintf(stderr,&#8221;write error in line %d\n&#8221;,__LINE__);<br />
               return -1;<br />
       }</p>
<p>       if(read(sock,recv_buf,100) &lt; 0)<br />
       {<br />
               fprintf(stderr,&#8221;read error in line %d\n&#8221;,__LINE__);<br />
               return -2;<br />
       }</p>
<p>       printf(&#8220;in set %s\n&#8221;,recv_buf);</p>
<p>       return 0;<br />
}</p>
<p>int mem_add(int sock,const char *key,const char *value)<br />
{<br />
       char add[101];<br />
       char recv_buf[101];</p>
<p>       sprintf(add,&#8221;add %s 0 0 %d\r\n%s\r\n&#8221;,key,strlen(value),value);</p>
<p>       if(write(sock,add,strlen(add)) &lt; 0)<br />
       {<br />
               fprintf(stderr,&#8221;write error in line %d\n&#8221;,__LINE__);<br />
               return -1;<br />
       }</p>
<p>       if(read(sock,recv_buf,100) &lt; 0)<br />
       {<br />
               fprintf(stderr,&#8221;read error in line %d\n&#8221;,__LINE__);<br />
               return -2;<br />
       }</p>
<p>       printf(&#8220;in add %s\n&#8221;,recv_buf);</p>
<p>       return 0;<br />
}</p>
<p>int mem_get(int sock,const char *key,char *value)<br />
{<br />
       char get[101];<br />
       char recv_buf[101];</p>
<p>       sprintf(get,&#8221;get %s\r\n&#8221;,key);</p>
<p>       if(write(sock,get,strlen(get)) &lt; 0)<br />
       {<br />
               fprintf(stderr,&#8221;write error in line %d\n&#8221;,__LINE__);<br />
               return -1;<br />
       }</p>
<p>       if(read(sock,recv_buf,100) &lt; 0)<br />
       {<br />
               fprintf(stderr,&#8221;read error in line %d\n&#8221;,__LINE__);<br />
               return -2;<br />
       }</p>
<p>       strncpy(value,recv_buf,strlen(recv_buf));</p>
<p>       printf(&#8220;in get %s\n&#8221;,recv_buf);</p>
<p>       return 0;<br />
}</p>
<p>int mem_del(int sock,const char *key)<br />
{<br />
       char del[101];<br />
       char recv_buf[101];</p>
<p>       sprintf(del,&#8221;delete %s 0\r\n&#8221;,key);</p>
<p>       if(write(sock,del,strlen(del)) &lt; 0)<br />
       {<br />
               fprintf(stderr,&#8221;write error in line %d\n&#8221;,__LINE__);<br />
               return -1;<br />
       }</p>
<p>       if(read(sock,recv_buf,100) &lt; 0)<br />
       {<br />
               fprintf(stderr,&#8221;read error in line %d\n&#8221;,__LINE__);<br />
               return -2;<br />
       }</p>
<p>       printf(&#8220;in del %s\n&#8221;,recv_buf);</p>
<p>       return 0;<br />
}<br />
       3.  分布式的实现<br />
       分布式的实现可以这么完成,构建一个struct用于存放server信息.对于每个请求的key值,用很简单的hash算法(如 libmemcache用的是crc32)映射到server数组中的某个数组,然后对其进行通信.获取处理结果之后,将结果美化返回client.</p>
<p>6.<a target="_blank" href="http://www.monkey.org/~provos/libevent/">libevent</a>简介<br />
       1.  libevent<br />
       libevent是一个事件触发的网络库,适用于windows,linux,bsd等多种平台,内部使用iopc/epoll/kqueue等系统调用管理事件机制,而且根据libevent官方网站上公布的数据统计,似乎也有着非凡的性能.<br />
       从代码中看,libevent支持用户使用三种类型的事件,分别是网络IO,定时器,信号三种,在定时器的实现上使用了红黑树(RB tree)的数据结构,以达到高效查找,排序,删除定时器的目的,网络IO上,libevent的epoll居然用的EPOLLLT水平触发的方式,不容易出错,但是在效率上可能比EPOLLET要低一些.跟网络无关的,libevent也有一些缓冲区管理的函数,libevent没有提供缓存的函数.而且libevent的接口形式非常值得参考.<br />
       2.  epoll<br />
在linux中,libevent用的是epoll.如果有兴趣的话,可以查看man epoll页面.或者看前面blog上引用的libevent的资源.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/73.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hammerora Installation</title>
		<link>http://www.aaronw.cn/static/59.html</link>
		<comments>http://www.aaronw.cn/static/59.html#comments</comments>
		<pubDate>Fri, 07 Mar 2008 09:07:43 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/html/59.html</guid>
		<description><![CDATA[
Hammerora的安装过程[For Windows]
1.安装Hammerora之前，你应该下载如下的软件包：

Oracle 9i/10g Windows
TCL 8.4.11
TK 8.4.11 
Threads 2.6.2
Oratcl 4.3
optional:
Oracle intant client

2.Oracle安装就不多说了，除了慢也没什么其他要说的。
3.关于Instant Client的一些说明
可以下载到一个安装文件，里面包括一些动态连接库和类包。因为Hammerora可以再客户端机器上运行（也就是说安装Hammerora的机器上不需要有Oracle数据库，可以远程连接并测试服务器上的数据库），但如果从源代码编译安装Oratcl的时候，需要一些Oracle的库，但客户机上没有，所以如果以客户机的方式运行Hammerora，就要下载一个Instant Client。并且要在客户机上新增环境变量ORACLE_HOME，设置为Instant Client的安装路径。
Instant Client可以从www.oracle.com/technology/software/tech/oci/instantclient/ 下载。
4.TCL/TK的安装要多说一句，sourceforge上比较新的版本都没有提供预先编译和制作好的binary版本，只有source code。但.4a2是有binary版本的，但不要使用这个版本。因为预先变异的时候Thread选项没有打开，这个版本不是线程安全的。
编译过程很简单，因为tcl/tk都提供跨平台的编译支持。在windows下可以使用vc 6.0进行编译（推荐）。当然，如果你安装了VS .Net或者只使用Visual C++ Toolkit 2003也可以进行编译，稍微麻烦一点，具体参考http://wiki.tcl.tk/11431。我使用vc 6.0进行编译。

典型的批处理编译命令如下（以tcl为例，tk和thread类似）：


rem 首先设置命令行编译的环境变量，执行vcvars32批处理文件
if &#8220;%MSVCDir%&#8221; == &#8220;&#8221; call &#8220;C:\Program Files\Microsoft Visual Studio\vc98\bin\vcvars32.bat&#8221;
rem 设置tcl的安装路径
set INSTALLDIR=C:\Program Files\Tcl
rem 调用nmake编译tcl源文件，-nologo是省略版权信息的喧响，OPTS指定编译tcl的选项
nmake -nologo -f makefile.vc hose OPTS=none
if errorlevel 1 goto error
rem 安装，指定线程安全支持
nmake -nologo -f makefile.vc all install OPTS=threads
if errorlevel 1 goto errorgoto [...]]]></description>
			<content:encoded><![CDATA[<p><font size="2" face="Courier"></p>
<p align="center"><font size="2" face="Courier">Hammerora的安装过程[For Windows]</font></p>
<p></font><font face="Courier">1.安装Hammerora之前，你应该下载如下的软件包：</font></p>
<ul>
<li><font face="Courier">Oracle 9i/10g Windows</font></li>
<li><font face="Courier">TCL 8.4.11</font></li>
<li><font face="Courier">TK 8.4.11 </font></li>
<li><font face="Courier">Threads 2.6.2</font></li>
<li><font face="Courier">Oratcl 4.3</font></li>
<li><font face="Courier">optional:<br />
Oracle intant client</font></li>
</ul>
<p><font face="Courier">2.Oracle安装就不多说了，除了慢也没什么其他要说的。</font></p>
<p><font face="Courier">3.关于Instant Client的一些说明</font></p>
<p><font face="Courier">可以下载到一个安装文件，里面包括一些动态连接库和类包。因为Hammerora可以再客户端机器上运行（也就是说安装Hammerora的机器上不需要有Oracle数据库，可以远程连接并测试服务器上的数据库），但如果从源代码编译安装Oratcl的时候，需要一些Oracle的库，但客户机上没有，所以如果以客户机的方式运行Hammerora，就要下载一个Instant Client。并且要在客户机上新增环境变量ORACLE_HOME，设置为Instant Client的安装路径。</font></p>
<p><font face="Courier">Instant Client可以从</font><a href="http://www.oracle.com/technology/software/tech/oci/instantclient/"><font color="#0000ff" face="Courier"><u>www.oracle.com/technology/software/tech/oci/instantclient/</u></font></a><font face="Courier"> 下载。</font></p>
<p><font face="Courier">4.TCL/TK的安装要多说一句，sourceforge上比较新的版本都没有提供预先编译和制作好的binary版本，只有source code。但.4a2是有binary版本的，但不要使用这个版本。因为预先变异的时候Thread选项没有打开，这个版本不是线程安全的。<br />
编译过程很简单，因为tcl/tk都提供跨平台的编译支持。在windows下可以使用vc 6.0进行编译（推荐）。当然，如果你安装了VS .Net或者只使用Visual C++ Toolkit 2003也可以进行编译，稍微麻烦一点，具体参考</font><a href="http://wiki.tcl.tk/11431"><font color="#0000ff" face="Courier"><u>http://wiki.tcl.tk/11431</u></font></a><font face="Courier">。我使用vc 6.0进行编译。</font></p>
<p><span id="more-59"></span></p>
<p><font face="Courier">典型的批处理编译命令如下（以tcl为例，tk和thread类似）：</font></p>
<table border="1" bgColor="#ffffff" width="100%" cellPadding="3" cellSpacing="2" borderColor="#cccccc">
<tr>
<td><font size="2" face="Courier">rem 首先设置命令行编译的环境变量，执行vcvars32批处理文件<br />
if &#8220;%MSVCDir%&#8221; == &#8220;&#8221; call &#8220;C:\Program Files\Microsoft Visual Studio\vc98\bin\vcvars32.bat&#8221;<br />
rem 设置tcl的安装路径<br />
set INSTALLDIR=C:\Program Files\Tcl<br />
rem 调用nmake编译tcl源文件，-nologo是省略版权信息的喧响，OPTS指定编译tcl的选项<br />
nmake -nologo -f makefile.vc hose OPTS=none<br />
if errorlevel 1 goto error<br />
rem 安装，指定线程安全支持<br />
nmake -nologo -f makefile.vc all install OPTS=threads<br />
if errorlevel 1 goto error</font><font size="2" face="Courier">goto end</font><font size="2" face="Courier">:error<br />
echo *** BOOM! ***</font></p>
<p><font size="2" face="Courier">:end<br />
title Building Tcl, please wait&#8230;DONE!<br />
echo DONE!<br />
pause</font></td>
</tr>
</table>
<p><font face="Courier">Tk和Thread安装过程基本一样，不过需要指定tcl源代码的路径，因为这些源代码包</font><font face="Courier">会引用一些tcl的c头文件。</font></p>
<p><font face="Courier"></p>
<table border="1" bgColor="#ffffff" width="100%" cellPadding="3" cellSpacing="2" borderColor="#cccccc">
<tr>
<td><font size="2">rem tcl的文件路径是但前路径连接..\..\tcl8.4.11<br />
set TCLDIR=..\..\tcl8.4.11</font></td>
</tr>
</table>
<p>5.如果从源代码编译Thread扩展模块，你需要手工的安装这个模块。在%</p>
<p></font><font face="Courier">TCL_HOME%/lib下新建一个目录叫做Thread,在里面添加一个包索引文件命名为</font><font face="Courier">pkgIndex.tcl，内容为：</font><font face="Courier">package ifneeded Thread 2.6 [list load [file join $dir thread26.dll]]</font></p>
<p><font face="Courier">然后把编译好Thread2.6.2拷贝到Thread目录下。</font></p>
<p><font face="Courier">6.安装Oratcl也很简单，Oratcl的安装包下有install.tcl，使用wish84或者tclsh执</font><font face="Courier">行即可。</font></p>
<p><font face="Courier">7.测试是否安装成功，可以打开wish84或tclsh，运行以下命令：<br />
package require Thread<br />
package require Oratcl<br />
如果成功，则表明安装成功。</font></p>
<p><font face="Courier">8.Hammerora安装，可以从sourceforge上下载到Hammerora的windows安装文件。双击</font><font face="Courier">安装就好了。不过要注意的是，Hammerora会自带一个tcl的解释器，但这个解释器不</font><font face="Courier">是线程安全和也没有oratcl扩展库。所以把Hammerora.bat改一下：把wish84的路径</font><font face="Courier">改成你刚编译安装tcl的路径就好了。</font></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/59.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hammerora TPC-C Plus</title>
		<link>http://www.aaronw.cn/static/58.html</link>
		<comments>http://www.aaronw.cn/static/58.html#comments</comments>
		<pubDate>Fri, 07 Mar 2008 09:06:08 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/html/58.html</guid>
		<description><![CDATA[


 几点说明：
1.这篇文字在操作步骤之前翻译自：http://hammerora.sourceforge.net/tpc-c.htm。
2.适合于英文不好和时间紧迫之人。
3.有什么错误欢迎指出。



TPC-C基准是目前最知名的数据库基准，关于它的详细信息可以在tpc.org的主页上找到。目前已经发布了5.1版，在TPC的主页上有一份TPC的详细说明。这份说明和其中的示例过程是hammerora tpc-c基准测试的实现基础。
所有的SQL语句都是原封不动的从说明中拷贝过来的，没有进行任何的优化。唯一的改变就是将标准中的数据库操作与Oracle进行了集成，并改正了说明中的个别SQL语法错误。但必须注意的是，这个实现并不是TPC-C基准的一个完全的实现。这个实现在不使用复杂的事务管理软件的前提下，尽可能的实现了TPC-C基准。
Hammerora包含了所有用于创建TPC-C关系模式和装载TPC-C基准数据所需要的Oracle存储过程和TCL脚本。
如果想要创建TPC-C的关系模式，首先选择TPC-C关系模式选项，并根据将要创建关系模式的数据库的基本信息填写表格内容。填写之后，点击&#8221;Create TPC-C&#8221;按钮并确认提示对话框。Hammerora会创建必要的用户，表和索引还有存储过程。
在运行TPC-C测试之前，确认DBMS_RANDOM包已经被安装了，确认方法是以sys用户运行$ORACLE_HOME/rdbms/admin/catoctk脚本。然后选择TPC-C驱动脚本菜单项，之后hammerora就会自动创建一个TPC-C的驱动脚本。驱动脚本中会根据TPC-C scheme中所填入的值来生成连接字符串。默认状态下，驱动脚本的实现中考虑了键盘敲击时间和思考时间。可以设置KEYANDTHINK变量值为 false关闭对这些时间的计算。
最后创建一定数目的虚拟用户（TPC-C的说明中指出每个实例有10个用户，并且要计算思考时间），然后就可以运行Hammerora来对你的Oracle数据库进行TPC-C的方针测试了。
总之，使用Hammerora进行tpc-c测试的步骤如下（假设system密码是pwd,service id是pku）：

填充TPC-C Scheme：service id:pku;system password:pwd;tpc-c user:tpcc;tpcc password:tpcc;default table space:&#60;whaterver exists&#62;
填充Transaction Counters：connect string:system/pwd@pku
创建TPC-C scheme
创建虚拟用户数，10个/warehouse，其他选项请看文档。
产生驱动脚本
run Hammerora Loadtest

ps:如果想要看到实时的tpm统计，那么请点击transaction counter按钮。
]]></description>
			<content:encoded><![CDATA[<table style="height: 88px;" border="1" cellspacing="2" cellpadding="3" width="670" bgcolor="#dddddd" bordercolor="#cccccc">
<tbody>
<tr>
<td><span style="font-family: 幼圆; font-size: xx-small;"> 几点说明：</span></p>
<p><span style="font-family: 幼圆; font-size: xx-small;">1.这篇文字在操作步骤之前翻译自：</span><a href="http://hammerora.sourceforge.net/tpc-c.htm"><span style="font-family: 幼圆; color: #0000ff; font-size: xx-small;"><span style="text-decoration: underline;">http://hammerora.sourceforge.net/tpc-c.htm</span></span></a><span style="font-family: 幼圆; font-size: xx-small;">。</span></p>
<p><span style="font-family: 幼圆; font-size: xx-small;">2.适合于英文不好和时间紧迫之人。</span></p>
<p><span style="font-family: 幼圆; font-size: xx-small;">3.有什么错误欢迎指出。</span></td>
</tr>
</tbody>
</table>
<p><span style="font-family: Courier; font-size: x-small;">TPC-C基准是目前最知名的数据库基准，关于它的详细信息可以在tpc.org的主页上找到。目前已经发布了5.1版，在TPC的主页上有一份TPC的详细说明。这份说明和其中的示例过程是hammerora tpc-c基准测试的实现基础。</span></p>
<p><span style="font-family: Courier; font-size: x-small;">所有的SQL语句都是原封不动的从说明中拷贝过来的，没有进行任何的优化。唯一的改变就是将标准中的数据库操作与Oracle进行了集成，并改正了说明中的个别SQL语法错误。但必须注意的是，这个实现并不是TPC-C基准的一个完全的实现。这个实现在不使用复杂的事务管理软件的前提下，尽可能的实现了TPC-C基准。</span></p>
<p><span style="font-family: Courier; font-size: x-small;">Hammerora包含了所有用于创建TPC-C关系模式和装载TPC-C基准数据所需要的Oracle存储过程和TCL脚本。</span></p>
<p><span style="font-family: Courier; font-size: x-small;">如果想要创建TPC-C的关系模式，首先选择TPC-C关系模式选项，并根据将要创建关系模式的数据库的基本信息填写表格内容。填写之后，点击&#8221;Create TPC-C&#8221;按钮并确认提示对话框。Hammerora会创建必要的用户，表和索引还有存储过程。</span></p>
<p><span style="font-family: Courier; font-size: x-small;">在运行TPC-C测试之前，确认DBMS_RANDOM包已经被安装了，确认方法是以sys用户运行$ORACLE_HOME/rdbms/admin/catoctk脚本。然后选择TPC-C驱动脚本菜单项，之后hammerora就会自动创建一个TPC-C的驱动脚本。驱动脚本中会根据TPC-C scheme中所填入的值来生成连接字符串。默认状态下，驱动脚本的实现中考虑了键盘敲击时间和思考时间。可以设置KEYANDTHINK变量值为 false关闭对这些时间的计算。</span></p>
<p><span style="font-family: Courier; font-size: x-small;">最后创建一定数目的虚拟用户（TPC-C的说明中指出每个实例有10个用户，并且要计算思考时间），然后就可以运行Hammerora来对你的Oracle数据库进行TPC-C的方针测试了。</span></p>
<p><span style="font-family: Courier; font-size: x-small;">总之，使用Hammerora进行tpc-c测试的步骤如下（假设system密码是pwd,service id是pku）：</span></p>
<ol>
<li><span style="font-family: Courier; font-size: x-small;">填充TPC-C Scheme：service id:pku;system password:pwd;tpc-c user:tpcc;tpcc password:tpcc;default table space:&lt;whaterver exists&gt;</span></li>
<li><span style="font-family: Courier; font-size: x-small;">填充Transaction Counters：connect string:system/pwd@pku</span></li>
<li><span style="font-family: Courier; font-size: x-small;">创建TPC-C scheme</span></li>
<li><span style="font-family: Courier; font-size: x-small;">创建虚拟用户数，10个/warehouse，其他选项请看文档。</span></li>
<li><span style="font-family: Courier; font-size: x-small;">产生驱动脚本</span></li>
<li><span style="font-family: Courier; font-size: x-small;">run Hammerora Loadtest</span></li>
</ol>
<p><span style="font-family: Courier; font-size: x-small;">ps:如果想要看到实时的tpm统计，那么请点击transaction counter按钮。</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/58.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>网站测试技术简介</title>
		<link>http://www.aaronw.cn/static/57.html</link>
		<comments>http://www.aaronw.cn/static/57.html#comments</comments>
		<pubDate>Fri, 07 Mar 2008 09:04:57 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/html/57.html</guid>
		<description><![CDATA[ 1 概述
在一个软件项目开发中，系统测试是保证整体项目质量的重要一环，本文将就网站的测试技术及相应的自动测试工具做一个简要的介绍。主要就如下几个方面进行探讨：功能测试
性能测试
安全性测试
稳定性测试
浏览器兼容性测试
可用性/易用性测试
链接测试
代码合法性测试

2 测试内容
2.1 功能测试
在实际工作中，功能在每一个系统中的具有其不确定性，而我们不可能采用穷举的方法进行测试，因而导致了功能测试较为困难，我们依据80/20原则（即80%的错误存在于系统的20%的部分）对于测试用例的设计采用如下两种方法
2.1.1 白盒测试
白盒测试即使用程序设计的控制结构导出测试用例。基于目前的现状我们采用基本路径测试方法进行白盒测试，此种方法简单高效。基本路径测试方法的简单说明如下：
¨ 首先通过系统设计的流程图导出数据流图
¨ 根据数据流图计算其环形复杂性
V(G)=E-N+2
或 V(G)=P+1
V(G)：环形负责性
E ：流图中边的数量
N ：流图中节点的数量
P ：流图中判定节点的数量
¨ 我们设定V(G)条路径
¨ 我们设计V(G)条路径的模拟数据
¨ 根据数据进行相应的测试
2.1.2 黑盒测试
黑盒测试即派生出执行程序所有功能需求的输入条件，从而导出测试用例，进行测试的方法，黑盒测试用于辅助白盒测试。
我们采用等价划分的方法进行测试，即为将程序的输入域划分为数据类，以便导出测试用例。一般情况下输入条件为：一个特定的数值、一个数值域、一组相关值或者一个布尔条件。
2.1.3 网站功能测试
对于网站的测试而言，每一个独立的功能模块需要单独的测试用例的设计导出，主要依据为《需求分析》，对于应用程序模块需要设计者提供基本路径测试法的测试用例
具有测试用例后可以采用OpenSTA(Open System Testing Architecture)进行自动化测试
2.2 性能测试
网站的性能测试对于网站的运行而言异常重要，但是目前对于网站的性能测试做的不够，我们在进行系统设计时也没有一个很好的基准可以参考，因而建立网站的性能测试的一整套的测试方案将是至关重要的。
网站的性能测试主要从两个方面进行：负荷测试(Load)和压力测试(Stress),负荷测试指的是进行一些边界数据的测试，压力测试更像是恶意测试，压力测试倾向应该是致使整个系统崩溃。
性能测试可以采用相应的工具进行自动化测试，我们目前采用如下工具
ab &#8212;&#8211;Apache 的测试工具
OpenSTA—开发系统测试架构
2.3 安全性测试
目前网络安全问题日益重要，特别对于有交互信息的网站及进行电子商务活动的网站尤其重要。目前我们的测试没有涵盖网站的安全性的测试，我们拟定采用工具来测定，工具如下
SAINT&#8212;&#8212;- Security Administrator&#8217;s Integrated Network Tool
此工具能够测出网站系统的相应的安全问题，并且能够给出安全漏洞的解决方案，不过是一些较为常见的漏洞解决方案。
2.4 稳定性测试
网站的稳定性测试是指网站的运行中整个系统是否运行正常，目前没有更好的测试方案，主要采用将测试服务器长时间运转进行测试。
2.5 浏览器兼容性测试
通过白盒测试或者黑盒测试导出的测试用例，采用相应的工具进行测试，可以采用OpenSTA进行测试，此测试工具可以采用不同的浏览器进行测试。
2.6 可用性/易用性测试
可用性/易用性方面目前我们只能采用手工测试的方法进行评判，而且缺乏一个很好的评判基准进行，此一方面需要大家共同讨论。
2.7 链接测试
超级链接对于网站用户而言意味着能不能流畅的使用整个网站提供的服务，因而链接将作为一个独立的项目进行测试。目前我们已经有了一个测试工具
Xenu&#8212;&#8212;主要测试链接的正确性的工具
可惜的是对于动态生成的页面的测试会出现一些错误。
2.8 代码合法性测试
代码合法性测试主要包括2个部分：程序代码合法性检查与显示代码合法性检查
¨ 程序代码合法性检查
程序代码合法性检查主要标准为《intergrp小组编程规范》，目前采用由SCM管理员进行规范的检查，未来期望能够有相应的工具进行测试。
¨ 显示代码合法性检查
显示代码的合法性检查，主要分为Html、JavaScript、Css代码检查，目前采用
HTML代码检查&#8212;&#8212;采用CSE HTML Validator进行测试
JavaScript、Css也可以在网上下载相应的测试工具。
3 测试工具
OpenSTA
主要做性能测试的负荷及压力测试，使用比较方便，可以编写测试脚本，也可以先行自动生成测试脚本，而后对于应用测试脚本进行测试。
SAINT
网站安全性测试，能够对于指定网站进行安全性测试，并可以提供安全问题的解决方案。
CSE HTML Validator
一个有用的对于HTML代码进行合法性检查的工具
Ab(Apache Bench)
Apache自带的对于性能测试方面的工具，功能不是很多，但是非常实用。
Crash-me
Mysql自带的测试数据库性能的工具，能够测试多种数据库的性能。
上述工具除Ab及Crash-me外均可在以下目录中找得到
\smbserver\apps\linuxapp\intergrp
ab及Crash-me请至相应的网站上察看相应的资料}
4 后记
此文只是对于网站的测试方面做了一个简单的介绍，提供的工具比较少，但是可以保证能够使用（当然都是可以从网上免费得到的），另外还有很多测试工具是需要Money的，大家有兴趣可以试用，对于上述提到的测试工具我也只是做了一个初步的调研，详细的功能说明请察看相关的说明文档。
对于网站的测试中比较重要的还有一个部分就是对于数据库的测试，由于对于数据库性能测试较好的工具需要一些Money因而我们采用Mysql的 Crash-me,但是同时也存在一个问题就是对于不同的数据库的测试采用第三方的工具较好。因而大家可以对于其他数据库性能测试的工具进行研究。
5 参考资料
(1)《软件工程-实践者的研究方法》&#8212;&#8211;Roger S.Pressman
(2) http://www.softwareqatest.com
(3) http://www.soft.com/
(4) http://www.qaforums.com
(5) http://www.opensta.org
]]></description>
			<content:encoded><![CDATA[<p> 1 概述<br />
在一个软件项目开发中，系统测试是保证整体项目质量的重要一环，本文将就网站的测试技术及相应的自动测试工具做一个简要的介绍。主要就如下几个方面进行探讨：功能测试<br />
性能测试<br />
安全性测试<br />
稳定性测试<br />
浏览器兼容性测试<br />
可用性/易用性测试<br />
链接测试<br />
代码合法性测试<br />
<span id="more-57"></span><br />
2 测试内容<br />
2.1 功能测试<br />
在实际工作中，功能在每一个系统中的具有其不确定性，而我们不可能采用穷举的方法进行测试，因而导致了功能测试较为困难，我们依据80/20原则（即80%的错误存在于系统的20%的部分）对于测试用例的设计采用如下两种方法<br />
2.1.1 白盒测试<br />
白盒测试即使用程序设计的控制结构导出测试用例。基于目前的现状我们采用基本路径测试方法进行白盒测试，此种方法简单高效。基本路径测试方法的简单说明如下：<br />
¨ 首先通过系统设计的流程图导出数据流图<br />
¨ 根据数据流图计算其环形复杂性<br />
V(G)=E-N+2<br />
或 V(G)=P+1<br />
V(G)：环形负责性<br />
E ：流图中边的数量<br />
N ：流图中节点的数量<br />
P ：流图中判定节点的数量<br />
¨ 我们设定V(G)条路径<br />
¨ 我们设计V(G)条路径的模拟数据<br />
¨ 根据数据进行相应的测试<br />
2.1.2 黑盒测试<br />
黑盒测试即派生出执行程序所有功能需求的输入条件，从而导出测试用例，进行测试的方法，黑盒测试用于辅助白盒测试。<br />
我们采用等价划分的方法进行测试，即为将程序的输入域划分为数据类，以便导出测试用例。一般情况下输入条件为：一个特定的数值、一个数值域、一组相关值或者一个布尔条件。<br />
2.1.3 网站功能测试<br />
对于网站的测试而言，每一个独立的功能模块需要单独的测试用例的设计导出，主要依据为《需求分析》，对于应用程序模块需要设计者提供基本路径测试法的测试用例<br />
具有测试用例后可以采用OpenSTA(Open System Testing Architecture)进行自动化测试<br />
2.2 性能测试<br />
网站的性能测试对于网站的运行而言异常重要，但是目前对于网站的性能测试做的不够，我们在进行系统设计时也没有一个很好的基准可以参考，因而建立网站的性能测试的一整套的测试方案将是至关重要的。<br />
网站的性能测试主要从两个方面进行：负荷测试(Load)和压力测试(Stress),负荷测试指的是进行一些边界数据的测试，压力测试更像是恶意测试，压力测试倾向应该是致使整个系统崩溃。<br />
性能测试可以采用相应的工具进行自动化测试，我们目前采用如下工具<br />
ab &#8212;&#8211;Apache 的测试工具<br />
OpenSTA—开发系统测试架构</p>
<p>2.3 安全性测试<br />
目前网络安全问题日益重要，特别对于有交互信息的网站及进行电子商务活动的网站尤其重要。目前我们的测试没有涵盖网站的安全性的测试，我们拟定采用工具来测定，工具如下<br />
SAINT&#8212;&#8212;- Security Administrator&#8217;s Integrated Network Tool<br />
此工具能够测出网站系统的相应的安全问题，并且能够给出安全漏洞的解决方案，不过是一些较为常见的漏洞解决方案。<br />
2.4 稳定性测试<br />
网站的稳定性测试是指网站的运行中整个系统是否运行正常，目前没有更好的测试方案，主要采用将测试服务器长时间运转进行测试。<br />
2.5 浏览器兼容性测试<br />
通过白盒测试或者黑盒测试导出的测试用例，采用相应的工具进行测试，可以采用OpenSTA进行测试，此测试工具可以采用不同的浏览器进行测试。<br />
2.6 可用性/易用性测试<br />
可用性/易用性方面目前我们只能采用手工测试的方法进行评判，而且缺乏一个很好的评判基准进行，此一方面需要大家共同讨论。<br />
2.7 链接测试<br />
超级链接对于网站用户而言意味着能不能流畅的使用整个网站提供的服务，因而链接将作为一个独立的项目进行测试。目前我们已经有了一个测试工具<br />
Xenu&#8212;&#8212;主要测试链接的正确性的工具<br />
可惜的是对于动态生成的页面的测试会出现一些错误。<br />
2.8 代码合法性测试<br />
代码合法性测试主要包括2个部分：程序代码合法性检查与显示代码合法性检查<br />
¨ 程序代码合法性检查<br />
程序代码合法性检查主要标准为《intergrp小组编程规范》，目前采用由SCM管理员进行规范的检查，未来期望能够有相应的工具进行测试。<br />
¨ 显示代码合法性检查<br />
显示代码的合法性检查，主要分为Html、JavaScript、Css代码检查，目前采用<br />
HTML代码检查&#8212;&#8212;采用CSE HTML Validator进行测试<br />
JavaScript、Css也可以在网上下载相应的测试工具。<br />
3 测试工具<br />
OpenSTA<br />
主要做性能测试的负荷及压力测试，使用比较方便，可以编写测试脚本，也可以先行自动生成测试脚本，而后对于应用测试脚本进行测试。<br />
SAINT<br />
网站安全性测试，能够对于指定网站进行安全性测试，并可以提供安全问题的解决方案。<br />
CSE HTML Validator<br />
一个有用的对于HTML代码进行合法性检查的工具<br />
Ab(Apache Bench)<br />
Apache自带的对于性能测试方面的工具，功能不是很多，但是非常实用。<br />
Crash-me<br />
Mysql自带的测试数据库性能的工具，能够测试多种数据库的性能。</p>
<p>上述工具除Ab及Crash-me外均可在以下目录中找得到<br />
\smbserver\apps\linuxapp\intergrp<br />
ab及Crash-me请至相应的网站上察看相应的资料}</p>
<p>4 后记<br />
此文只是对于网站的测试方面做了一个简单的介绍，提供的工具比较少，但是可以保证能够使用（当然都是可以从网上免费得到的），另外还有很多测试工具是需要Money的，大家有兴趣可以试用，对于上述提到的测试工具我也只是做了一个初步的调研，详细的功能说明请察看相关的说明文档。<br />
对于网站的测试中比较重要的还有一个部分就是对于数据库的测试，由于对于数据库性能测试较好的工具需要一些Money因而我们采用Mysql的 Crash-me,但是同时也存在一个问题就是对于不同的数据库的测试采用第三方的工具较好。因而大家可以对于其他数据库性能测试的工具进行研究。</p>
<p>5 参考资料<br />
(1)《软件工程-实践者的研究方法》&#8212;&#8211;Roger S.Pressman<br />
(2) http://www.softwareqatest.com<br />
(3) http://www.soft.com/<br />
(4) http://www.qaforums.com<br />
(5) http://www.opensta.org</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/57.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>测试一下你的防火墙的安全性！！！！！</title>
		<link>http://www.aaronw.cn/static/56.html</link>
		<comments>http://www.aaronw.cn/static/56.html#comments</comments>
		<pubDate>Fri, 07 Mar 2008 09:02:58 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/html/56.html</guid>
		<description><![CDATA[http://www.pcflank.com/scanner1s.htm
]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" href="http://www.pcflank.com/scanner1s.htm"><font size="5" color="#2f5fa1">http://www.pcflank.com/scanner1s.htm</font></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/56.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>提高页面访问速度</title>
		<link>http://www.aaronw.cn/static/55.html</link>
		<comments>http://www.aaronw.cn/static/55.html#comments</comments>
		<pubDate>Fri, 07 Mar 2008 09:02:13 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/html/55.html</guid>
		<description><![CDATA[速度是用户体验非常重要的一部分。如果说用户体验可以分成“能用、可用、好用”，“能用”就是后两者的基础。
大部分用户往往会死等一个网页出来，而很少会同时做其他事情。没有速度，如何向用户展示流程，如何带给用户进一步的体验呢？
Yahoo! Exceptional Performance团队在Developer Network上总结：80-90%的客户端响应时间都用于下载所有的页面元素：图片、样式表、脚本文件、Flash等等。
因此，加快页面响应速度，提高页面性能是提高用户体验重要的第一步。

Yahoo!最近提供了一个页面性能分析工具YSlow，以Firefox Add-on的形式集成到Firebug中。
装上这个工具后，它会分析页面加载的所有内容，根据加速站点的13条规则给站点页面评分并给出建议。
并且它会列出所分析页面上所有元素的类型：URL、过期时间、gzip状态、load时间、文件大小、ETag、包括HTTP响应报头，以及页面Empty Cache和Full Cache时的数据。


Yahoo!页面加速的13条规则如下：（http://developer.yahoo.com/performance/rules.html#num_http ）

1. 减少 HTTP 请求
2. 使用 CDN
3. 为网页元素添加 Expires Header
4. 支持 Gzip
5. 把 CSS 放在网页顶部
6. 把活动的脚本文件移到底部
7. CSS中避免使用Expression语句
8. 使用外部 JavaScript 和 CSS 文件
9. 减少 DNS 查表时间
10. 最小化 JavaScript
11. 避免网页跳转
12. 删除重复的脚本 
13 .配置Etag
XXX站点首页的测试:


]]></description>
			<content:encoded><![CDATA[<p><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">速度是用户体验非常重要的一部分。如果说用户体验可以分成“能用、可用、好用”，</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">“</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">能用</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">”</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">就是</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">后两者</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">的基础。</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">大部分用户往往会死等一个网页出来，而很少会同时做其他事情。没有速度，如何向用户展示流程，如何带给用户进一步的体验呢？</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">Yahoo! Exceptional Performance</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">团队在</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">Developer Network</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">上总结：</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">80-90%</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">的客户端响应时间都用于下载所有的页面元素：图片、样式表、脚本文件、</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">Flash</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">等等。</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">因此，加快页面响应速度，提高页面性能是提高用户体验重要的第一步。</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">Yahoo!</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">最近提供了一个页面性能分析工具</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">YSlow</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">，以</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">Firefox Add-on</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">的形式集成到</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">Firebug</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">中。</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">装上这个工具后，它会分析页面加载的所有内容，根据加速站点的</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">13</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">条规则给站点页面评分并给出建议。</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">并且它会列出所分析页面上所有元素的类型：</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">URL</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">、过期时间、</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">gzip</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">状态、</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">load</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">时间、文件大小、</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">ETag</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">、包括</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">HTTP</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">响应报头，以及页面</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">Empty Cache</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">和</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">Full Cache</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">时的数据。</span></font></p>
<p><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体"></span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"><span id="more-55"></span></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">Yahoo!</span></font><strong><font size="2" face="宋体"><span style="font-weight: bold; font-size: 10pt; font-family: 宋体">页面加速的</span></font></strong><strong><font size="2" face="Verdana"><span style="font-weight: bold; font-size: 10pt; font-family: Verdana" lang="EN-US">13</span></font></strong><strong><font size="2" face="宋体"><span style="font-weight: bold; font-size: 10pt; font-family: 宋体">条规则</span></font></strong><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">如下：（</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"><a href="http://developer.yahoo.com/performance/rules.html#num_http" title="http://developer.yahoo.com/performance/rules.html#num_http">http://developer.yahoo.com/performance/rules.html#num_http</a> </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">）</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">1. </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">减少</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"> HTTP </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">请求</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">2. </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">使用</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"> CDN</span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">3. </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">为网页元素</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">添加</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"> Expires Header</span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">4. </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">支持</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"> Gzip</span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">5. </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">把</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"> CSS </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">放在网页顶部</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">6. </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">把活动的脚本文件移到底部</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">7. CSS</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">中</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">避免使用</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">Expression</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">语句</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">8. </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">使用外部</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"> JavaScript </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">和</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"> CSS </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">文件</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">9. </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">减少</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"> DNS </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">查表时间</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">10. </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">最小化</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"> JavaScript</span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">11. </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">避免网页跳转</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">12. </span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">删除重复的脚本</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana"> </span><span lang="EN-US"></span></font></p>
<p><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">13 .</span></font><font size="2" face="宋体"><span style="font-size: 10pt; font-family: 宋体">配置</span></font><font size="2" face="Verdana"><span style="font-size: 10pt; font-family: Verdana" lang="EN-US">Etag</span></font></p>
<p>XXX站点首页的测试:</p>
<p><img src="http://enissue.com/wp-content/uploads/2007/08/untitled.bmp" alt="untitled.bmp" /></p>
<p><img src="http://enissue.com/wp-content/uploads/2007/08/untitled2.bmp" alt="untitled2.bmp" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/55.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>这些大网站都用什么操作系统与 Web 服务器 ?</title>
		<link>http://www.aaronw.cn/static/46.html</link>
		<comments>http://www.aaronw.cn/static/46.html#comments</comments>
		<pubDate>Fri, 07 Mar 2008 08:41:54 +0000</pubDate>
		<dc:creator>Aaron.wang</dc:creator>
				<category><![CDATA[WEB]]></category>

		<guid isPermaLink="false">http://www.aaronw.cn/html/46.html</guid>
		<description><![CDATA[一时好奇，看看这些大网站的 Web 服务器信息(操作系统/Web 服务器/应用服务器软件).
Google
用哪些软件做 Web Server?
除了有两个节点操作系统看出来是 Linux 外，其他的都是未知的. Web 服务器用的都是 GWS ? 我估计是 Google Web Server 的缩写．
Yahoo!
操作系统都是 FreeBSD. 其他的都不可知.Yahoo! 的网络安全据说是一级棒!
微软
操作系统全是 Windows 2003(如果使用 Linux 会被笑死) , 看来 Windows 2000 已经退出微软自己的舞台．Web 服务器用的是Microsoft-IIS/6.0．
eBay
操作系统用:Windows Server 2003 /2000, Web服务器用 Microsoft-IIS/6.0 (5.0). 对这个检测有些怀疑．eBay 大规模使用 Windows ?

GNU.org
操作系统全是 Debian Linux(没错,Debian 是 GNU 正宗传人)． Web 服务器: Apache/1.3.31 (Debian GNU/Linux) mod_python/2.7.10 Python/2.3.4 , 也有的配置是：Apache/1.3.26 (Unix) [...]]]></description>
			<content:encoded><![CDATA[<p>一时好奇，看看这些大网站的 Web 服务器信息(操作系统/Web 服务器/应用服务器软件).</p>
<p><a href="http://www.google.com/"><font color="#4389cf">Google</font></a><br />
用<a href="http://uptime.netcraft.com/up/graph?site=www.google.com"><font color="#4389cf">哪些软件</font></a>做 Web Server?<br />
除了有两个节点操作系统看出来是 Linux 外，其他的都是未知的. Web 服务器用的都是 GWS ? 我估计是 Google Web Server 的缩写．</p>
<p><a href="http://www.yahoo.com/"><font color="#4389cf">Yahoo!</font></a><br />
操作系统都是 FreeBSD. 其他的都不可知.Yahoo! 的网络安全据说是一级棒!</p>
<p><a href="http://www.microsoft.com/"><font color="#4389cf">微软</font></a><br />
操作系统全是 Windows 2003(如果使用 Linux 会被笑死) , 看来 Windows 2000 已经退出微软自己的舞台．Web 服务器用的是Microsoft-<acronym title="Internet Information Services">IIS</acronym>/6.0．</p>
<p><a href="http://www.ebay.com/"><font color="#4389cf">eBay</font></a><br />
操作系统用:Windows Server 2003 /2000, Web服务器用 Microsoft-<acronym title="Internet Information Services">IIS</acronym>/6.0 (5.0). 对这个检测有些怀疑．eBay 大规模使用 Windows ?<br />
<span id="more-46"></span><br />
<a href="http://gnu.org/"><font color="#4389cf">GNU.org</font></a><br />
操作系统全是 Debian Linux(没错,Debian 是 <acronym title="GNU's Not Unix">GNU</acronym> 正宗传人)． Web 服务器: Apache/1.3.31 (Debian <acronym title="GNU's Not Unix">GNU</acronym>/Linux) mod_python/2.7.10 Python/2.3.4 , 也有的配置是：Apache/1.3.26 (Unix) Debian <acronym title="GNU's Not Unix">GNU</acronym>/Linux mod_python/2.7.8 Python/2.1.3．GNU.org 对 Python 用的比较多的．</p>
<p>看看国内的一些公司．</p>
<p><a href="http://www.alibaba.com/"><font color="#4389cf">阿里巴巴</font></a><br />
操作系统是 Linux . Web 服务器: Apache/1.3.29 (Unix) mod_alibaba/1.0 Resin/2.1.13 .<br />
(+mod_gzip/1.3.26.1a). mod_alibaba 模块估计是专门定制的．</p>
<p><a href="http://www.sina.com.cn/"><font color="#4389cf">Sina</font></a><br />
操作系统是 FreeBSD. Web 服务器都是 Apache/2.0.54 .</p>
<p><a href="http://www.baidu.com/"><font color="#4389cf">百度</font></a><br />
操作系统是 Linux , Web 服务器: Apache/1.3.27. 整齐划一．</p>
<p><a href="http://www.sohu.com/"><font color="#4389cf">搜狐</font></a><br />
操作系统居然是 SCO UNIX ,Web 服务器信息: Apache/1.3.33 (Unix) mod_gzip/1.3.19.1a<br />
看来业界传闻&#8221;Sohu 的技术力量最差&#8221;并不夸张．</p>
<p><a href="http://www.163.com/"><font color="#4389cf">网易</font></a><br />
操作系统:Linux. Web 服务器信息: Apache/2.0.5x</p>
<p>这些数据是在<a href="http://uptime.netcraft.com/"><font color="#4389cf">Netcraft</font></a>得到的．</p>
<p>分析一下上述数据，可以得到的基本信息如下:</p>
<p>1. <a href="http://www.kernel.org/"><font color="#4389cf">Linux</font></a> vs <a href="http://freebsd.org/"><font color="#4389cf">FreeBSD</font></a> 半斤八两．很多公司用 Linux , <a href="http://freebsd.org/"><font color="#4389cf">FreeBSD</font></a> 也不乏拥趸．但开源操作系统做 Web 应用是首选已经是一个既定事实．<br />
2. 关于 Apache ,虽然 Apache 目前还是推荐使用 1.3 版本. 但是很多公司还是使用了 2.0 版．而 <a href="http://apache.org/"><font color="#4389cf">Apache.org</font></a> 自己也全在使用 Apache 2.0 .甚至是 2.2 ．<br />
3. Mod_gzip 被一些公司有选择的使用．<br />
4. 技术实力强的公司定制自己专用的模块.<br />
这些判断的前提是 Netcraft 的探测是正确的并且具备代表性.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronw.cn/static/46.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
