<?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>Feng&#039;s Blog</title>
	<atom:link href="http://www.mzfeng.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.mzfeng.com</link>
	<description>关注internet web windows linux 系统管理 服务器架构</description>
	<lastBuildDate>Thu, 02 Sep 2010 21:44:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>轻松搞定window2003 超出远程连接限制</title>
		<link>http://www.mzfeng.com/html/y2010/333.html</link>
		<comments>http://www.mzfeng.com/html/y2010/333.html#comments</comments>
		<pubDate>Thu, 02 Sep 2010 21:44:33 +0000</pubDate>
		<dc:creator>mzfeng</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[window2003]]></category>
		<category><![CDATA[远程连接]]></category>
		<category><![CDATA[限制]]></category>

		<guid isPermaLink="false">http://www.mzfeng.com/?p=333</guid>
		<description><![CDATA[windows2003 server远程终端连接有2个连接数的限制，如果用户登陆后未注销或有超过2人同时登陆时会出现终端超过最大连接数的提示。
解决方法：
1、如果能telnet登录的话，telnet上去，然后执行query user命令，使用logoff命令注销相关用户。(一般都很难telenet上去，至少我连不上)
2、没有telnet的，如果服务器安装了sqlserver，使用sqlserver的xp_cmdshell语句执行cmd命令，xp_cmdshell &#8216;query user&#8217;;xp_cmdshell &#8216;logoff #管道id&#8217;。
3、如果mstsc的版本是5的话，可以运行 &#8216;mstsc -console&#8217; 来连接到服务器的终端，不受远程连接数的影响。适于于 XP SP2。 
4、如果mstsc的版本是6的话，可以运行 &#8216;mstsc -admin&#8217; 来连接到服务器的终端。适于于Vista SP1, Server 2008, XP SP3。
5、运行 mstsc /v:IP /console 就可以连接到远程系统的的0会话, mstsc 还有很多参数 可以运行 mstsc /?来查看. 适用于xp。
6、运行“tsmmc.msc”就可以打开远程桌面连接,在这里我们添加一个新的连接,输入对方的IP地址帐号和密码后就可以成功登陆到对方的桌面中,这时可以再踢下一个用户.适用于windows2003。
7、 通过设置解决，输入“gpedit.msc”，回车后打开组策略窗口，然后依次定位到“计算机配置→管理模板→终端服务→会话”，然后在右侧窗口中双击“为断开的会话设置时间限制”，在打开的窗口中将“结束断开连接的会话”时间设置为5分钟
好了，问题解决了，继续工作，有和我一样问题的朋友快去试试吧~~~
]]></description>
			<content:encoded><![CDATA[<p>windows2003 server远程终端连接有2个连接数的<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/%e9%99%90%e5%88%b6" title="查看 限制 的全部文章" target="_blank">限制</a></span>，如果用户登陆后未注销或有超过2人同时登陆时会出现终端超过最大连接数的提示。<br />
解决方法：<br />
1、如果能telnet登录的话，telnet上去，然后执行query user命令，使用logoff命令注销相关用户。(一般都很难telenet上去，至少我连不上)<br />
2、没有telnet的，如果服务器安装了sqlserver，使用sqlserver的xp_cmdshell语句执行cmd命令，xp_cmdshell &#8216;query user&#8217;;xp_cmdshell &#8216;logoff #管道id&#8217;。<br />
3、如果mstsc的版本是5的话，可以运行 &#8216;mstsc -console&#8217; 来连接到服务器的终端，不受<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/%e8%bf%9c%e7%a8%8b%e8%bf%9e%e6%8e%a5" title="查看 远程连接 的全部文章" target="_blank">远程连接</a></span>数的影响。适于于 XP SP2。 <br />
4、如果mstsc的版本是6的话，可以运行 &#8216;mstsc -admin&#8217; 来连接到服务器的终端。适于于Vista SP1, Server 2008, XP SP3。<span id="more-333"></span><br />
5、运行 mstsc /v:IP /console 就可以连接到远程系统的的0会话, mstsc 还有很多参数 可以运行 mstsc /?来查看. 适用于xp。<br />
6、运行“tsmmc.msc”就可以打开远程桌面连接,在这里我们添加一个新的连接,输入对方的IP地址帐号和密码后就可以成功登陆到对方的桌面中,这时可以再踢下一个用户.适用于windows2003。<br />
7、 通过设置解决，输入“gpedit.msc”，回车后打开组策略窗口，然后依次定位到“计算机配置→管理模板→终端服务→会话”，然后在右侧窗口中双击“为断开的会话设置时间<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/%e9%99%90%e5%88%b6" title="查看 限制 的全部文章" target="_blank">限制</a></span>”，在打开的窗口中将“结束断开连接的会话”时间设置为5分钟<br />
好了，问题解决了，继续工作，有和我一样问题的朋友快去试试吧~~~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mzfeng.com/html/y2010/333.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>常用SQL语句大全</title>
		<link>http://www.mzfeng.com/html/y2010/332.html</link>
		<comments>http://www.mzfeng.com/html/y2010/332.html#comments</comments>
		<pubDate>Fri, 20 Aug 2010 15:25:41 +0000</pubDate>
		<dc:creator>mzfeng</dc:creator>
				<category><![CDATA[软件应用]]></category>
		<category><![CDATA[SQL语句]]></category>

		<guid isPermaLink="false">http://www.mzfeng.com/?p=332</guid>
		<description><![CDATA[　　SELECT –从数据库表中检索数据行和列
　　INSERT –向数据库表添加新数据行
　　DELETE –从数据库表中删除数据行
　　UPDATE –更新数据库表中的数据
　　–数据定义
　　CREATE TABLE –创建一个数据库表
　　DROP TABLE –从数据库中删除表
　　ALTER TABLE –修改数据库表结构
　　CREATE VIEW –创建一个视图
　　DROP VIEW –从数据库中删除视图
　　CREATE INDEX –为数据库表创建一个索引
　　DROP INDEX –从数据库中删除索引
　　CREATE PROCEDURE –创建一个存储过程
　　DROP PROCEDURE –从数据库中删除存储过程
　　CREATE TRIGGER –创建一个触发器
　　DROP TRIGGER –从数据库中删除触发器
　　CREATE SCHEMA –向数据库添加一个新模式
　　DROP SCHEMA –从数据库中删除一个模式
　　CREATE DOMAIN –创建一个数据值域
　　ALTER DOMAIN –改变域定义
　　DROP DOMAIN –从数据库中删除一个域
　–数据控制
　　GRANT –授予用户访问权限
　　DENY –拒绝用户访问
　　REVOKE –解除用户访问权限
　　–事务控制
　　COMMIT –结束当前事务
　　ROLLBACK –中止当前事务
　　SET TRANSACTION –定义当前事务数据访问特征
　　–程序化SQL
　　DECLARE –为查询设定游标
　　EXPLAN –为查询描述数据访问计划
　　OPEN –检索查询结果打开一个游标
　　FETCH –检索一行查询结果
　　CLOSE –关闭游标
　　PREPARE –为动态执行准备SQL 语句
　　EXECUTE –动态地执行SQL 语句
　　DESCRIBE –描述准备好的查询
　　—局部变量
　　declare @id [...]]]></description>
			<content:encoded><![CDATA[<p>　　SELECT –从数据库表中检索数据行和列</p>
<p>　　INSERT –向数据库表添加新数据行</p>
<p>　　DELETE –从数据库表中删除数据行</p>
<p>　　UPDATE –更新数据库表中的数据</p>
<p>　　–数据定义</p>
<p>　　CREATE TABLE –创建一个数据库表</p>
<p>　　DROP TABLE –从数据库中删除表</p>
<p>　　ALTER TABLE –修改数据库表结构</p>
<p>　　CREATE VIEW –创建一个视图<span id="more-332"></span></p>
<p>　　DROP VIEW –从数据库中删除视图</p>
<p>　　CREATE INDEX –为数据库表创建一个索引</p>
<p>　　DROP INDEX –从数据库中删除索引</p>
<p>　　CREATE PROCEDURE –创建一个存储过程</p>
<p>　　DROP PROCEDURE –从数据库中删除存储过程</p>
<p>　　CREATE TRIGGER –创建一个触发器</p>
<p>　　DROP TRIGGER –从数据库中删除触发器</p>
<p>　　CREATE SCHEMA –向数据库添加一个新模式</p>
<p>　　DROP SCHEMA –从数据库中删除一个模式</p>
<p>　　CREATE DOMAIN –创建一个数据值域</p>
<p>　　ALTER DOMAIN –改变域定义</p>
<p>　　DROP DOMAIN –从数据库中删除一个域</p>
<p>　–数据控制</p>
<p>　　GRANT –授予用户访问权限</p>
<p>　　DENY –拒绝用户访问</p>
<p>　　REVOKE –解除用户访问权限</p>
<p>　　–事务控制</p>
<p>　　COMMIT –结束当前事务</p>
<p>　　ROLLBACK –中止当前事务</p>
<p>　　SET TRANSACTION –定义当前事务数据访问特征</p>
<p>　　–程序化SQL</p>
<p>　　DECLARE –为查询设定游标</p>
<p>　　EXPLAN –为查询描述数据访问计划</p>
<p>　　OPEN –检索查询结果打开一个游标</p>
<p>　　FETCH –检索一行查询结果</p>
<p>　　CLOSE –关闭游标</p>
<p>　　PREPARE –为动态执行准备SQL 语句</p>
<p>　　EXECUTE –动态地执行SQL 语句</p>
<p>　　DESCRIBE –描述准备好的查询</p>
<p>　　—局部变量</p>
<p>　　declare @id char(10)</p>
<p>　　–set @id = ’10010001′</p>
<p>　　select @id = ’10010001′</p>
<p>—全局变量</p>
<p>　　—必须以@@开头</p>
<p>　　–IF ELSE　　</p>
<p>declare @x int @y int @z int<br />
　　select @x = 1 @y = 2 @z=3<br />
　　if @x &gt; @y<br />
　　print ‘x &gt; y’ –打印字符串’x &gt; y’<br />
　　else if @y &gt; @z<br />
　　print ‘y &gt; z’<br />
　　else print ‘z &gt; y’</p>
<p>　　–CASE　　</p>
<p>use pangu<br />
　　update employee<br />
　　set e_wage =<br />
　　case<br />
　　when job_level = ’1’ then e_wage*1.08<br />
　　when job_level = ’2’ then e_wage*1.07<br />
　　when job_level = ’3’ then e_wage*1.06<br />
　　else e_wage*1.05<br />
　　end</p>
<p>　　–WHILE CONTINUE BREAK　　</p>
<p>declare @x int @y int @c int<br />
　　select @x = 1 @y=1<br />
　　while @x &lt; 3<br />
　　begin<br />
　　print @x &#8211;打印变量x 的值<br />
　　while @y &lt; 3<br />
　　begin<br />
　　select @c = 100*@x + @y<br />
　　print @c &#8211;打印变量c 的值<br />
　　select @y = @y + 1<br />
　　end<br />
　　select @x = @x + 1<br />
　　select @y = 1<br />
　　end</p>
<p>&#8211;WAITFOR</p>
<p>　　&#8211;例 等待1 小时2 分零3 秒后才执行SELECT 语句　</p>
<p>waitfor delay ’01:02:03’<br />
　　select * from employee</p>
<p>　　&#8211;例 等到晚上11 点零8 分后才执行SELECT 语句　　</p>
<p>waitfor time ’23:08:00’<br />
　　select * from employee</p>
<p>　　***SELECT***　</p>
<p>select *(列名) from table_name(表名) where column_name operator value<br />
　　ex:(宿主)<br />
　　select * from stock_information where stockid = str(nid)<br />
　　stockname = &#8217;str_name&#8217;<br />
　　stockname like &#8216;% find this %&#8217;<br />
　　stockname like &#8216;[a-zA-Z]%&#8217; &#8212;&#8212;&#8212; ([]指定值的范围)<br />
　　stockname like &#8216;[^F-M]%&#8217; &#8212;&#8212;&#8212; (^排除指定范围)<br />
　　&#8212;&#8212;&#8212; 只能在使用like关键字的where子句中使用通配符)<br />
　　or stockpath = &#8217;stock_path&#8217;<br />
　　or stocknumber &lt; 1000<br />
　　and stockindex = 24<br />
　　not stock*** = &#8216;man&#8217;<br />
　　stocknumber between 20 and 100<br />
　　stocknumber in(10,20,30)<br />
　　order by stockid desc(asc) &#8212;&#8212;&#8212; 排序，desc-降序，asc-升序<br />
　　order by 1,2 &#8212;&#8212;&#8212; by列号<br />
　　stockname = (select stockname from stock_information where stockid = 4)</p>
<p>　　&#8212;&#8212;&#8212; 子查询</p>
<p>　　&#8212;&#8212;&#8212; 除非能确保内层select只返回一个行的值，</p>
<p>　　&#8212;&#8212;&#8212; 否则应在外层where子句中用一个in限定符　</p>
<p>select distinct column_name form table_name &#8212;&#8212;&#8212; distinct指定检索独有的列值，不重复<br />
　　select stocknumber ,stocknumber + 10 = stocknumber + 10 from table_name<br />
　　select stockname , stocknumber = count(*) from table_name group by stockname</p>
<p>　　&#8212;&#8212;&#8212; group by 将表按行分组,指定列中有相同的值　　</p>
<p>having count(*) = 2 &#8212;&#8212;&#8212; having选定指定的组<br />
　　select *<br />
　　from table1, table2<br />
　　where table1.id *= table2.id &#8212;&#8212;&#8211; 左外部连接，table1中有的而table2中没有得以null表示<br />
　　table1.id =* table2.id &#8212;&#8212;&#8211; 右外部连接<br />
　　select stockname from table1<br />
　　union [all] &#8212;&#8211; union合并查询结果集，all-保留重复行<br />
　　select stockname from table2</p>
<p>　***insert***　　</p>
<p>insert into table_name (Stock_name,Stock_number) value (xxx,xxxx)<br />
　　value (select Stockname , Stocknumber from Stock_table2)&#8212;value为select语句</p>
<p>　　***update***　　</p>
<p>update table_name set Stockname = xxx [where Stockid = 3]<br />
　　Stockname = default<br />
　　Stockname = null<br />
　　Stocknumber = Stockname + 4</p>
<p>　　***delete***　　</p>
<p>delete from table_name where Stockid = 3<br />
　　truncate table_name &#8212;&#8212;&#8212;&#8211; 删除表中所有行，仍保持表的完整性<br />
　　drop table table_name &#8212;&#8212;&#8212;&#8212;&#8212; 完全删除表</p>
<p>　　***alter table*** &#8212; 修改数据库表结构　　</p>
<p>alter table database.owner.table_name add column_name char(2) null &#8230;..<br />
　　sp_help table_name &#8212;- 显示表已有特征<br />
　　create table table_name (name char(20), age smallint, lname varchar(30))<br />
　　insert into table_name select &#8230;&#8230;&#8230; &#8212;&#8211; 实现删除列的方法(创建新表)<br />
　　alter table table_name drop constraint Stockname_default &#8212;- 删除Stockname的default约束</p>
<p>　　***function(/*常用函数*/)***</p>
<p>　　&#8212;-统计函数&#8212;-</p>
<p>　　***G &#8211;求平均值</p>
<p>　　COUNT &#8211;统计数目</p>
<p>　　MAX &#8211;求最大值</p>
<p>　　MIN &#8211;求最小值</p>
<p>　　SUM &#8211;求和</p>
<p>　　&#8211;***G　</p>
<p>use pangu<br />
　　select avg(e_wage) as dept_avgWage<br />
　　from employee<br />
　　group by dept_id</p>
<p>&#8211;MAX</p>
<p>　　&#8211;求工资最高的员工姓名</p>
<p>use pangu<br />
　　select e_name<br />
　　from employee<br />
　　where e_wage =<br />
　　(select max(e_wage)<br />
　　from employee)</p>
<p>　　&#8211;STDEV()</p>
<p>　　&#8211;STDEV()函数返回表达式中所有数据的标准差</p>
<p>　　&#8211;STDEVP()</p>
<p>　　&#8211;STDEVP()函数返回总体标准差</p>
<p>　　&#8211;VAR()</p>
<p>　　&#8211;VAR()函数返回表达式中所有值的统计变异数</p>
<p>　　&#8211;VARP()</p>
<p>　　&#8211;VARP()函数返回总体变异数</p>
<p>　　&#8212;-算术函数&#8212;-</p>
<p>　　/***三角函数***/</p>
<p>　　SIN(float_expression) &#8211;返回以弧度表示的角的正弦</p>
<p>　　COS(float_expression) &#8211;返回以弧度表示的角的余弦</p>
<p>　　TAN(float_expression) &#8211;返回以弧度表示的角的正切</p>
<p>　　COT(float_expression) &#8211;返回以弧度表示的角的余切</p>
<p>/***反三角函数***/</p>
<p>　　ASIN(float_expression) &#8211;返回正弦是FLOAT 值的以弧度表示的角</p>
<p>　　ACOS(float_expression) &#8211;返回余弦是FLOAT 值的以弧度表示的角</p>
<p>　　ATAN(float_expression) &#8211;返回正切是FLOAT 值的以弧度表示的角</p>
<p>　　ATAN2(float_expression1,float_expression2)</p>
<p>　　&#8211;返回正切是float_expression1 /float_expres-sion2的以弧度表示的角</p>
<p>　　DEGREES(numeric_expression)</p>
<p>　　&#8211;把弧度转换为角度返回与表达式相同的数据类型可为</p>
<p>　　&#8211;INTEGER/MONEY/REAL/FLOAT 类型</p>
<p>　　RADIANS(numeric_expression) &#8211;把角度转换为弧度返回与表达式相同的数据类型可为</p>
<p>　　&#8211;INTEGER/MONEY/REAL/FLOAT 类型</p>
<p>　　EXP(float_expression) &#8211;返回表达式的指数值</p>
<p>　　LOG(float_expression) &#8211;返回表达式的自然对数值</p>
<p>　　LOG10(float_expression)&#8211;返回表达式的以10 为底的对数值</p>
<p>　　SQRT(float_expression) &#8211;返回表达式的平方根</p>
<p>　　/***取近似值函数***/</p>
<p>　　CEILING(numeric_expression) &#8211;返回&gt;=表达式的最小整数返回的数据类型与表达式相同可为</p>
<p>　　–INTEGER/MONEY/REAL/FLOAT 类型</p>
<p>　　FLOOR(numeric_expression) –返回&lt;=表达式的最小整数返回的数据类型与表达式相同可为</p>
<p>　　&#8211;INTEGER/MONEY/REAL/FLOAT 类型</p>
<p>　　ROUND(numeric_expression) &#8211;返回以integer_expression 为精度的四舍五入值返回的数据</p>
<p>　　&#8211;类型与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型</p>
<p>　　ABS(numeric_expression) &#8211;返回表达式的绝对值返回的数据类型与表达式相同可为</p>
<p>　　&#8211;INTEGER/MONEY/REAL/FLOAT 类型</p>
<p>　　SIGN(numeric_expression) &#8211;测试参数的正负号返回0 零值1 正数或-1 负数返回的数据类型</p>
<p>　　&#8211;与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型</p>
<p>　　PI() &#8211;返回值为π 即3.1415926535897936</p>
<p>　　RAND([integer_expression]) &#8211;用任选的[integer_expression]做种子值得出0-1 间的随机浮点数</p>
<p>&#8212;-字符串函数&#8212;-</p>
<p>　　ASCII() &#8211;函数返回字符表达式最左端字符的ASCII 码值</p>
<p>　　CHAR() &#8211;函数用于将ASCII 码转换为字符</p>
<p>　　&#8211;如果没有输入0 ~ 255 之间的ASCII 码值CHAR 函数会返回一个NULL 值</p>
<p>　　LOWER() &#8211;函数把字符串全部转换为小写</p>
<p>　　UPPER() &#8211;函数把字符串全部转换为大写</p>
<p>　　STR() &#8211;函数把数值型数据转换为字符型数据</p>
<p>　　LTRIM() &#8211;函数把字符串头部的空格去掉</p>
<p>　　RTRIM() &#8211;函数把字符串尾部的空格去掉</p>
<p>　　LEFT(),RIGHT(),SUBSTRING() &#8211;函数返回部分字符串</p>
<p>　　CHARINDEX(),PATINDEX() &#8211;函数返回字符串中某个指定的子串出现的开始位置</p>
<p>　　SOUNDEX() &#8211;函数返回一个四位字符码</p>
<p>　　&#8211;SOUNDEX函数可用来查找声音相似的字符串但SOUNDEX函数对数字和汉字均只返回0 值</p>
<p>　　DIFFERENCE() &#8211;函数返回由SOUNDEX 函数返回的两个字符表达式的值的差异</p>
<p>　　&#8211;0 两个SOUNDEX 函数返回值的第一个字符不同</p>
<p>　　&#8211;1 两个SOUNDEX 函数返回值的第一个字符相同</p>
<p>　　&#8211;2 两个SOUNDEX 函数返回值的第一二个字符相同</p>
<p>　　&#8211;3 两个SOUNDEX 函数返回值的第一二三个字符相同</p>
<p>　　&#8211;4 两个SOUNDEX 函数返回值完全相同</p>
<p>QUOTENAME() &#8211;函数返回被特定字符括起来的字符串　</p>
<p>select quotename(&#8216;abc&#8217;, &#8216;{&#8216;) quotename(&#8216;abc&#8217;)</p>
<p>　　运行结果如下</p>
<p>　　&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-{</p>
<p>　　{abc} [abc]*/</p>
<p>　　REPLICATE() &#8211;函数返回一个重复character_expression 指定次数的字符串</p>
<p>　　以下是引用片段：　</p>
<p>select replicate(&#8216;abc&#8217;, 3) replicate( &#8216;abc&#8217;, -2)</p>
<p>　　运行结果如下</p>
<p>　　&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8211;</p>
<p>　　abcabcabc NULL*/</p>
<p>　　REVERSE() &#8211;函数将指定的字符串的字符排列顺序颠倒</p>
<p>　　REPLACE() &#8211;函数返回被替换了指定子串的字符串</p>
<p>　　/*select replace(&#8216;abc123g&#8217;, &#8216;123&#8242;, &#8216;def&#8217;)</p>
<p>　　运行结果如下</p>
<p>　　&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8211;</p>
<p>　　abcdefg*/</p>
<p>　　SPACE() &#8211;函数返回一个有指定长度的空白字符串</p>
<p>　　STUFF() &#8211;函数用另一子串替换字符串指定位置长度的子串</p>
<p>　&#8212;-数据类型转换函数&#8212;-</p>
<p>　　CAST() 函数语法如下　</p>
<p>CAST() ( AS [ length ])</p>
<p>　　CONVERT() 函数语法如下　</p>
<p>CONVERT() ([ length ], [, style])<br />
　</p>
<p>select cast(100+99 as char) convert(varchar(12), getdate())</p>
<p>　　运行结果如下</p>
<p>　　&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;</p>
<p>　　199 Jan 15 2000</p>
<p>　　&#8212;-日期函数&#8212;-</p>
<p>　　DAY() &#8211;函数返回date_expression 中的日期值</p>
<p>　　MONTH() &#8211;函数返回date_expression 中的月份值</p>
<p>　　YEAR() &#8211;函数返回date_expression 中的年份值</p>
<p>　　DATEADD( , ,)</p>
<p>　　&#8211;函数返回指定日期date 加上指定的额外日期间隔number 产生的新日期</p>
<p>　　DATEDIFF( , ,)</p>
<p>　　&#8211;函数返回两个指定日期在datepart 方面的不同之处</p>
<p>　　DATENAME( , ) &#8211;函数以字符串的形式返回日期的指定部分</p>
<p>　　DATEPART( , ) &#8211;函数以整数值的形式返回日期的指定部分</p>
<p>　　GETDATE() &#8211;函数以DATETIME 的缺省格式返回系统当前的日期和时间</p>
<p>&#8212;-系统函数&#8212;-</p>
<p>　　APP_NAME() &#8211;函数返回当前执行的应用程序的名称</p>
<p>　　COALESCE() &#8211;函数返回众多表达式中第一个非NULL 表达式的值</p>
<p>　　COL_LENGTH(&lt;&#8217;table_name&#8217;&gt;, &lt;&#8217;column_name&#8217;&gt;) –函数返回表中指定字段的长度值</p>
<p>　　COL_NAME(, ) –函数返回表中指定字段的名称即列名</p>
<p>　　DATALENGTH() –函数返回数据表达式的数据的实际长度</p>
<p>　　DB_ID(['database_name']) –函数返回数据库的编号</p>
<p>　　DB_NAME(database_id) –函数返回数据库的名称</p>
<p>　　HOST_ID() –函数返回服务器端计算机的名称</p>
<p>　　HOST_NAME() –函数返回服务器端计算机的名称</p>
<p>　　IDENTITY([, seed increment]) [AS column_name])</p>
<p>　　–IDENTITY() 函数只在SELECT INTO 语句中使用用于插入一个identity column列到新表中　</p>
<p>/*select identity(int, 1, 1) as column_name<br />
　　into newtable<br />
　　from oldtable*/</p>
<p>　　ISDATE() –函数判断所给定的表达式是否为合理日期</p>
<p>　　ISNULL(, ) –函数将表达式中的NULL 值用指定值替换</p>
<p>　　ISNUMERIC() –函数判断所给定的表达式是否为合理的数值</p>
<p>　　NEWID() –函数返回一个UNIQUEIDENTIFIER 类型的数值</p>
<p>　　NULLIF(, )</p>
<p>　　–NULLIF 函数在expression1 与expression2 相等时返回NULL 值若不相等时则返回expression1 的值</p>
<p>　sql中的保留字</p>
<p>　　action add aggregate all</p>
<p>　　alter after and as</p>
<p>　　asc avg avg_row_length auto_increment</p>
<p>　　between bigint bit binary</p>
<p>　　blob bool both by</p>
<p>　　cascade case char character</p>
<p>　　change check checksum column</p>
<p>　　columns comment constraint create</p>
<p>　　cross current_date current_time current_timestamp</p>
<p>　　data database databases date</p>
<p>　　datetime day day_hour day_minute</p>
<p>　　day_second dayofmonth dayofweek dayofyear</p>
<p>　　dec decimal default delayed</p>
<p>　　delay_key_write delete desc describe</p>
<p>　　distinct distinctrow double drop</p>
<p>　　end else escape escaped</p>
<p>　　enclosed enum explain exists</p>
<p>　　fields file first float</p>
<p>　　float4 float8 flush foreign</p>
<p>　　from for full function</p>
<p>　　global grant grants group</p>
<p>　　having heap high_priority hour</p>
<p>　　hour_minute hour_second hosts identified</p>
<p>　　ignore in index infile</p>
<p>　　inner insert insert_id int</p>
<p>　　integer interval int1 int2</p>
<p>　　int3 int4 int8 into</p>
<p>　　if is isam join</p>
<p>　　key keys kill last_insert_id</p>
<p>　　leading left length like</p>
<p>　　lines limit load local</p>
<p>　　lock logs long longblob</p>
<p>　　longtext low_priority max max_rows</p>
<p>　　match mediumblob mediumtext mediumint</p>
<p>　　middleint min_rows minute minute_second</p>
<p>　　modify month monthname myisam</p>
<p>　natural numeric no not</p>
<p>　　null on optimize option</p>
<p>　　optionally or order outer</p>
<p>　　outfile pack_keys partial password</p>
<p>　　precision primary procedure process</p>
<p>　　processlist privileges read real</p>
<p>　　references reload regexp rename</p>
<p>　　replace restrict returns revoke</p>
<p>　　rlike row rows second</p>
<p>　　select set show shutdown</p>
<p>　　smallint soname sql_big_tables sql_big_selects</p>
<p>　　sql_low_priority_updates sql_log_off sql_log_update sql_select_limit</p>
<p>　　sql_small_result sql_big_result sql_warnings straight_join</p>
<p>　　starting status string table</p>
<p>　　tables temporary terminated text</p>
<p>　　then time timestamp tinyblob</p>
<p>　　tinytext tinyint trailing to</p>
<p>　　type use using unique</p>
<p>　　unlock unsigned update usage</p>
<p>　　values varchar variables varying</p>
<p>　　varbinary with write when</p>
<p>　　where year year_month zerofill</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mzfeng.com/html/y2010/332.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mysqld-nt.exe大量占用CPU问题的解决方法</title>
		<link>http://www.mzfeng.com/html/y2010/330.html</link>
		<comments>http://www.mzfeng.com/html/y2010/330.html#comments</comments>
		<pubDate>Sat, 14 Aug 2010 12:08:26 +0000</pubDate>
		<dc:creator>mzfeng</dc:creator>
				<category><![CDATA[软件应用]]></category>
		<category><![CDATA[mysqld]]></category>
		<category><![CDATA[数据表]]></category>

		<guid isPermaLink="false">http://www.mzfeng.com/?p=330</guid>
		<description><![CDATA[早上帮朋友一台服务器解决了 Mysql cpu 占用 100% 的问题，稍整理如下，希望对各位有所帮助。
该主机 (Windows 2003 +  IIS + PHP + MYSQL )近来 MySQL 服务进程 (mysqld-nt.exe) CPU  占用率总为 100% 高居不下。此主机有10个左右的  database, 分别给十个网站调用。据朋友测试，导致 mysqld-nt.exe  cpu 占用奇高的是网站A，一旦在 IIS 中将此网站停止服务，CPU  占用就降下来了。一启用，则马上上升。
MYSQL CPU 占用 100% 的解决过程
今天早上仔细检查了一下。目前此网站的七日平均日 IP 为2000，PageView 为 3万左右。网站A 用的 database  目前有39个表，记录数 60.1万条，占空间 45MB。按这个数据，MySQL 不可能占用这么高的资源。
于是在服务器上运行命令，将 mysql  当前的环境变量输出到文件 output.txt：
d:\web\mysql&#62;mysqld.exe&#8211;help&#62;output.txt
发现 tmp_table_size [...]]]></description>
			<content:encoded><![CDATA[<p>早上帮朋友一台服务器解决了 Mysql cpu 占用 100% 的问题，稍整理如下，希望对各位有所帮助。</p>
<p>该主机 (Windows 2003 +  IIS + PHP + MYSQL )近来 MySQL 服务进程 (<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/mysqld" title="查看 mysqld 的全部文章" target="_blank">mysqld</a></span>-nt.exe) CPU  占用率总为 100% 高居不下。此主机有10个左右的  database, 分别给十个网站调用。据朋友测试，导致 <span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/mysqld" title="查看 mysqld 的全部文章" target="_blank">mysqld</a></span>-nt.exe  cpu 占用奇高的是网站A，一旦在 IIS 中将此网站停止服务，CPU  占用就降下来了。一启用，则马上上升。</p>
<p>MYSQL CPU 占用 100% 的解决过程</p>
<p>今天早上仔细检查了一下。目前此网站的七日平均日 IP 为2000，PageView 为 3万左右。网站A 用的 database  目前有39个表，记录数 60.1万条，占空间 45MB。按这个数据，MySQL 不可能占用这么高的资源。</p>
<p>于是在服务器上运行命令，将 mysql  当前的环境变量输出到文件 output.txt：</p>
<p>d:\web\mysql&gt;<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/mysqld" title="查看 mysqld 的全部文章" target="_blank">mysqld</a></span>.exe&#8211;help&gt;output.txt</p>
<p>发现 tmp_table_size 的值是默认的 32M，于是修改 My.ini, 将 tmp_table_size 赋值到 200M:</p>
<p>d:\web\mysql&gt;notepad c:\windows\my.ini[mysqld]tmp_table_size=200M</p>
<p>然后重启 MySQL 服务。CPU 占用有轻微下降，以前的CPU 占用波形图是 100% 一根直线，现在则在  97%~100%之间起伏。这表明调整 tmp_table_size 参数对 MYSQL 性能提升有改善作用。但问题还没有完全解决。</p>
<p><span id="more-330"></span></p>
<p>于是进入  mysql 的 shell 命令行，调用 show processlist, 查看当前 mysql 使用频繁的 sql 语句：</p>
<p>mysql&gt;show processlist;</p>
<p>反复调用此命令(每秒刷两次），发现网站 A 的两个 SQL  语句经常在 process list 中出现，其语法如下：</p>
<p>SELECT  t1.pid, t2.userid, t3.count,  t1.date FROM _mydata AS t1LEFT JOIN  _myuser AS t3 ON t1.userid=t3.useridLEFT  JOIN _mydata_body AS t2 ON  t1.pid=t3.pid ORDER BY t1.pid LIMIT0,15</p>
<p>调用 show columns 检查这三个表的结构 :</p>
<p>mysql&gt;show columns from  _myuser;mysql&gt;show columns from _mydata;mysql&gt;show columns from  _mydata_body;</p>
<p>终于发现了问题所在：_mydata 表，只根据 pid 建立了一个 primary key，但并没有为  userid 建立索引。而在这个 SQL 语句的第一个 LEFT JOIN ON 子句中：</p>
<p>LEFT JOIN _myuser AS t3 ON  t1.userid=t3.userid</p>
<p>_mydata 的 userid 被参与了条件比较运算。于是我为给 _mydata 表根据字段  userid 建立了一个索引：</p>
<p>mysql&gt;ALTER TABLE `_mydata` ADD INDEX ( `userid` )</p>
<p>建立此索引之后，CPU 马上降到了 80% 左右。看到找到了问题所在，于是检查另一个反复出现在 show processlist 中的  sql 语句：</p>
<p>SELECT COUNT(*)FROM _mydata AS t1, _mydata_key AS t2WHERE  t1.pid=t2.pid and t2.keywords=<br />
&#8216;孔雀&#8217;</p>
<p>经 检查 _mydata_key 表的结构，发现它只为  pid 建了了 primary key, 没有为 keywords 建立  index。_mydata_key 目前有 33  万条记录，在没有索引的情况下对33万条记录进行文本检索匹配，不耗费大量的 cpu  时间才怪。看来就是针对这个表的检索出问题了。于是同样为 _mydata_key  表根据字段 keywords 加上索引:</p>
<p>mysql&gt;ALTER TABLE `_mydata_key` ADD INDEX (  `keywords` )</p>
<p>建立此索引之后，CPU立刻降了下来，在 50%~70%之间震荡。</p>
<p>再次调用 show  prosslist，网站A 的sql 调用就很少出现在结果列表中了。但发现此主机运行了几个 Discuz 的论坛程序，  Discuz论坛的好几个表也存在着这个问题。于是顺手一并解决，cpu占用再次降下来了。</p>
<p>至此，问题解决。<br />
1.  增加  tmp_table_size 值。mysql 的配置文件中，tmp_table_size 的默认大小是  32M。如果一张临时表超出该大小，MySQL产生一个  The table tbl_name is full 形式的错误，如果你做很多高级  GROUP BY 查询，增加 tmp_table_size 值。 这是  mysql 官方关于此选项的解释：</p>
<p>tmp_table_size<br />
This  variable determines the  maximum size for a temporary table in memory.  If the table becomes too large, a  MYISAM table is created on disk. Try  to avoid temporary tables by optimizing the  queries where possible, but  where this is not possible, try to ensure temporary  tables are always  stored in memory. Watching the processlist for queries with  temporary  tables that take too long to resolve can give you an early warning  that  tmp_table_size needs to be upped. Be aware that memory is also  allocated  per-thread. An example where upping this worked for more was a  server where I  upped this from 32MB (the default) to 64MB with  immediate effect. The quicker  resolution of queries resulted in less  threads being active at any one time,  with all-round benefits for the  server, and available memory.</p>
<p>2. 对  WHERE, JOIN, MAX(), MIN(), ORDER BY 等子句中的条件判断中用到的字段,应该根据其建立索引 INDEX。</p>
<p>索 引被用来快速找出在一个列上用一特定值的行。没有索引，MySQL不得不首先以第一条记录开始并然后读完整个表直到它找出相关的行。表越大，花费时间越 多。如果表对于查询的列有一个索引，MySQL能快速到达一个位置去搜寻到数据文件的中间，没有必要考虑所有数据。如果一个表有1000行，这比顺序读取 至少快100倍。所有的MySQL索引(PRIMARY、UNIQUE和INDEX)在B树中存储。</p>
<p>根据 mysql 的开发文档:</p>
<p>索引 index 用于：</p>
<p>o 快速找出匹配一个WHERE子句的行<br />
o  当执行联结(JOIN)时，从其他表检索行。<br />
o 对特定的索引列找出MAX()或MIN()值<br />
o  如果排序或分组在一个可用键的最左面前缀上进行(例如，ORDER BY  key_part_1,key_part_2)，排序或分组一个表。如果所有键值部分跟随DESC，键以倒序被读取。<br />
o  在一些情况中，一个查询能被优化来检索值，不用咨询数据文件。如果对某些表的所有使用的列是数字型的并且构成某些键的最左面前缀，为了更快，值可以从索引树被检索出来。</p>
<p>假定你发出下列SELECT语句：</p>
<p>mysql&gt;SELECT*FROM tbl_name WHERE col1=val1  AND col2=val2;</p>
<p>如果一个多列索引存在于col1和col2上，适当的行可以直接被取出。如果分开的单行列索引存在于col1和col2上，优化器试图通过决定哪个索引将找到更少的行并来找出更具限制性的索引并且使用该索引取行。</p>
<p>开发人员做 SQL <span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/%e6%95%b0%e6%8d%ae%e8%a1%a8" title="查看 数据表 的全部文章" target="_blank">数据表</a></span>设计的时候，一定要通盘考虑清楚。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mzfeng.com/html/y2010/330.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux主机使用DenyHosts阻止SSH暴力攻击</title>
		<link>http://www.mzfeng.com/html/y2010/329.html</link>
		<comments>http://www.mzfeng.com/html/y2010/329.html#comments</comments>
		<pubDate>Sun, 01 Aug 2010 00:41:11 +0000</pubDate>
		<dc:creator>mzfeng</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[DenyHosts]]></category>

		<guid isPermaLink="false">http://www.mzfeng.com/?p=329</guid>
		<description><![CDATA[现今很多朋友都在用国外的VPS，国外由于LINUX是免费开源，相比微软的高额的Windows费用，Linux就有很大的优势。从而有很多朋友都采用LINUX来做系统 ；但是网上有很多无聊的人经常在扫描SSH端口,试图连接ssh端口进行暴力破解（穷举扫描），所以建议vps主机的空间,尽量设置复杂的ssh登录密码，还有就是可以使用denyhosts这款软件，它会分析/var/log/secure（redhat，Fedora Core）等日志文件，当发现同一IP在进行多次SSH密码尝试时就会记录IP到/etc/hosts.deny文件，从而达到自动屏蔽该IP的目的。
DenyHosts官方网站为：http://denyhosts.sourceforge.net/
1、下载DenyHosts 并解压
# wget http://soft.vpser.net/security/denyhosts/DenyHosts-2.6.tar.gz
# tar zxvf DenyHosts-2.6.tar.gz
# cd DenyHosts-2.6
2、安装、配置和启动
# python setup.py install
默认是安装到/usr/share/denyhosts/目录的,进入相应的目录修改配置文件
# cd /usr/share/denyhosts/
# cp denyhosts.cfg-dist denyhosts.cfg
# cp daemon-control-dist daemon-control
默认的设置已经可以适合centos系统环境，你们可以使用vi命令查看一下denyhosts.cfg和daemon-control，里面有详细的解释
接着使用下面命令启动denyhosts程序
# chown root daemon-control
# chmod 700 daemon-control
# ./daemon-control start
如果要使DenyHosts每次重起后自动启动还需做如下设置：
# cd /etc/init.d
# ln -s /usr/share/denyhosts/daemon-control denyhosts
# chkconfig &#8211;add denyhosts
# chkconfig &#8211;level 2345 denyhosts on
或者执行下面的命令，将会修改/etc/rc.local文件：
# echo &#8220;/usr/share/denyhosts/daemon-control start&#8221; &#62;&#62; /etc/rc.local
DenyHosts配置文件denyhosts.cfg说明：
SECURE_LOG = /var/log/secure
#sshd日志文件，它是根据这个文件来判断的，不同的操作系统，文件名稍有不同。
HOSTS_DENY = /etc/hosts.deny
#控制用户登陆的文件
PURGE_DENY = 5m
#过多久后清除已经禁止的
BLOCK_SERVICE [...]]]></description>
			<content:encoded><![CDATA[<p>现今很多朋友都在用国外的VPS，国外由于LINUX是免费开源，相比微软的高额的Windows费用，<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/linux" title="查看 Linux 的全部文章" target="_blank">Linux</a></span>就有很大的优势。从而有很多朋友都采用LINUX来做系统 ；但是网上有很多无聊的人经常在扫描SSH端口,试图连接ssh端口进行暴力破解（穷举扫描），所以建议vps主机的空间,尽量设置复杂的ssh登录密码，还有就是可以使用denyhosts这款软件，它会分析/var/log/secure（redhat，Fedora Core）等日志文件，当发现同一IP在进行多次SSH密码尝试时就会记录IP到/etc/hosts.deny文件，从而达到自动屏蔽该IP的目的。</p>
<p><span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/denyhosts" title="查看 DenyHosts 的全部文章" target="_blank">DenyHosts</a></span>官方网站为：http://denyhosts.sourceforge.net/</p>
<p>1、下载<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/denyhosts" title="查看 DenyHosts 的全部文章" target="_blank">DenyHosts</a></span> 并解压</p>
<p># wget http://soft.vpser.net/security/denyhosts/DenyHosts-2.6.tar.gz<br />
# tar zxvf DenyHosts-2.6.tar.gz<br />
# cd DenyHosts-2.6</p>
<p>2、安装、配置和启动</p>
<p># python setup.py install<br />
默认是安装到/usr/share/denyhosts/目录的,进入相应的目录修改配置文件</p>
<p># cd /usr/share/denyhosts/<br />
# cp denyhosts.cfg-dist denyhosts.cfg<br />
# cp daemon-control-dist daemon-control</p>
<p>默认的设置已经可以适合centos系统环境，你们可以使用vi命令查看一下denyhosts.cfg和daemon-control，里面有详细的解释<br />
接着使用下面命令启动denyhosts程序<br />
# chown root daemon-control<br />
# chmod 700 daemon-control<br />
# ./daemon-control start</p>
<p>如果要使DenyHosts每次重起后自动启动还需做如下设置：<br />
# cd /etc/init.d<br />
# ln -s /usr/share/denyhosts/daemon-control denyhosts<br />
# chkconfig &#8211;add denyhosts<br />
# chkconfig &#8211;level 2345 denyhosts on<br />
或者执行下面的命令，将会修改/etc/rc.local文件：<br />
# echo &#8220;/usr/share/denyhosts/daemon-control start&#8221; &gt;&gt; /etc/rc.local</p>
<p>DenyHosts配置文件denyhosts.cfg说明：</p>
<p>SECURE_LOG = /var/log/secure</p>
<p>#sshd日志文件，它是根据这个文件来判断的，不同的操作系统，文件名稍有不同。</p>
<p>HOSTS_DENY = /etc/hosts.deny</p>
<p>#控制用户登陆的文件</p>
<p>PURGE_DENY = 5m</p>
<p>#过多久后清除已经禁止的</p>
<p>BLOCK_SERVICE = sshd</p>
<p>#禁止的服务名</p>
<p>DENY_THRESHOLD_INVALID = 1</p>
<p>#允许无效用户失败的次数</p>
<p>DENY_THRESHOLD_VALID = 10</p>
<p>#允许普通用户登陆失败的次数</p>
<p>DENY_THRESHOLD_ROOT = 5</p>
<p>#允许root登陆失败的次数</p>
<p>HOSTNAME_LOOKUP=NO</p>
<p>#是否做域名反解</p>
<p>DAEMON_LOG = /var/log/denyhosts</p>
<p>更多的说明请查看自带的README文本文件，好了以后维护VPS就会省一些心了，但是各位朋友们注意了安全都是相对的哦，没有绝对安全，请定期或不定期的检查你的VPS主机，而且要定时备份你的数据哦。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mzfeng.com/html/y2010/329.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一封程序员的爱情表白书</title>
		<link>http://www.mzfeng.com/html/y2010/327.html</link>
		<comments>http://www.mzfeng.com/html/y2010/327.html#comments</comments>
		<pubDate>Mon, 14 Jun 2010 01:50:41 +0000</pubDate>
		<dc:creator>mzfeng</dc:creator>
				<category><![CDATA[互联网]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[表白书]]></category>

		<guid isPermaLink="false">http://www.mzfeng.com/?p=327</guid>
		<description><![CDATA[原文出处：http://www.1985y.com.cn/188.html
我能抽象出整个世界．．．
但是我不能抽象出你．．．
因为你在我心中是那么的具体．．．
所以我的世界并不完整．．．
我可以重载甚至覆盖这个世界里的任何一种方法．．．
但是我却不能重载对你的思念．．．
也许命中注定了 你在我的世界里永远的烙上了静态的属性．．．
而我不慎调用了爱你这个方法．．．
当我义无返顾的把自己作为参数传进这个方法时．．．
我才发现爱上你是一个死循环．．．
它不停的返回对你的思念压入我心里的堆栈．．．
在这无尽的黑夜中．．．
我的内存里已经再也装不下别人．．．
我不停的向系统申请空间．．．
但却捕获一个异常－－－我爱的人不爱我．．．
为了解决这个异常．．．
我愿意虚拟出最后一点内存．．．
把所有我能实现的方法地址压入堆栈．．．
并且在栈尾压入最后一个方法－－－将字符串＂我爱你，你爱我吗？＂传递给你．．．
如果返回值为真－－我将用尽一生去爱你．．．
否则－－我将释放掉所有系资源．
]]></description>
			<content:encoded><![CDATA[<p>原文出处：http://www.1985y.com.cn/188.html</p>
<p>我能抽象出整个世界．．．<br />
但是我不能抽象出你．．．<br />
因为你在我心中是那么的具体．．．<br />
所以我的世界并不完整．．．<br />
我可以重载甚至覆盖这个世界里的任何一种方法．．．<br />
但是我却不能重载对你的思念．．．<br />
也许命中注定了 你在我的世界里永远的烙上了静态的属性．．．<br />
而我不慎调用了爱你这个方法．．．<br />
当我义无返顾的把自己作为参数传进这个方法时．．．<span id="more-327"></span><br />
我才发现爱上你是一个死循环．．．<br />
它不停的返回对你的思念压入我心里的堆栈．．．<br />
在这无尽的黑夜中．．．<br />
我的内存里已经再也装不下别人．．．<br />
我不停的向系统申请空间．．．<br />
但却捕获一个异常－－－我爱的人不爱我．．．<br />
为了解决这个异常．．．<br />
我愿意虚拟出最后一点内存．．．<br />
把所有我能实现的方法地址压入堆栈．．．<br />
并且在栈尾压入最后一个方法－－－将字符串＂我爱你，你爱我吗？＂传递给你．．．<br />
如果返回值为真－－我将用尽一生去爱你．．．<br />
否则－－我将释放掉所有系资源．</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mzfeng.com/html/y2010/327.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Linux性能监控之Network篇</title>
		<link>http://www.mzfeng.com/html/y2010/325.html</link>
		<comments>http://www.mzfeng.com/html/y2010/325.html#comments</comments>
		<pubDate>Sun, 30 May 2010 17:14:45 +0000</pubDate>
		<dc:creator>mzfeng</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Network]]></category>
		<category><![CDATA[性能监控]]></category>

		<guid isPermaLink="false">http://www.mzfeng.com/?p=325</guid>
		<description><![CDATA[日常应用中，影响网络的因素有很多这些因素包括，延迟、冲突、阻塞等等。 接下来让我们了解Linux性能监控之下Network的具体情况，希望在关于Linux性能监控这方面对大家有更多的帮助。
大部分的以太网络都是自适应速度的，因为一个网络中可能有不同的网络设备采用不同的速率和工作模式（全双工或半双工）。大部分企业网络都工作在100到1000BaseTX。ethtool命令可以设置网卡的工作速率和模式。
# ethtool eth0
Settings for eth0:
Supported ports: [ TP MII ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
Advertised auto-negotiation: Yes
Speed: 10Mb/s
Duplex: Half
Port: MII
PHYAD: 32
Transceiver: internal
Auto-negotiation: on
Supports Wake-on: pumbg
Wake-on: d
Current message level: 0&#215;00000007 (7)
Link detected: yes
Linux性能监控我们可以看到网卡工作在10Mb/s，模式为半双工，并且打开了自适应开关。我们通过下列命令强制设置网卡工作在100Mb/s全双工模式，并关闭自适应功能。
# ethtool -s eth0 speed 100 duplex full autoneg off
再次运行ethtool显示如下：
# ethtool eth0
Settings for eth0:
Supported ports: [ [...]]]></description>
			<content:encoded><![CDATA[<p>日常应用中，影响网络的因素有很多这些因素包括，延迟、冲突、阻塞等等。 接下来让我们了解<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/linux" title="查看 Linux 的全部文章" target="_blank">Linux</a></span><span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/%e6%80%a7%e8%83%bd%e7%9b%91%e6%8e%a7" title="查看 性能监控 的全部文章" target="_blank">性能监控</a></span>之下<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/network" title="查看 Network 的全部文章" target="_blank">Network</a></span>的具体情况，希望在关于<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/linux" title="查看 Linux 的全部文章" target="_blank">Linux</a></span><span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/%e6%80%a7%e8%83%bd%e7%9b%91%e6%8e%a7" title="查看 性能监控 的全部文章" target="_blank">性能监控</a></span>这方面对大家有更多的帮助。<br />
大部分的以太网络都是自适应速度的，因为一个网络中可能有不同的网络设备采用不同的速率和工作模式（全双工或半双工）。大部分企业网络都工作在100到1000BaseTX。ethtool命令可以设置网卡的工作速率和模式。<br />
# ethtool eth0<br />
Settings for eth0:<br />
Supported ports: [ TP MII ]<br />
Supported link modes: 10baseT/Half 10baseT/Full<br />
100baseT/Half 100baseT/Full<br />
Supports auto-negotiation: Yes<br />
Advertised link modes: 10baseT/Half 10baseT/Full<br />
100baseT/Half 100baseT/Full<br />
Advertised auto-negotiation: Yes<br />
Speed: 10Mb/s<span id="more-325"></span><br />
Duplex: Half<br />
Port: MII<br />
PHYAD: 32<br />
Transceiver: internal<br />
Auto-negotiation: on<br />
Supports Wake-on: pumbg<br />
Wake-on: d<br />
Current message level: 0&#215;00000007 (7)<br />
Link detected: yes</p>
<p><span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/linux" title="查看 Linux 的全部文章" target="_blank">Linux</a></span>性能监控我们可以看到网卡工作在10Mb/s，模式为半双工，并且打开了自适应开关。我们通过下列命令强制设置网卡工作在100Mb/s全双工模式，并关闭自适应功能。<br />
# ethtool -s eth0 speed 100 duplex full autoneg off</p>
<p>再次运行ethtool显示如下：<br />
# ethtool eth0<br />
Settings for eth0:<br />
Supported ports: [ TP MII ]<br />
Supported link modes: 10baseT/Half 10baseT/Full<br />
100baseT/Half 100baseT/Full<br />
Supports auto-negotiation: Yes<br />
Advertised link modes: 10baseT/Half 10baseT/Full<br />
100baseT/Half 100baseT/Full<br />
Advertised auto-negotiation: No<br />
Speed: 100Mb/s<br />
Duplex: Full<br />
Port: MII<br />
PHYAD: 32<br />
Transceiver: internal<br />
Auto-negotiation: off<br />
Supports Wake-on: pumbg<br />
Wake-on: d<br />
Current message level: 0&#215;00000007 (7)<br />
Link detected: yes</p>
<p>用iptraf工具可以清楚的看到每个网卡的工作情况。<br />
# iptraf –d eth0</p>
<p><a href="http://www.51testing.com/batch.download.php?aid=7928" target="_blank"><img title="Linux性能监控 - hljwxdn - hljwxdn的博客" src="http://images.51cto.com/files/uploadimg/20100526/1850280.jpg" border="0" alt="Linux性能监控 - hljwxdn - hljwxdn的博客" /></a></p>
<p>利用iptraf还可以监听固定TCP端口的流量，如对于Web服务器我们希望监听80端口的流量，对于邮件服务器我们关注25端口的流量。</p>
<p><a href="http://www.51testing.com/batch.download.php?aid=7929" target="_blank"><img title="Linux性能监控 - hljwxdn - hljwxdn的博客" src="http://images.51cto.com/files/uploadimg/20100526/1850281.jpg" border="0" alt="Linux性能监控 - hljwxdn - hljwxdn的博客" /></a>   </p>
<p>网络中最常见的错误就是冲突，由于网络中目前基本采用交换机环境，因此冲突问题已被消除。但是当网络流量不断增大的时候，就会出现丢包，网卡过载等情况。在网络流量很大的时候我们用sar命令来给出网络中可能的错误:<br />
# sar -n FULL 5 100<br />
Linux 2.6.9-55.ELsmp (sapulpa) 06/23/2007<br />
11:44:32 AM IFACE rxpck/s txpck/s rxbyt/s txbyt/s rxcmp/s txcmp/s rxmcst/s<br />
11:44:37 AM lo 6.00 6.00 424.40 424.40 0.00 0.00 0.00<br />
11:44:37 AM eth0 0.00 0.00 0.00 0.00 0.00 0.00 0.00<br />
11:44:37 AM sit0 0.00 0.00 0.00 0.00 0.00 0.00 0.00<br />
11:44:32 AM IFACE rxerr/s txerr/s coll/s rxdrop/s txdrop/s txcarr/s rxfram/s rxfifo/s txfifo/s<br />
11:44:37 AM lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00<br />
11:44:37 AM eth0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00<br />
11:44:37 AM sit0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00<br />
11:44:32 AM totsck tcpsck udpsck rawsck ip-frag<br />
11:44:37 AM 297 79 8 0 0</p>
<p>rxerr/s是接受错误率；txerr/s是发送错误率；coll/s冲突率；rxdrop/s接受帧丢失率；txdrop/s发送帧丢失率； txcarr/s载波错误率；rxfram/s帧排列错误；rxfifo/s接受FIFO错误；txfifo/s发送FIFO错误。从上面输出看出各种错 误为零，证明网络工作良好。</p>
<p>Linux性能监控总的来说监视网络性能，我们有遵循一下几点：</p>
<p>1. 检查所有网络接口确保他们都运行在正确的速率；</p>
<p>2. 检查每块网卡的吞吐量确保没有造成过载；</p>
<p>3. 检查流量的类型确保正确的数据流在传送。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mzfeng.com/html/y2010/325.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Linux查看性能的命令之——top命令介绍</title>
		<link>http://www.mzfeng.com/html/y2010/324.html</link>
		<comments>http://www.mzfeng.com/html/y2010/324.html#comments</comments>
		<pubDate>Sat, 29 May 2010 15:53:58 +0000</pubDate>
		<dc:creator>mzfeng</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[top]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.mzfeng.com/?p=324</guid>
		<description><![CDATA[Linux系统运行维护的过程中，随时可能有需要查看 CPU 和内存使用率，并根据相应信息分析系统状况的需要。在 CentOS 中，可以通过 top 命令来查看 CPU 使用状况。运行 top 命令后，CPU 使用状态会以全屏的方式显示，并且会处在对话的模式 &#8212; 用基于 top 的命令，可以控制显示方式等等。退出 top 的命令为 q ，以下就让我们看看相关的命令。
Linux 查看性能操作实例:
在命令行中输入 “top”
即可启动 top
top 的全屏对话模式可分为3部分：系统信息栏、命令输入栏、进程列表栏。
第一部分 &#8212; 最上部的 系统信息栏 ：
第一行（top）：
“00:11:04”为系统当前时刻；
“3:35”为系统启动后到现在的运作时间；
“2 users”为当前登录到系统的用户，更确切的说是登录到用户的终端数 &#8212; 同一个用户同一时间对系统多个终端的连接将被视为多个用户连接到系统，这里的用户数也将表现
为终端的数目；
“load average”为当前系统负载的平均值，后面的三个值分别为1分钟前、5分钟前、15分钟前进程的平均数，一般的可以认为这个数值超过 CPU 数目时，CPU 将比较吃力的负
载当前系统所包含的进程；
第二行（Tasks）：
“59 total”为当前系统进程总数；
“1 running”为当前运行中的进程数；
“58 sleeping”为当前处于等待状态中的进程数；
“0 stoped”为被停止的系统进程数；
“0 zombie”为被复原的进程数；
第三行（Cpus）：
分别表示了 CPU 当前的使用率；
第四行（Mem）：
分别表示了内存总量、当前使用量、空闲内存量、以及缓冲使用中的内存量；
第五行（Swap）：
表示类别同第四行（Mem），但此处反映着交换分区（Swap）的使用情况。通常，交换分区（Swap）被频繁使用的情况，将被视作物理内存不足而造成的。
第二部分 &#8212; 中间部分的内部命令提示栏：
Linux 查看性能top 运行中可以通过 top 的内部命令对进程的显示方式进行控制。内部命令如下表：
-Linux 查看性能 改变画面更新频率
l &#8211; 关闭或开启第一部分第一行 top 信息的表示
t &#8211; 关闭或开启第一部分第二行 [...]]]></description>
			<content:encoded><![CDATA[<p><span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/linux" title="查看 Linux 的全部文章" target="_blank">Linux</a></span>系统运行维护的过程中，随时可能有需要查看 CPU 和内存使用率，并根据相应信息分析系统状况的需要。在 CentOS 中，可以通过 <span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/top" title="查看 top 的全部文章" target="_blank">top</a></span> <span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/%e5%91%bd%e4%bb%a4" title="查看 命令 的全部文章" target="_blank">命令</a></span>来查看 CPU 使用状况。运行 <span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/top" title="查看 top 的全部文章" target="_blank">top</a></span> <span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/%e5%91%bd%e4%bb%a4" title="查看 命令 的全部文章" target="_blank">命令</a></span>后，CPU 使用状态会以全屏的方式显示，并且会处在对话的模式 &#8212; 用基于 top 的<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/%e5%91%bd%e4%bb%a4" title="查看 命令 的全部文章" target="_blank">命令</a></span>，可以控制显示方式等等。退出 top 的命令为 q ，以下就让我们看看相关的命令。</p>
<p><span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/linux" title="查看 Linux 的全部文章" target="_blank">Linux</a></span> 查看性能操作实例:<br />
在命令行中输入 “top”<br />
即可启动 top<br />
top 的全屏对话模式可分为3部分：系统信息栏、命令输入栏、进程列表栏。</p>
<p>第一部分 &#8212; 最上部的 系统信息栏 ：</p>
<p><span id="more-324"></span>第一行（top）：<br />
“00:11:04”为系统当前时刻；<br />
“3:35”为系统启动后到现在的运作时间；<br />
“2 users”为当前登录到系统的用户，更确切的说是登录到用户的终端数 &#8212; 同一个用户同一时间对系统多个终端的连接将被视为多个用户连接到系统，这里的用户数也将表现</p>
<p>为终端的数目；<br />
“load average”为当前系统负载的平均值，后面的三个值分别为1分钟前、5分钟前、15分钟前进程的平均数，一般的可以认为这个数值超过 CPU 数目时，CPU 将比较吃力的负</p>
<p>载当前系统所包含的进程；</p>
<p>第二行（Tasks）：<br />
“59 total”为当前系统进程总数；<br />
“1 running”为当前运行中的进程数；<br />
“58 sleeping”为当前处于等待状态中的进程数；<br />
“0 stoped”为被停止的系统进程数；<br />
“0 zombie”为被复原的进程数；</p>
<p>第三行（Cpus）：<br />
分别表示了 CPU 当前的使用率；</p>
<p>第四行（Mem）：<br />
分别表示了内存总量、当前使用量、空闲内存量、以及缓冲使用中的内存量；</p>
<p>第五行（Swap）：<br />
表示类别同第四行（Mem），但此处反映着交换分区（Swap）的使用情况。通常，交换分区（Swap）被频繁使用的情况，将被视作物理内存不足而造成的。</p>
<p>第二部分 &#8212; 中间部分的内部命令提示栏：</p>
<p>Linux 查看性能top 运行中可以通过 top 的内部命令对进程的显示方式进行控制。内部命令如下表：</p>
<p>-Linux 查看性能 改变画面更新频率<br />
l &#8211; 关闭或开启第一部分第一行 top 信息的表示<br />
t &#8211; 关闭或开启第一部分第二行 Tasks 和第三行 Cpus 信息的表示<br />
m &#8211; 关闭或开启第一部分第四行 Mem 和 第五行 Swap 信息的表示<br />
N &#8211; 以 PID 的大小的顺序排列表示进程列表（第三部分后述）<br />
P &#8211; 以 CPU 占用率大小的顺序排列进程列表 （第三部分后述）<br />
M &#8211; 以内存占用率大小的顺序排列进程列表 （第三部分后述）<br />
h &#8211; 显示帮助<br />
n &#8211; 设置在进程列表所显示进程的数量<br />
q &#8211; 退出 top<br />
s -</p>
<p>Linux 查看性能改变画面更新周期</p>
<p>第三部分 &#8212; 最下部分的进程列表栏：</p>
<p>以 PID 区分的进程列表将根据所设定的画面更新时间定期的更新。Linux 查看性能通过 top 内部命令可以控制此处的显示方式。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mzfeng.com/html/y2010/324.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>免费的几款远程协助软件介绍</title>
		<link>http://www.mzfeng.com/html/y2010/322.html</link>
		<comments>http://www.mzfeng.com/html/y2010/322.html#comments</comments>
		<pubDate>Sat, 29 May 2010 15:45:59 +0000</pubDate>
		<dc:creator>mzfeng</dc:creator>
				<category><![CDATA[软件应用]]></category>
		<category><![CDATA[远程协助]]></category>

		<guid isPermaLink="false">http://www.mzfeng.com/?p=322</guid>
		<description><![CDATA[我们日常办公常用的远程协助一般都是使用Windows自带的远程协助,这里介绍九款免费的Windows远程协助软件。
1、Team Viewer：
TeamViewer是一个既简单又友好的远程协助工具。您可以通过它远程控制对方的桌面，在线帮助对方，也可以让对方看你的屏幕，无需担心防火墙，IP地址和NAT。

2、CrossLoop：
CrossLoop 是另一个免费的远程协助工具，该软件需要两个人都安装它。有关CrossLoop的更多内容可以在 这里看到。

3、LogMeIn：
LogMeIn是一个免费的应用程序，一般在你想让自己的电脑被其他的电脑通过互联网远程控制时使用。通过互联网对方可以完全控制你整个电脑。之前我们曾在这个博客中提到过LogMeIn。

4、Mikogo：
这是另一种易 于使用的跨平台桌面共享工具，非常适合网络会议，在线会议或远程协助。而且它对商业和私人使用都免费。

5、ShowMyPC：
ShowMyPC 提供即时协作工具，也是个免费软件。软件功能包括桌面共享，屏幕录制，远程PC访问。

6、YuuGuu：
这是 另一个有用的远程桌面应用程序，支持Windows以及Mac OSX的平台。

7、UltraVNC：
ultravnc 是一个功能强大，易于使用的免费软件，可以在你自己的屏幕上显示另一台电脑的屏幕（通过互联网或局域网）。该软件允许你使用鼠标和键盘来远程控制其他电 脑。

8、TightVNC：
另一个免费的远程控制软件。通过TightVNC，你可以像坐在自己的电脑前一样，看到并使用本地的鼠标和电脑控制远程电脑的桌面。它也是免费的。

9、EchoVNC：
EchoVNC 是一种既安全，“又对防火墙友好的”远程桌面控制工具，支持VNC，Radmin服务器和查看对方桌面功能。有了它，Windows系统的PC和Mac OSX系统的苹果机都可以无视防火墙，路由器和网络代理配置互相进行远程控制。

这里面有你需要的远程协助软件吗？你还有其他的远程协助软件吗？希望以上总结的几款软件对大家有所帮助。
]]></description>
			<content:encoded><![CDATA[<p>我们日常办公常用的<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/%e8%bf%9c%e7%a8%8b%e5%8d%8f%e5%8a%a9" title="查看 远程协助 的全部文章" target="_blank">远程协助</a></span>一般都是使用Windows自带的<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/%e8%bf%9c%e7%a8%8b%e5%8d%8f%e5%8a%a9" title="查看 远程协助 的全部文章" target="_blank">远程协助</a></span>,这里介绍九款免费的Windows<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/%e8%bf%9c%e7%a8%8b%e5%8d%8f%e5%8a%a9" title="查看 远程协助 的全部文章" target="_blank">远程协助</a></span>软件。</p>
<p><strong>1、Team Viewer：</strong></p>
<p>TeamViewer是一个既简单又友好的远程协助工具。您可以通过它远程控制对方的桌面，在线帮助对方，也可以让对方看你的屏幕，无需担心防火墙，IP地址和NAT。</p>
<p><a href="http://images.51cto.com/files/uploadimg/20100528/0938250.jpg" class="highslide-image" onclick="return hs.expand(this);" target="_blank"><img src="http://images.51cto.com/files/uploadimg/20100528/0938250.jpg" border="0" alt="Team Viewer" width="550" /></a></p>
<p><strong><span id="more-322"></span>2、CrossLoop：</strong></p>
<p>CrossLoop 是另一个免费的远程协助工具，该软件需要两个人都安装它。有关CrossLoop的更多内容可以在 这里看到。</p>
<p><a href="http://images.51cto.com/files/uploadimg/20100528/0938251.jpg" class="highslide-image" onclick="return hs.expand(this);" target="_blank"><img src="http://images.51cto.com/files/uploadimg/20100528/0938251.jpg" border="0" alt="CrossLoop" width="200" height="171" /></a></p>
<p><strong>3、LogMeIn：</strong></p>
<p>LogMeIn是一个免费的应用程序，一般在你想让自己的电脑被其他的电脑通过互联网远程控制时使用。通过互联网对方可以完全控制你整个电脑。之前我们曾在这个博客中提到过LogMeIn。</p>
<p><a href="http://images.51cto.com/files/uploadimg/20100528/0938252.jpg" class="highslide-image" onclick="return hs.expand(this);" target="_blank"></a></p>
<p><strong>4、Mikogo：</strong></p>
<p>这是另一种易 于使用的跨平台桌面共享工具，非常适合网络会议，在线会议或远程协助。而且它对商业和私人使用都免费。</p>
<p><a href="http://images.51cto.com/files/uploadimg/20100528/0938253.jpg" class="highslide-image" onclick="return hs.expand(this);" target="_blank"></a></p>
<p><strong>5、ShowMyPC：</strong></p>
<p>ShowMyPC 提供即时协作工具，也是个免费软件。软件功能包括桌面共享，屏幕录制，远程PC访问。</p>
<p><a href="http://images.51cto.com/files/uploadimg/20100528/0938254.jpg" class="highslide-image" onclick="return hs.expand(this);" target="_blank"><img src="http://images.51cto.com/files/uploadimg/20100528/0938254.jpg" border="0" alt="ShowMyPC" width="542" height="226" /></a></p>
<p><strong>6、YuuGuu：</strong></p>
<p>这是 另一个有用的远程桌面应用程序，支持Windows以及Mac OSX的平台。</p>
<p><a href="http://images.51cto.com/files/uploadimg/20100528/0938255.jpg" class="highslide-image" onclick="return hs.expand(this);" target="_blank"></a></p>
<p><strong>7、UltraVNC：</strong></p>
<p>ultravnc 是一个功能强大，易于使用的免费软件，可以在你自己的屏幕上显示另一台电脑的屏幕（通过互联网或局域网）。该软件允许你使用鼠标和键盘来远程控制其他电 脑。</p>
<p><a href="http://images.51cto.com/files/uploadimg/20100528/0938256.jpg" class="highslide-image" onclick="return hs.expand(this);" target="_blank"><img src="http://images.51cto.com/files/uploadimg/20100528/0938256.jpg" border="0" alt="UltraVNC" width="550" /></a></p>
<p><strong>8、TightVNC：</strong></p>
<p>另一个免费的远程控制软件。通过TightVNC，你可以像坐在自己的电脑前一样，看到并使用本地的鼠标和电脑控制远程电脑的桌面。它也是免费的。</p>
<p><a href="http://images.51cto.com/files/uploadimg/20100528/0938257.jpg" class="highslide-image" onclick="return hs.expand(this);" target="_blank"><img src="http://images.51cto.com/files/uploadimg/20100528/0938257.jpg" border="0" alt="TightVNC" width="495" height="436" /></a></p>
<p><strong>9、EchoVNC：</strong></p>
<p>EchoVNC 是一种既安全，“又对防火墙友好的”远程桌面控制工具，支持VNC，Radmin服务器和查看对方桌面功能。有了它，Windows系统的PC和Mac OSX系统的苹果机都可以无视防火墙，路由器和网络代理配置互相进行远程控制。</p>
<p><a href="http://images.51cto.com/files/uploadimg/20100528/0938258.jpg" class="highslide-image" onclick="return hs.expand(this);" target="_blank"></a></p>
<p>这里面有你需要的远程协助软件吗？你还有其他的远程协助软件吗？希望以上总结的几款软件对大家有所帮助。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mzfeng.com/html/y2010/322.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>腾讯用JAWS做WEB服务器</title>
		<link>http://www.mzfeng.com/html/y2010/320.html</link>
		<comments>http://www.mzfeng.com/html/y2010/320.html#comments</comments>
		<pubDate>Fri, 28 May 2010 15:05:28 +0000</pubDate>
		<dc:creator>mzfeng</dc:creator>
				<category><![CDATA[互联网]]></category>
		<category><![CDATA[JAWS]]></category>
		<category><![CDATA[WEB服务器]]></category>
		<category><![CDATA[腾讯]]></category>

		<guid isPermaLink="false">http://www.mzfeng.com/?p=320</guid>
		<description><![CDATA[JAWS是什么？JAWS是一个高性能Web服务器的架构。我又是怎么找到腾讯在使用这个的呢？
请确保你的Firefox己装firebug。打开firefox,进入这里：http://m98.mail.qq.com/cgi-bin/mdb
看到404错误，打开FireBUG，查看请求的header响应，你会发现它会有一个这样的信息：JAWS/1.0prebeta
那么神奇的JAWS到底有什么魔力呢？
下面转一篇文章
——————————————————————————————————————-
第2章JAWS：高性能Web服务器构架
James C. Hu Douglas C. Schmidt
摘要
通信软件的开发者面临着许多挑战。通信软件包含固有的复杂性，比如错误检测和恢复；以及随机的复杂性，比如关键概念和组件的持续的重新发现和发明。应对这些挑战需要对面向对象应用构架和模式有全面的了解。本论文阐释我们是怎样将通信软件的构架和模式应用于开发称为JAWS的高性能Web服务器的。
JAWS是一种面向对象的构架，支持多种Web服务器策略的配置，比如使用异步I/O和LRU缓存的线程池并发模型 vs.使用同步I/O和LFU缓存的Thread-per-Request并发模型。因为JAWS是一个构架，可以系统地对这些策略进行定制，独立地或协作地进行评估，以决定最佳的策略方案。使用这些方案，JAWS可以静态地和动态地改变自己的行为，以为给定的软件/硬件平台和工作负载采用最为有效的策略。JAWS的自适配软件特性使其成为用于构造高性能Web服务器的强大应用构架。
2.1介绍
在过去的几年中，万维网（Web）上的通信流量发生了戏剧性的增长。流量的增长在很大程度上应归于廉价的和无处不在的Web浏览器（比如NCSA Mosaic、Netscape Navigator和Internet Explorer）的激增。同样地，Web协议和浏览器也正日益被应用于专门而昂贵的计算任务，比如西门子[1]和柯达[2]所用的图像处理服务器和像 AltaVista和Lexis-Nexis这样的数据库搜索引擎。
要跟上需求增长的步伐，必须开发高性能Web服务器。但是，在开发者配置和优化Web服务器时，他们面对的是一组异常丰富的设计策略。例如，开发者必须在广泛的并发模型（比如Thread-per-Request vs. 线程池）、分派模型（比如同步 vs. 异步分派）、文件缓存模型（比如LRU vs. LFU），以及协议处理模型（比如HTTP/1.0 vs. HTTP/1.1）中进行选择。没有哪种配置对于所有硬件/软件平台和工作负载来说都是最佳的[1, 3]。
所有这些可选策略的存在保证了开发者可以定制Web服务器、以满足用户的需求。但是，在许多设计和优化策略间进行选择是麻烦而易错的。没有相应的指导，开发者将面临艰巨的任务：从头开始设计Web服务器来产生特定的解决方案。这样的系统常常难以维护、定制和调谐，因为许多设计工作都只是花在了使系统可运行上。
2.1.1定义
我们将经常引用术语OO类库、构架、模式和组件。这些术语所指的是用于构建可复用软件系统的工具。OO类库是一组软件对象实现，它们在用户调用对象方法时提供可复用功能。构架是一种可复用、“半完成”的应用，可被定制以产生自定义应用 [4]。模式表示在特定的上下文中、软件开发问题的可反复使用的解决方案[5]。组件指的是一种“可具体化”的对象。OO类库和构架都是通过实例化和专门化而得以具体化的成组对象。模式组件则通过编码来具体化。
2.1.2综述
本论文阐释怎样使用OO应用构架和设计模式来产生灵活而高效的Web服务器。模式和构架可以协作应用，以改善 Web服务器的效率和灵活性。模式以一种系统而易于理解的形式捕捉高性能和自适配Web服务器的抽象设计和软件体系结构。构架则使用特定的编程语言，比如 C++或Java，来捕捉Web服务器的具体设计、算法和实现。相反，OO类库提供构建应用所必需的原始材料，但没有对怎样将这些片段放在一起进行指导。
本论文聚焦于用于开发JAWS[1, 3]高性能Web服务器的模式和构架。JAWS既是一个Web服务器，又是一个构架，其他类型的服务器可通过它来进行构建。JAWS构架自身是使用ACE构架[6, 7]来开发的。ACE构架使通信软件领域中的一些关键模式[5]得以具体化。JAWS和ACE中的构架和模式是有代表性的解决方案，已被成功应用于许多通信系统，范围从电信系统管理[8]到企业医学成像[2]和实时航空控制系统[9]等。
本论文被组织如下：2.2给出对模式和构架的综述，并说明JAWS所提供的通信软件构架类型的动机；2.3阐释怎样应用模式和组件来开发高性能Web服务器；2.4比较JAWS与其他高性能Web服务器在高速ATM网络上的性能；2.5给出结束语。
2.2将模式和构架应用于Web服务器
为了给数目正在增长的 Internet和Intranet用户提供服务和内容，对于高性能Web服务器的需求正在日益增长。Web服务器的开发者正在努力构建快速、可伸缩和可配置的系统。但是，如果不注意避开一些常见的陷阱和缺陷，其中包括麻烦而易错的低级编程细节、缺乏可移植性，以及广泛的设计选择，这样的任务可能是十分困难的。这一部分给出了这些危险的路标。随后我们描述开发者怎样通过有效利用设计和代码复用，将模式和构架应用于避免这些危险。
2.2.1 Web服务器软件的常见缺陷
Web服务器开发者面临着一些反复发生的挑战，这些挑战在很大程度上独立于特定的应用需求。例如，像其他通信软件一样，Web服务器必须执行多种任务：连接建立、事件处理器分派、进程间通信、内存管理和文件缓存、静态和动态的组件配置、并发、同步，以及持续性。在大多数Web服务器中，这些任务是以特定的方式、使用低级的本地OS应用编程接口（API）（比如用C编写的 Win32或POSIX）来实现的。
遗憾的是，本地OS API并不是开发Web服务器或其他类型的通信中间件和应用[10]的有效途径。下面是与本地OS API的使用相关联的常见缺陷：
过多的低级细节：通过本地OS API来构建Web服务器要求开发者熟悉低级的OS细节。开发者必须仔细地追踪每个系统调用返回的错误代码，并在他们的服务器中处理这些特定于OS的问题。这样的细节使得开发者的注意力从更广阔的、更为战略性的问题（比如语义和程序结构）上转移开来。例如，使用wait系统调用的UNIX开发者必须在下面两种错误之间进行区分：由于没有子进程存在而返回的错误和来自信号中断的错误。在后一种情况下，必须重新发出wait调用。
持续地重新发现和发明不兼容的更高级编程抽象：常用的对过多的OS API细节的补救方法是定义更高级的编程抽象。例如，许多Web服务器都创建文件缓存，以避免每次客户请求都要访问文件系统。但是，这些类型的抽象常常被各个开发者或项目独立地重新发现和发明。这样的特定处理妨碍了生产效率，并创建出不兼容的组件，无法迅速地在大型软件组织的项目内和项目间复用。
高错误可能性：由于低级OS API缺乏类型安全性，对它们进行编程是麻烦而易错的。例如，大多数Web服务器都使用Socket API[11]来编写。但是，Socket API中的通信端点被表示为无类型的句柄。这增加了发生微妙的编程错误和运行时错误的可能性。
缺乏可移植性：低级OS API出了名地不可移植，即使是在同一OS的不同版本间也是如此。例如，Win32平台上的Socket API实现（WinSock）与UNIX 平台上的实现有着微妙的不同。而且，即使是Windows NT的不同版本上的WinSock实现也具有不兼容的、与时俱变的错误：在执行非阻塞连接时会导致偶发的失败。
陡峭的学习曲线：由于有过多的细节，掌握OS级API所需的努力可能是很高的。例如，学习怎样正确地使用POSIX异步I/O[12]来编程十分困难。学习怎样使用异步I/O机制来编写可移植的应用甚至会更困难，因为它们在各OS平台间有着极大的不同。
不能处理更高的复杂性：OS API为一些机制定义了基本接口，像进程和线程管理、进程间通信、文件系统，以及内存管理。但是，当应用的大小和复杂性增长时，这些基本接口无法适当地升级。例如，典型的UNIX进程只允许缓冲大约7个待处理连接[13]。对于被大量访问的、必须处理成百并发客户的Web服务器来说，这个数目是不够的。
2.2.2通过模式和构架克服Web服务器的缺陷
软件复用是被广泛称许的减少开发工作量的方法。复用有效利用了有经验的开发者的领域知识和以前的成果。在有效地应用时，复用可以避免重新创建和认证常用的、针对重复发生的应用需求和软件设计挑战的解决方案。
Java的java.lang.net和RougeWave Net.h++是两个常见的将可复用OO类库应用于通信软件的例子。尽管类库有效地支持小规模的组件复用，它们的范围是严重受限的。特别地，类库不会对相关软件组件族之间的规范控制流和协作进行捕捉。因而，应用基于类库的复用的开发者常常要为每个新应用重新发明和实现整个的软件体系结构。
更为强大的克服上面描述的缺陷的途径是对在成功的Web服务器之下的模式进行标识，并在面向对象应用构架中使这些模式具体化。通过捕捉常见软件开发问题的解决方案，模式和构架有助于减少对关键的Web服务器概念和组件的重新发现和发明[5]。
将模式应用于Web服务器的好处：模式提供了常见的Web服务器微体系中的结构和参与者的文档。例如，反应堆（Reactor） [14]和主动对象（Active Object）[15]模式分别被广泛用作Web服务器的分派和并发策略。这些模式是已被证明有益于构建灵活而高效的Web服务器的对象结构的一般化。
传统上，这些模式类型或者被锁在老练的开发者的头脑里，或者被深埋在源码中。但是，让这样有价值的信息只是放在这些地方是危险而昂贵的。例如，如果不编写文档，有经验的Web服务器设计者的洞见可能会随时间而消逝。同样地，可能需要相当的努力才能从现有源码中反向地设计出模式来。因此，为了给负责增强和维护现有软件的开发者保留设计信息，明确地捕捉Web服务器模式并编写文档是必要的。而且，特定领域的知识还有助于指导在其他领域中构建新服务器的开发者的设计决策。
将构架应用于Web服务器的好处：模式知识有助于减少开发工作和维护代价。但是，只是复用模式并不足以创建灵活而高效的Web服务器软件。在模式使抽象设计和体系结构知识复用成为可能的同时，被编写为模式的抽象并不会直接产生可复用的代码[16]。因此，有必要增加对模式的研究，考查它们与构架的创建和使用的关系。通过实现常用设计模式、并分解出常见实现角色，构架可帮助开发者避免对标准的Web服务器组件进行昂贵的重新发明。
2.2.3构架、模式，以及其他复用技术之间的关系
通过集成成组的抽象类，并定义这些类的实例进行协作的标准方式，构架为应用提供了可复用的软件组件[4]。一般而言，组件并不是自包含的，因为它们常常依赖于构架中其他组件所提供的功能。但是，这些组件聚合在一起构成了特定的实现，也就是，应用骨架。可以通过继承和实例化构架中的可复用组件来对骨架进行定制。
Web服务器中复用的范围可以显著地大于使用传统的函数库或组件的OO类库。特别地，2.3中描述的JAWS构架特别为广泛的Web服务器任务作了裁剪。这些任务包括服务初始化、错误处理、流控制、事件处理、文件缓存、并发控制和原型流水线操作。重要的是要记住这些任务对于其他许多类型的通信软件来说也是可复用的。
总而言之，构架和组件以下面几种方式增强了基于组件类库的复用技术：
构架定义“半完成”应用，其中包含了特定领域的对象结构和功能：类库提供了一种粒度相对较小的复用。例如，图2-1中的类和字符串、复数、数据及位组一样，是典型的低级、相对独立和通用的组件。
[点击图片可在新窗口打开]
图2-1 类库组件体系结构
相反，构架中的组件相互协作，来为相关应用族提供可定制的体系结构骨架。完整的应用可以通过从构架组件继承、以及/或者实例化构架组件来合成。如图2-2所示，构架减少了应用特有代码的数量，因为特定领域的许多处理被分解进通用的构架组件中。
[点击图片可在新窗口打开]
图2-2 应用构架组件体系结构
构架是主动的，并在运行时显示出 “控制的反转”：类库组件通常被动地工作。特别地，类库组件常常从“自指引”（self-directed）的应用对象那里借用线程控制来完成它们的处理。因为应用对象是自指引的，在很大程度上应用开发者要负责决定怎样组合组件和类，以形成完整的系统。例如，通常要为每个新应用重写管理事件循环、并在可复用和应用特有组件间确定控制流的代码。
通过类库和组件构建的应用的典型结构和动力特性在图2-1中演示。该图还演示了设计模式怎样帮助指导类库组件的设计、实现和复用。注意，在提供工具解决特定任务（例如建立网络连接）的同时，类库的存在并没有提供对系统设计的明确指导。特别地，软件开发者要独自负责在他们的应用设计中确定并应用模式。
相对于类库，构架中的组件更为主动。特别地，它们通过像反应堆（Reactor）[14]和观察者（Observer）[5]这样的事件分派分派模式来管理应用中的规范控制流。构架的回调驱动的运行时体系结构如图2-2所示。
图2-2演示了构架的一种关键特性：它在运行时的“控制的反转”。这种设计使得规范的应用处理步骤可由通过构架的反应式分派机制[14]调用的事件处理器对象来定制。在事件发生时，构架的分派器通过调用预登记处理器对象的挂钩方法来进行反应，由该方法完成事件的应用特有的处理。
控制的反转允许构架，而不是每个应用，确定调用哪一组应用特有方法来响应外部事件（比如HTTP连接和数据到达Socket）。作为结果，构架使一组集成的模式具体化、并预先应用进协作的组件中。这样的设计减轻了软件开发者的负担。
在实践中，构架、类库和组件是互相补充的技术。构架常常在内部利用类库和组件来简化构架的开发。例如，JAWS的一些部分使用由C++标准模板库（STL） [17]提供的字符串和向量容器来管理连接映射和其他查找结构。此外，由构架事件处理器调用的应用特有的回调常常使用类库组件来完成基本的任务，比如字符串处理、文件管理和数字分析。
为演示怎样成功地应用OO模式和构架来开发灵活而高效的通信软件，本论文的余下部分检查JAWS构架的结构、使用和性能。
2.3 JAWS自适配Web服务器
将构架和模式应用于通信软件的好处最好通过例子来演示。这一部分描述JAWS的结构和功能。JAWS是一种高性能和自适配的、实现了HTTP协议的Web服务器。它还是一个平台无关的应用构架，其他类型的通信服务器可以通过它来构建。
2.3.1 JAWS构架综述
图2-3 JAWS构架的体系概览
图2-3演示组成JAWS自适配Web服务器构架的主要结构组件和设计模式。JAWS的设计允许定制多种Web服务器策略，以响应环境因素。这些因素包括静态因素，比如对OS中的内核级线程及/或异步I/O的支持、可用CPU的数目；以及动态因素，比如Web流量模式和工作负载特性。
JAWS被构造为构架的构架（framework of frameworks）。整个JAWS构架含有以下组件和构架：事件分派器（Event Dispatcher）、并发策略（Concurrency Strategy）、I/O策略（I/O Strategy）、协议流水线（Protocol [...]]]></description>
			<content:encoded><![CDATA[<p><span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/jaws" title="查看 JAWS 的全部文章" target="_blank">JAWS</a></span>是什么？<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/jaws" title="查看 JAWS 的全部文章" target="_blank">JAWS</a></span>是一个高性能Web服务器的架构。我又是怎么找到<span class='wp_keywordlink_affiliate'><a href="http://www.mzfeng.com/html/ytag/%e8%85%be%e8%ae%af" title="查看 腾讯 的全部文章" target="_blank">腾讯</a></span>在使用这个的呢？</p>
<p>请确保你的Firefox己装firebug。打开firefox,进入这里：<a href="http://m98.mail.qq.com/cgi-bin/mdb">http://m98.mail.qq.com/cgi-bin/mdb</a></p>
<p>看到404错误，打开FireBUG，查看请求的header响应，你会发现它会有一个这样的信息：<code>JAWS/1.0prebeta</code></p>
<p>那么神奇的JAWS到底有什么魔力呢？</p>
<p><span id="more-320"></span>下面转一篇文章</p>
<p>——————————————————————————————————————-<br />
第2章JAWS：高性能Web服务器构架</p>
<p>James C. Hu Douglas C. Schmidt</p>
<p>摘要</p>
<p>通信软件的开发者面临着许多挑战。通信软件包含固有的复杂性，比如错误检测和恢复；以及随机的复杂性，比如关键概念和组件的持续的重新发现和发明。应对这些挑战需要对面向对象应用构架和模式有全面的了解。本论文阐释我们是怎样将通信软件的构架和模式应用于开发称为JAWS的高性能Web服务器的。<br />
JAWS是一种面向对象的构架，支持多种Web服务器策略的配置，比如使用异步I/O和LRU缓存的线程池并发模型 vs.使用同步I/O和LFU缓存的Thread-per-Request并发模型。因为JAWS是一个构架，可以系统地对这些策略进行定制，独立地或协作地进行评估，以决定最佳的策略方案。使用这些方案，JAWS可以静态地和动态地改变自己的行为，以为给定的软件/硬件平台和工作负载采用最为有效的策略。JAWS的自适配软件特性使其成为用于构造高性能Web服务器的强大应用构架。</p>
<p>2.1介绍</p>
<p>在过去的几年中，万维网（Web）上的通信流量发生了戏剧性的增长。流量的增长在很大程度上应归于廉价的和无处不在的Web浏览器（比如NCSA Mosaic、Netscape Navigator和Internet Explorer）的激增。同样地，Web协议和浏览器也正日益被应用于专门而昂贵的计算任务，比如西门子[1]和柯达[2]所用的图像处理服务器和像 AltaVista和Lexis-Nexis这样的数据库搜索引擎。<br />
要跟上需求增长的步伐，必须开发高性能Web服务器。但是，在开发者配置和优化Web服务器时，他们面对的是一组异常丰富的设计策略。例如，开发者必须在广泛的并发模型（比如Thread-per-Request vs. 线程池）、分派模型（比如同步 vs. 异步分派）、文件缓存模型（比如LRU vs. LFU），以及协议处理模型（比如HTTP/1.0 vs. HTTP/1.1）中进行选择。没有哪种配置对于所有硬件/软件平台和工作负载来说都是最佳的[1, 3]。<br />
所有这些可选策略的存在保证了开发者可以定制Web服务器、以满足用户的需求。但是，在许多设计和优化策略间进行选择是麻烦而易错的。没有相应的指导，开发者将面临艰巨的任务：从头开始设计Web服务器来产生特定的解决方案。这样的系统常常难以维护、定制和调谐，因为许多设计工作都只是花在了使系统可运行上。</p>
<p>2.1.1定义</p>
<p>我们将经常引用术语OO类库、构架、模式和组件。这些术语所指的是用于构建可复用软件系统的工具。OO类库是一组软件对象实现，它们在用户调用对象方法时提供可复用功能。构架是一种可复用、“半完成”的应用，可被定制以产生自定义应用 [4]。模式表示在特定的上下文中、软件开发问题的可反复使用的解决方案[5]。组件指的是一种“可具体化”的对象。OO类库和构架都是通过实例化和专门化而得以具体化的成组对象。模式组件则通过编码来具体化。</p>
<p>2.1.2综述</p>
<p>本论文阐释怎样使用OO应用构架和设计模式来产生灵活而高效的Web服务器。模式和构架可以协作应用，以改善 Web服务器的效率和灵活性。模式以一种系统而易于理解的形式捕捉高性能和自适配Web服务器的抽象设计和软件体系结构。构架则使用特定的编程语言，比如 C++或Java，来捕捉Web服务器的具体设计、算法和实现。相反，OO类库提供构建应用所必需的原始材料，但没有对怎样将这些片段放在一起进行指导。<br />
本论文聚焦于用于开发JAWS[1, 3]高性能Web服务器的模式和构架。JAWS既是一个Web服务器，又是一个构架，其他类型的服务器可通过它来进行构建。JAWS构架自身是使用ACE构架[6, 7]来开发的。ACE构架使通信软件领域中的一些关键模式[5]得以具体化。JAWS和ACE中的构架和模式是有代表性的解决方案，已被成功应用于许多通信系统，范围从电信系统管理[8]到企业医学成像[2]和实时航空控制系统[9]等。<br />
本论文被组织如下：2.2给出对模式和构架的综述，并说明JAWS所提供的通信软件构架类型的动机；2.3阐释怎样应用模式和组件来开发高性能Web服务器；2.4比较JAWS与其他高性能Web服务器在高速ATM网络上的性能；2.5给出结束语。</p>
<p>2.2将模式和构架应用于Web服务器</p>
<p>为了给数目正在增长的 Internet和Intranet用户提供服务和内容，对于高性能Web服务器的需求正在日益增长。Web服务器的开发者正在努力构建快速、可伸缩和可配置的系统。但是，如果不注意避开一些常见的陷阱和缺陷，其中包括麻烦而易错的低级编程细节、缺乏可移植性，以及广泛的设计选择，这样的任务可能是十分困难的。这一部分给出了这些危险的路标。随后我们描述开发者怎样通过有效利用设计和代码复用，将模式和构架应用于避免这些危险。</p>
<p>2.2.1 Web服务器软件的常见缺陷</p>
<p>Web服务器开发者面临着一些反复发生的挑战，这些挑战在很大程度上独立于特定的应用需求。例如，像其他通信软件一样，Web服务器必须执行多种任务：连接建立、事件处理器分派、进程间通信、内存管理和文件缓存、静态和动态的组件配置、并发、同步，以及持续性。在大多数Web服务器中，这些任务是以特定的方式、使用低级的本地OS应用编程接口（API）（比如用C编写的 Win32或POSIX）来实现的。<br />
遗憾的是，本地OS API并不是开发Web服务器或其他类型的通信中间件和应用[10]的有效途径。下面是与本地OS API的使用相关联的常见缺陷：</p>
<p>过多的低级细节：通过本地OS API来构建Web服务器要求开发者熟悉低级的OS细节。开发者必须仔细地追踪每个系统调用返回的错误代码，并在他们的服务器中处理这些特定于OS的问题。这样的细节使得开发者的注意力从更广阔的、更为战略性的问题（比如语义和程序结构）上转移开来。例如，使用wait系统调用的UNIX开发者必须在下面两种错误之间进行区分：由于没有子进程存在而返回的错误和来自信号中断的错误。在后一种情况下，必须重新发出wait调用。</p>
<p>持续地重新发现和发明不兼容的更高级编程抽象：常用的对过多的OS API细节的补救方法是定义更高级的编程抽象。例如，许多Web服务器都创建文件缓存，以避免每次客户请求都要访问文件系统。但是，这些类型的抽象常常被各个开发者或项目独立地重新发现和发明。这样的特定处理妨碍了生产效率，并创建出不兼容的组件，无法迅速地在大型软件组织的项目内和项目间复用。</p>
<p>高错误可能性：由于低级OS API缺乏类型安全性，对它们进行编程是麻烦而易错的。例如，大多数Web服务器都使用Socket API[11]来编写。但是，Socket API中的通信端点被表示为无类型的句柄。这增加了发生微妙的编程错误和运行时错误的可能性。</p>
<p>缺乏可移植性：低级OS API出了名地不可移植，即使是在同一OS的不同版本间也是如此。例如，Win32平台上的Socket API实现（WinSock）与UNIX 平台上的实现有着微妙的不同。而且，即使是Windows NT的不同版本上的WinSock实现也具有不兼容的、与时俱变的错误：在执行非阻塞连接时会导致偶发的失败。</p>
<p>陡峭的学习曲线：由于有过多的细节，掌握OS级API所需的努力可能是很高的。例如，学习怎样正确地使用POSIX异步I/O[12]来编程十分困难。学习怎样使用异步I/O机制来编写可移植的应用甚至会更困难，因为它们在各OS平台间有着极大的不同。</p>
<p>不能处理更高的复杂性：OS API为一些机制定义了基本接口，像进程和线程管理、进程间通信、文件系统，以及内存管理。但是，当应用的大小和复杂性增长时，这些基本接口无法适当地升级。例如，典型的UNIX进程只允许缓冲大约7个待处理连接[13]。对于被大量访问的、必须处理成百并发客户的Web服务器来说，这个数目是不够的。</p>
<p>2.2.2通过模式和构架克服Web服务器的缺陷</p>
<p>软件复用是被广泛称许的减少开发工作量的方法。复用有效利用了有经验的开发者的领域知识和以前的成果。在有效地应用时，复用可以避免重新创建和认证常用的、针对重复发生的应用需求和软件设计挑战的解决方案。<br />
Java的java.lang.net和RougeWave Net.h++是两个常见的将可复用OO类库应用于通信软件的例子。尽管类库有效地支持小规模的组件复用，它们的范围是严重受限的。特别地，类库不会对相关软件组件族之间的规范控制流和协作进行捕捉。因而，应用基于类库的复用的开发者常常要为每个新应用重新发明和实现整个的软件体系结构。<br />
更为强大的克服上面描述的缺陷的途径是对在成功的Web服务器之下的模式进行标识，并在面向对象应用构架中使这些模式具体化。通过捕捉常见软件开发问题的解决方案，模式和构架有助于减少对关键的Web服务器概念和组件的重新发现和发明[5]。</p>
<p>将模式应用于Web服务器的好处：模式提供了常见的Web服务器微体系中的结构和参与者的文档。例如，反应堆（Reactor） [14]和主动对象（Active Object）[15]模式分别被广泛用作Web服务器的分派和并发策略。这些模式是已被证明有益于构建灵活而高效的Web服务器的对象结构的一般化。<br />
传统上，这些模式类型或者被锁在老练的开发者的头脑里，或者被深埋在源码中。但是，让这样有价值的信息只是放在这些地方是危险而昂贵的。例如，如果不编写文档，有经验的Web服务器设计者的洞见可能会随时间而消逝。同样地，可能需要相当的努力才能从现有源码中反向地设计出模式来。因此，为了给负责增强和维护现有软件的开发者保留设计信息，明确地捕捉Web服务器模式并编写文档是必要的。而且，特定领域的知识还有助于指导在其他领域中构建新服务器的开发者的设计决策。</p>
<p>将构架应用于Web服务器的好处：模式知识有助于减少开发工作和维护代价。但是，只是复用模式并不足以创建灵活而高效的Web服务器软件。在模式使抽象设计和体系结构知识复用成为可能的同时，被编写为模式的抽象并不会直接产生可复用的代码[16]。因此，有必要增加对模式的研究，考查它们与构架的创建和使用的关系。通过实现常用设计模式、并分解出常见实现角色，构架可帮助开发者避免对标准的Web服务器组件进行昂贵的重新发明。</p>
<p>2.2.3构架、模式，以及其他复用技术之间的关系</p>
<p>通过集成成组的抽象类，并定义这些类的实例进行协作的标准方式，构架为应用提供了可复用的软件组件[4]。一般而言，组件并不是自包含的，因为它们常常依赖于构架中其他组件所提供的功能。但是，这些组件聚合在一起构成了特定的实现，也就是，应用骨架。可以通过继承和实例化构架中的可复用组件来对骨架进行定制。<br />
Web服务器中复用的范围可以显著地大于使用传统的函数库或组件的OO类库。特别地，2.3中描述的JAWS构架特别为广泛的Web服务器任务作了裁剪。这些任务包括服务初始化、错误处理、流控制、事件处理、文件缓存、并发控制和原型流水线操作。重要的是要记住这些任务对于其他许多类型的通信软件来说也是可复用的。<br />
总而言之，构架和组件以下面几种方式增强了基于组件类库的复用技术：</p>
<p>构架定义“半完成”应用，其中包含了特定领域的对象结构和功能：类库提供了一种粒度相对较小的复用。例如，图2-1中的类和字符串、复数、数据及位组一样，是典型的低级、相对独立和通用的组件。</p>
<p>[点击图片可在新窗口打开]</p>
<p>图2-1 类库组件体系结构</p>
<p>相反，构架中的组件相互协作，来为相关应用族提供可定制的体系结构骨架。完整的应用可以通过从构架组件继承、以及/或者实例化构架组件来合成。如图2-2所示，构架减少了应用特有代码的数量，因为特定领域的许多处理被分解进通用的构架组件中。</p>
<p>[点击图片可在新窗口打开]</p>
<p>图2-2 应用构架组件体系结构</p>
<p>构架是主动的，并在运行时显示出 “控制的反转”：类库组件通常被动地工作。特别地，类库组件常常从“自指引”（self-directed）的应用对象那里借用线程控制来完成它们的处理。因为应用对象是自指引的，在很大程度上应用开发者要负责决定怎样组合组件和类，以形成完整的系统。例如，通常要为每个新应用重写管理事件循环、并在可复用和应用特有组件间确定控制流的代码。<br />
通过类库和组件构建的应用的典型结构和动力特性在图2-1中演示。该图还演示了设计模式怎样帮助指导类库组件的设计、实现和复用。注意，在提供工具解决特定任务（例如建立网络连接）的同时，类库的存在并没有提供对系统设计的明确指导。特别地，软件开发者要独自负责在他们的应用设计中确定并应用模式。<br />
相对于类库，构架中的组件更为主动。特别地，它们通过像反应堆（Reactor）[14]和观察者（Observer）[5]这样的事件分派分派模式来管理应用中的规范控制流。构架的回调驱动的运行时体系结构如图2-2所示。<br />
图2-2演示了构架的一种关键特性：它在运行时的“控制的反转”。这种设计使得规范的应用处理步骤可由通过构架的反应式分派机制[14]调用的事件处理器对象来定制。在事件发生时，构架的分派器通过调用预登记处理器对象的挂钩方法来进行反应，由该方法完成事件的应用特有的处理。<br />
控制的反转允许构架，而不是每个应用，确定调用哪一组应用特有方法来响应外部事件（比如HTTP连接和数据到达Socket）。作为结果，构架使一组集成的模式具体化、并预先应用进协作的组件中。这样的设计减轻了软件开发者的负担。</p>
<p>在实践中，构架、类库和组件是互相补充的技术。构架常常在内部利用类库和组件来简化构架的开发。例如，JAWS的一些部分使用由C++标准模板库（STL） [17]提供的字符串和向量容器来管理连接映射和其他查找结构。此外，由构架事件处理器调用的应用特有的回调常常使用类库组件来完成基本的任务，比如字符串处理、文件管理和数字分析。<br />
为演示怎样成功地应用OO模式和构架来开发灵活而高效的通信软件，本论文的余下部分检查JAWS构架的结构、使用和性能。</p>
<p>2.3 JAWS自适配Web服务器</p>
<p>将构架和模式应用于通信软件的好处最好通过例子来演示。这一部分描述JAWS的结构和功能。JAWS是一种高性能和自适配的、实现了HTTP协议的Web服务器。它还是一个平台无关的应用构架，其他类型的通信服务器可以通过它来构建。</p>
<p>2.3.1 JAWS构架综述</p>
<p>图2-3 JAWS构架的体系概览</p>
<p>图2-3演示组成JAWS自适配Web服务器构架的主要结构组件和设计模式。JAWS的设计允许定制多种Web服务器策略，以响应环境因素。这些因素包括静态因素，比如对OS中的内核级线程及/或异步I/O的支持、可用CPU的数目；以及动态因素，比如Web流量模式和工作负载特性。<br />
JAWS被构造为构架的构架（framework of frameworks）。整个JAWS构架含有以下组件和构架：事件分派器（Event Dispatcher）、并发策略（Concurrency Strategy）、I/O策略（I/O Strategy）、协议流水线（Protocol Pipeline）、协议处理器（Protocol Handler），以及缓存式虚拟文件系统(Cached Virtual Filesystem)。各个构架都被构造为一组使用ACE[18]中的组件实现的协作对象。JAWS组件和构架之间的协作由一个模式族进行指导，该模式族在图2-3中沿着图的边缘列出。对JAWS中的关键构架、组件和模式的概述在下面给出。更为详细的对这些模式怎样应用于JAWS的设计的描述将在 2.3.2中给出。</p>
<p>事件分派器（Event Dispatcher）：该组件负责协调JAWS的并发策略和它的I/O策略。Web客户的被动连接建立遵循接受器（Acceptor）模式 [19]。新到来的请求由一种并发策略服务。在事件被处理时，它们被分派到协议处理器（Protocol Handler），后者由一种I/O策略参数化。从一系列可选方案中选择，以动态绑定到特定并发策略和I/O策略的机制遵循策略（Strategy）模式 [5]。</p>
<p>并发策略（Concurrency Strategy）：该构架实现的并发机制（比如单线程、Thread- per-Request，或线程池）可被适配性地选择：在运行时使用状态（State）模式，或在初始化时预先确定。服务配置器（Service Configurator）模式[20]用于在运行时将特定的并发策略配置进Web服务器。当并发涉及多线程时，策略会创建遵循主动对象（Active Object）模式[15]的协议处理器。</p>
<p>I/O策略（I/O Strategy）：该构架实现多种I/O机制，比如异步、同步和反应式I /O。多种I/O机制可以同时使用。异步I/O通过前摄器（Proactor）[21]和异步完成令牌（Asynchronous Completion Token）[22]模式来实现。反应式I/O通过反应堆（Reactor）模式[14]来完成。反 应式I/O利用Memento模式[5]来捕捉请求状态，并使其外在化，以在后面将其恢复。</p>
<p>协议处理器（Protocol Handler）：该构架允许系统开发者将JAWS构架应用于Web系统应用的变种。协议处理器由并发策略和I/O策略来参数化。这些策略对协议处理器来说是不透明的（通过使用适配器（Adapter） [5]模式）。在JAWS中，该组件实现了HTTP/1.0请求方法的解析与处理。该抽象使得其他协议（比如HTTP/1.1和DICOM）能够很容易地结合进JAWS。要增加新协议，开发者只需简单地编写新的协议处理器实现，随后将其配置进JAWS构架中。</p>
<p>协议流水线（Protocol Pipeline）：该构架使过滤器操作能够很容易地与正在被协议处理器处理的数据进行合成。这种集成是通过采用适配器模式来完成的。流水线遵循用于输入处理的管道和过滤器（Pipes and Filters）模式[23]。使用服务配置器模式，可在运行时动态链接流水线组件。</p>
<p>缓存式虚拟文件系统（Cached Virtual Filesystem）：该组件通过减少文件系统访问开销来改善Web服务器性能。可以遵循策略模式[5]来选择多种缓存策略，比如LRU、LFU、提示式策略和结构化策略。这使得开发者可以根据有效性来对不同的缓存策略进行裁剪，并静态或动态地配置最佳策略。各个Web服务器的缓存通过使用单体（Singleton）模式[5]来实例化。</p>
<p>Tilde Expander：该组件是另一种缓存组件，它使用理想哈希表[24]来将简写的用户登录名（例如，~schmidt）映射到用户主目录（例如，/home/cs/faculty/schmidt）。当个人Web页面存储在用户主目录中、而用户目录又没有驻留在共同的根上时，该组件能够充分地减少访问系统用户信息文件（比如/etc/passwd）所需的磁盘I/O开销。通过服务配置器模式的效力，可以动态地解除Tilde Expander的链接，并将其重新链接进服务器（例如，在新用户加入系统时）。</p>
<p>2.3.2 JAWS中的设计模式综述</p>
<p>图2-3中的JAWS体系结构图演示了JAWS是怎样构造的，但并没有说明它为什么以这种特定的方式构造。要理解JAWS为什么包含有像并发策略、I/O策略、协议处理器和事件分派器这样的构架和组件，需要对在通信软件领域（一般而言）和Web服务器（特定的）之下的设计模式有更深入的了解。图2-4 演示与JAWS有关的战略和战术模式。这些模式在下面进行总结。</p>
<p>图2-4 JAWS构架中使用的设计模式</p>
<p>2.3.2.1 战略模式</p>
<p>下面的模式对于Web服务器的整个软件体系结构来说是战略性的。它们的使用广泛地影响了系统中大量组件的交互水平。这些模式还被广泛用于指导许多其他类型的通信软件的体系结构。</p>
<p>接受器模式（Acceptor Pattern）：该模式使被动的连接建立与连接一旦建立后所执行的服务去耦合 [19]。JAWS使用接受器模式来独立于它的连接管理策略适配性地改变它的并发和I/O策略。图2-5演示在JAWS的上下文中的接受器模式的结构。接受器是一种工厂[5]，无论何时事件分派器通知它有连接已从客户到达，它都会创建、接受并启用一个新的协议处理器。</p>
<p>图2-5 JAWS中接受器模式的结构</p>
<p>反应堆模式（Reactor Pattern）：该模式使服务器应用的同步事件多路分离及事件处理器通知分派逻辑与为响应事件而执行的服务去耦合[14]。JAWS使用反应堆模式来处理来自多个事件源的多个同步事件，而又无需轮询所有事件源，或是无限期地阻塞在任何事件源上。图2-6演示在JAWS上下文中的反应堆模式的结构。</p>
<p>图2-6 JAWS中反应堆模式的结构</p>
<p>JAWS Reactive IO Handler（反应式I/O处理器）对象将自身登记到Initiation Dispatcher（发起分派器），以与一些事件（也就是，在由HTTP请求建立的连接上的输入和输出）相关联。当与这些Reactive IO Handler对象相关联的事件发生时，Initiation Dispatcher调用它们的handle_input 通知挂钩方法。2.3.3.2介绍的单线程Web服务器并发模型使用了反应堆模式。</p>
<p>前摄器模式（Proactor Pattern）：该模式使服务器应用的异步事件多路分离及事件处理器完成分派逻辑与为响应事件而执行的服务去耦合[21]。JAWS使用前摄器模式来在异步地处理其他I/O事件的同时执行服务器特有的处理，比如解析请求头。图2-7 演示在JAWS上下文中的前摄器模式的结构。JAWS Proactive IO Handler（前摄式I/O处理器）对象将自身登记到Completion Dispatcher（完成分派器），以与一些事件（也就是，在由HTTP请求建立的连接上的文件接收和递送）相关联。</p>
<p>图2-7 JAWS中前摄器模式的结构</p>
<p>反应堆和前摄器模式之间的主要区别是Proactive IO Handler定义完成挂钩，而Reactive IO Handler处理器定义发起挂钩。因此，当像recv_file或send_file这样的异步调用的操作完成时，Completion Dispatcher会调用这些Proactive IO Handler对象的适当的完成挂钩方法。2.3.3.2中的线程池的异步变种使用了前摄器模式。</p>
<p>主动对象模式（Active Object Pattern）：该模式使方法调用与方法执行去耦合，允许方法并发地运行[15]。JAWS使用主动对象模式来在分离的线程控制中并发地执行客户请求。图2-8演示在JAWS上下文中的主动对象模式的结构。</p>
<p>图2-8 JAWS中主动对象模式的结构</p>
<p>Protocol Handler（协议处理器）发出请求给Scheduler（调度器），后者将请求方法（比如 HTTP请求）转换为存储在Activation Queue（启用队列）中的Method Object（方法对象）。运行在与客户分离的线程中的Scheduler使这些Method Object出队，并将它们转换回方法调用，以执行指定的协议。在2.3.3.2描述的Thread-per-Request、线程池，以及Thread-per-Session并发模型中使用了主动对象模式。</p>
<p>服务配置器模式（Service Configurator Pattern）：该模式使系统中个体组件的实现与它们被配置进系统的时间去耦合。JAWS使用服务配置器模式来在安装时或运行时动态地优化、控制及重配置Web服务器策略的行为[25]。图2-9演示在协议流水线过滤器（Protocol Pipeline Filter）和缓存策略（Caching Strategy）的上下文中的服务配置器模式的结构。<br />
该图描述服务配置器模式怎样动态地管理动态链接库（DLL）。这使得构架能够在运行时动态地配置服务器策略的不同实现。Filter Repository（过滤器仓库）和Cache Strategy Repository（缓存策略仓库）从Service Repository（服务仓库）继承功能。同样地，策略实现（比如Parse Request（解析请求）和LRU Strategy（LRU策略））从模式的Service（服务）组件那里借用接口，以使仓库能动态地对它们进行管理。</p>
<p>图2-9 JAWS中服务配置器模式的结构</p>
<p>2.3.2.2 战术模式</p>
<p>Web服务器还利用了许多战术模式，比起上面描述的战略模式，它们要更为普遍和与领域无关。下列战术模式被用于JAWS中：</p>
<p>策略模式（Strategy Pattern）：该模式定义一个算法族，对其中的每个算法进行封装，并使它们成为可互换的[5]。JAWS大量地使用此模式来有选择地配置不同的缓存替换策略，而又不影响Web服务器的核心软件体系结构。</p>
<p>适配器模式（Adapter Pattern）：该模式将不兼容的接口转换为可由客户使用的接口[5]。JAWS 在它的I/O策略构架中使用此模式，以统一封装同步、异步和反应式I/O操作。</p>
<p>状态模式（State Pattern）：该模式定义一种合成对象，其行为取决于其状态[5]。JAWS中的 Event Dispatcher使用状态模式来无缝地支持不同的并发策略，以及同步和异步I/O。</p>
<p>单体模式（Singleton Pattern）：该模式确保一个类只有一个实例，并提供一个对它进行访问的全局访问点[5]。JAWS使用单体来确保它的缓存式虚拟文件系统只有一份拷贝存在于Web服务器进程中。</p>
<p>相对于早先描述的战略模式，战术模式对软件设计有着相对局部的影响。例如，单体是一种战术模式，常常用于统一Web服务器中特定的可全局访问的资源。尽管此模式是领域无关的、因而也是可广泛应用的，它所解决的问题并不像战略模式（比如主动对象和反应堆）那样普遍而深入地影响Web服务器软件体系结构。但是，要实现高度灵活、能良好地响应应用需求和平台特性的变化的软件，必须全面理解战术模式。<br />
这一部分的余下部分讨论JAWS的用于并发、I/O、协议流水线处理和文件缓存的构架的结构。对于每一个构架，我们描述关键的设计挑战、并概述可选方案策略的范围。随后，我们解释各个JAWS构架是怎样被结构、以支持可选策略方案的配置的。</p>
<p>2.3.3 并发策略</p>
<p>2.3.3.1 设计挑战</p>
<p>并发策略会显著地影响Web系统的设计和性能。对现有Web服务器（包括Roxen、Apache、PHTTPD、Zeus、Netscape 和Java Web服务器）的实验研究[3]表明大部分与I/O无关的Web服务器开销来自Web服务器的并发策略。关键的开销包括同步、线程/进程创建，以及上下文切换。因此，选择高效的并发策略对于获取高性能来说是至关紧要的。</p>
<p>2.3.3.2 可选策略方案</p>
<p>选择正确的并发策略并非无关紧要的事情。影响决策的有动态和静态两种因素。静态因素可被预先确定。这些因素包括硬件配置（例如，处理器数目、内存数量，以及网络连接速度）、OS平台（例如，线程和异步I/O的可用性），以及Web服务器使用情况（例如，数据库连接、图像服务器，或是HTML服务器）。动态因素是那些在系统执行过程中发生的可检测和可度量的情况。这些因素包括机器负载、并发请求数、动态内存的使用，以及服务器工作负载。<br />
现有的Web服务器使用了广泛的并发策略来回应有关的众多因素。这些策略包括单线程并发（例如，Roxen）、基于进程的并发（例如，Apache和Zeus），以及多线程并发（例如，Apache和JAWS）。每种策略都会产生正面和负面的效果，必须在静态和动态因素的上下文中才能加以分析和评估。这些权衡在下面总结。</p>
<p>图2-10 JAWS中的Thread-per-Request策略</p>
<p>Thread-per-Request：该模式在单独的线程控制中处理每个来自客户的请求。因而，当每个请求到达时，就会创建一个新线程来处理该请求。这种设计允许每个线程使用同步I/O机制来读写所请求的文件。图2-10在JAWS构架的上下文中演示此模式。在这里，接受器反复地等待连接，创建协议处理器，并派生新线程，以使处理器能够继续处理连接。<br />
Thread-per-Request的优点是它的简单性和它利用多处理器平台上的并行性的能力。它的主要缺点是缺乏可伸缩性、也就是，正在运行的线程的数目有可能无节制地增长，耗尽可用内存和CPU资源。因此，Thread-per-Request对于轻负载、低延迟的服务器来说是足够的。但是，它可能不适用于那些被频繁访问、执行费时任务的服务器。</p>
<p>Thread-per-Session：会话（Session）是客户向服务器做出的一系列请求。在Thread-per-Session中，所有这些请求都通过在每个客户与Web服务器进程中的单独线程之间的一个连接来提交。因此，该模型在多次请求间分摊了线程创建和连接建立开销。<br />
Thread-per-Session的资源耗费比Thread-Per-Request要少，因为它并不为每个请求派生一个单独的线程。但是，在客户的数量增长时，它还是易于无节制地消耗资源。还有，Thread-per-Session的使用要求客户和服务器都支持在多个请求间复用已建立连接的概念。例如，如果Web客户和Web服务器都遵循HTTP/1.1，就可以在它们之间使用Thread-per-Session。但是，如果客户或服务器只支持HTTP/1.0，Thread-per-Session就会退化为Thread-per-Request[26, 27]。</p>
<p>线程池（Thread Pool）：在此模型中，在Web服务器初始化过程中会预先派生一组线程。每个线程从作业队列中获取一项任务。在线程处理作业的同时，它从线程池中被移除。一旦任务完成，线程就返回池中。如图2-11所示，正被获取的作业是接受器的完成。当它完成时，线程创建协议处理器，并出借它的线程控制，以使处理器能够处理连接。<br />
线程池比Thread-per-Request的开销要少，因为线程创建的代价通过预先派生而被分摊掉了。而且，线程池所能消耗的资源的数量是有限的，因为池的大小是固定的。但是，如果池太小，它可能会被耗尽。这将导致新到来的请求被丢弃或无限期地等待。更进一步，如果池太大，资源耗费可能并不比使用Thread-per-Request更好。</p>
<p>图2-11 JAWS中的线程池策略</p>
<p>单线程（Single-Threaded）：在此模型中，所有连接和请求都由同一线程控制来处理。单线程服务器的简单实现依次对请求进行处理。通常这对于高流量的产品服务器来说是不够的，因为后续请求会被阻塞、直到轮到它们进行处理，从而产生不可接受的延迟。<br />
更为成熟的单线程实现使用异步或反应式I/O（在2.3.4描述）来并发地处理多个请求。在支持异步I/O的单处理器机器上，单线程并发策略可以比多线程方案执行得更好[1]。因为JAWS的I/O构架与它的并发构架是不相关的，我们认为单线程并发策略是线程池的池大小为1时的一种特例。</p>
<p>[1]和[3]中的实验演示了并发和时间分派策略的选择对负载条件遇到变化的Web服务器性能的影响。特别地，没有哪种服务器策略能够为所有情况都提供最佳性能。因而，服务器构架至少应该提供两种程度的自由：</p>
<p>1. 静态适配性：构架应该允许Web服务器开发者选择能最好地满足系统的静态需求的并发策略。例如，多处理器机器可能比单处理器机器更适合多线程并发。<br />
2. 动态适配性：构架应该允许它的并发策略动态地适配当前的服务器环境，以在服务器负载发生动态变化的情况下取得最佳性能。例如，为了应付意外的负载使用，有可能必须增加线程池中可用线程的数目。</p>
<p>2.3.3.3 JAWS并发策略构架</p>
<p>如上面所讨论的，没有哪种并发策略在所有情况下都能最佳地执行。但是，也不是所有平台都能够有效地使用所有可用的并发策略。为解决这些问题，JAWS并发策略构架同时支持相关于它的并发和事件分派策略的静态和动态的适配性。<br />
图2-12演示JAWS的并发策略构架的OO设计。Event Dispatcher（事件分派器）和Concurrency（并发）对象依据State（状态）模式来交互。如图中所演示的，server可以在对server-&gt;dispatch()的连续调用间改变为使用Thread-per-Connection或线程池，从而使不同的并发策略产生效果。Thread-per-Connection策略是对上面讨论的Thread-per-Request和Thread-per-Session策略的抽象。每种并发机制都使用了Task（任务）。取决于并发的选择，任务可以表示单个主动对象，或是一组主动对象。并发对象的行为遵循接受器（Acceptor）模式。这样的体系结构使得服务器开发者能够集成各种可选的并发策略。通过策略配置文件的帮助，服务器可以在运行时动态地选择不同策略，以获得最佳的性能。</p>
<p>图2-12 并发策略构架的结构</p>
<p>2.3.4 I/O策略</p>
<p>2.3.4.1 设计挑战</p>
<p>对Web服务器开发者的另一项关键挑战是设计高效的数据获取和递送策略，合起来称为I/O。围绕高效I/O的问题可以是极具挑战性的。系统开发者常常必须安排多个I/O操作、以利用硬件/软件平台上可用的并发性。例如，高性能Web服务器在并发地解析新获取的来自其他客户的请求时，应该能同时在网络上传输多个文件。<br />
特定类型的I/O操作有着与其他类型的I/O操作不同的需求。例如，涉及货币基金转账的Web事务可能需要同步地运行，也就是，用户在事务结束后才能继续其他操作。相反，访问静态信息的Web，比如基于CGI的搜索引擎查询，可以异步地运行，因为它们可以在任何时候被取消。这些不同的需求把我们引向了不同的执行I/O的策略。</p>
<p>2.3.4.2 可选策略方案</p>
<p>如上面所指出的，有多种因素影响对I/O策略的选择。Web服务器的设计可使用若干不同的I/O策略，比如同步、反应式和异步的I/O。使用这些策略的相关好处在下面讨论。</p>
<p>同步I/O策略：同步I/O描述在Web服务器进程和内核之间的I/O交互的模型。在此模型中，内核不到所请求的 I/O操作完成、部分完成或失败，就不会将线程控制返回给服务器。[1]显示在高速ATM网络上的Windows NT中，用于小文件传输的同步I/O通常执行良好。<br />
同步I/O广为UNIX服务器程序员所知，并且最容易使用（有争论的）。但是，该模型也有一些缺点。首先，它与单线程并发策略结合在一起，不可能同时执行多个同步I/O操作。其次，当使用多个线程（或进程）时，I/O请求还是有可能无限期地阻塞。因而，有限的资源（比如Socket句柄或文件描述符）可能会耗尽，使得服务器不再有响应。</p>
<p>反应式I/O策略：早期版本的UNIX只提供同步I/O。系统V UNIX引入了非阻塞式I/O，以避免阻塞问题。但是，非阻塞式I/O要求Web服务器轮询内核、以发现是否有任何输入可用[11]。反应式I/O减轻了同步I/O的阻塞问题，而又不诉诸轮询方法。在此模型中，Web服务器使用OS事件多路分离系统调用（例如，UNIX中的select，或Win32中的 WaitForMultipleObjects）来确定哪一个Socket可以执行I/O。当调用返回时，服务器可在返回的句柄上执行I/O，也就是，服务器对发生在分开的句柄上的多个事件进行反应。<br />
反应式I/O被事件驱动应用（比如X windows）广泛使用，并已被编写为反应堆（Reactor）设计模式[14]。但是除非小心地封装反应式I/O，由于管理多个I/O句柄的复杂性，这种技术很容易出错。而且，反应式I/O可能无法有效地利用多CPU。</p>
<p>异步I/O策略：异步I/O简化了一或多个线程控制中多个事件的多路分离，而又不会阻塞Web服务器。当Web服务器发起I/O操作时，内核在服务器处理其他请求的同时、异步地执行操作直到完成。例如，Windows NT中的TransmitFile操作可以异步地将整个文件从服务器传输到客户去。<br />
异步I/O的优点是Web服务器不需要在I/O请求上阻塞，因为它们是异步完成的。这使得服务器能够高效地为高I/O延迟的操作（比如大文件传输）进行伸缩。异步I/O的缺点是它在许多OS平台（特别是UNIX）上不可用。此外，编写异步程序比编写同步程序可能要更为复杂[21, 22, 28]。</p>
<p>2.3.4.3 JAWS I/O策略构架</p>
<p>[1]中的实验研究将不同的服务器策略系统地归属到多种负载条件。结果揭示出各种I/O策略在不同的负载条件下的行为也不同。而且，没有哪种I /O策略能够在所有负载条件下最优地执行。通过使I/O策略动态地适应运行时服务器环境，JAWS I/O策略构架解决了这一问题。而且，如果新的OS提供了一种定制的I/O机制（比如，异步分散/集中式I/O），有可能提供更好的性能，可以很容易地改编JAWS I/O策略构架来使用它。</p>
<p>图2-13 I/O策略构架的结构</p>
<p>图2-13演示JAWS所提供的I/O策略构架的结构。Perform Request（执行请求）是一种Filter（过滤器），派生自在2.3.5中阐释的Protocol Pipeline（协议流水线）。在此例中，Perform Request发出 I/O请求给它的InputOutput Handler（输入输出处理器）。InputOutput Handler将对它发出的I/O请求委托给InputOutput对象。<br />
JAWS构架提供派生自InputOutput的Synchronous、Asynchronous和Reactive IO组件。各种I/O策略使用适当的机制来发出请求。例如，Synchronous IO组件使用传统的阻塞式read和 write系统调用；Asynchronous IO依据前摄器模式[21]来执行请求；而Reactive IO则使用反应堆模式[14]。<br />
InputOutput组件由接受器通过相关联的流、从2.3.3描述的Task组件创建。文件操作通过2.3.6描述的Filecache Handle（文件缓存句柄）组件来执行。例如，send_file操作将由 Filecache Handle表示的文件发送给由接受器返回的流。<br />
2.3.5 协议流水线策略</p>
<p>2.3.5.1 设计挑战</p>
<p>早期的Web服务器，像NCSA最初的httpd，执行的文件处理非常少。它们只是简单地取得所请求的文件，将其内容传输给请求者。但是，现代的Web服务器除了执行文件获取，还进行数据处理。例如，HTTP/1.0协议可用于确定各种文件属性，比如文件类型（例如，文本、图像、音频或视频）、文件编码和压缩类型、文件大小，以及它的最后修改日期。这些信息通过HTTP头返回给请求者。<br />
通过引入CGI，Web服务器甚至已经能够执行更为广泛的任务，包括搜索引擎、地图生成、数据库系统连接，以及安全的商业和金融交易，等等。但是，CGI的限制是服务器必须派生新进程来扩展服务器功能。典型地，每个请求要求CGI派生它自己的进程来处理它，致使服务器成了 Process-per-Request服务器，一种性能“抑制剂”[3]。高性能Web服务器构架的挑战是：允许开发者扩展服务器功能，而又不诉诸 CGI进程。</p>
<p>2.3.5.2 可选策略方案</p>
<p>概念上，大多数Web服务器都在若干阶段中进行数据流处理或变换。例如，处理HTTP/1.0请求的诸阶段可被组织为一系列任务。这些任务涉及（1）读入请求，（2）解析请求，（3）解析请求头信息，（4）执行请求，以及（5）生成请求日志。如图2-14所示，这一系列任务构成了处理到来的请求的任务流水线（pipeline）。</p>
<p>图2-14 为HTTP请求而执行的任务流水线</p>
<p>处理HTTP/1.0请求所执行的任务有着固定的结构。因而，图2-14演示了一种静态流水线配置。对于被请求执行有限数目的处理操作的服务器扩展来说，静态配置是有用的。如果这些操作相对较少，并且已被预先了解的话，它们可以预先制作，并在服务器执行过程中直接使用。静态处理的例子包括：数据整编和数据去整编、通过自定义Web协议层进行的数据多路分离，以及编译applet代码。将静态流水线结合进服务器中，使得开发者能够扩展服务器功能，而又不求助于派生外部进程。Apache Web服务器通过使用模块（module）提供了这种类型的可扩展性；模块封装静态处理，并且动态地链接到Web服务器。<br />
但是，有些情况可能需要动态配置操作流水线。它们发生在这样的时候：Web服务器扩展涉及任意的处理流水线配置，所以数目在本质上是没有限制的。如果有大量中间的流水线组件，可以通过任意的次序排列，就有可能发生上述情况。如果对数据的操作只有在程序执行的过程中才能知道，通过组件动态地构造流水线就提供了一种经济的解决方案。有许多例子可说明动态流水线何时有用，包括：</p>
<p>高级搜索引擎：根据所提供的查询字符串，搜索引擎可以动态地构造数据过滤器。例如，像“(performance AND (NOT symphonic))”这样的查询查找含有单词“performance”、但没有单词“symphonic”的Web页面；它可被实现为由一个肯定的匹配组件和一个否定的匹配组件耦合而成的流水线。</p>
<p>图像服务器：图像服务器可以根据用户所请求的操作来动态地构造过滤器。例如，用户可以请求剪切、缩放、旋转和抖动图像。</p>
<p>自适配Web内容：Web内容可以根据最终用户的特性而动态地递送。例如，个人数字助理（PDA）接收的应该是 Web内容综述和较小的图像，而工作站可以接收全部的富含多媒体的页面。同样地，家用电脑用户可以选择屏蔽某些类型的内容。</p>
<p>现有的允许开发者动态增强Web服务器功能的解决方案不是太针对特定应用，就是太过一般化。例如，Netscape的NetDynamics整个地聚焦于Web服务器与现有数据库应用的集成。相反，基于Java的Web服务器（比如Sun的Java Server和W3C的Jigsaw）允许进行任意的服务器扩展，因为Java应用有能力动态执行任意的Java代码。但是，怎样提供可动态配置的操作流水线的问题仍然要由服务器开发者来解决。因此，开发者需要在不利用基于设计模式的应用构架所提供的好处的情况下，自己定制解决方案的设计。<br />
构造服务器来处理逻辑阶段的数据被称为管道和过滤器（Pipes and Filters）模式[23]。在该模式帮助开发者考虑怎样组织处理流水线的组件的同时，它并没有提供完成这些工作的构架。没有这样一个构架，改编自定义服务器、以高效地采用新协议特性的任务可能会太过昂贵、困难，或产生维护开销很高的代码。</p>
<p>2.3.5.3 JAWS协议流水线策略构架</p>
<p>前面的讨论激发了开发者对扩展服务器功能、而又不诉诸外部进程的需要。我们还描述了怎样将管道和过滤器模式应用于创建静态和动态的信息处理流水线。JAWS的协议流水线构架被设计用于简化编写这些流水线所需的工作。这是通过提供流水线组件的任务骨架（task skeleton）来完成的。当开发者完成流水线组件逻辑时，组件可随即与其他组件组合，以创建一条流水线。已完成组件被存储进仓库中，以使它们可在服务器运行时被访问。这使得服务器构架可以在Web服务器执行时按照需要动态地创建流水线。<br />
图2-15提供了对构架结构的演示。该图描述协议处理器（Protocol Handler），它利用协议流水线（Protocol Pipeline）来处理到来的请求。过滤器（Filter）组件派生自协议流水线，并被用作流水线组件的任务骨架。</p>
<p>图2-15 协议流水线构架的结构</p>
<p>流水线的实现者从过滤器派生来创建流水线组件。每个流水线组件的svc方法首先调用父svc，由其获取要处理的数据，并随即针对数据执行它的组件特有的逻辑。父svc调用前面组件的svc方法。因而，组件的组合产生了一条调用链，拖着数据通过流水线。这条调用链在负责获取原始输入的组件那里结束，该组件直接派生自协议流水线抽象。</p>
<p>2.3.6 文件缓存策略<br />
2.3.6.1 设计挑战</p>
<p>[3]中的结果显示访问文件系统是Web服务器的开销的重要来源。大多数分布式应用都可以从缓存中获益，Web服务器也不例外。因此，不奇怪，对Web服务器性能的研究会聚焦于怎样通过文件缓存来获得更好的性能[29, 30]。<br />
缓存是一种存储媒介，它提供比所需信息通常所在的媒介更为高效的检索。在Web服务器的情况下，缓存驻留在服务器的主内存中。因为内存是有限的资源，文件只是暂时地驻留在缓存中。因而，围绕最佳缓存性能的问题是由数量（有多少信息应被存储在缓存中）和持续时间（信息应在缓存中停留多长时间）来决定的。</p>
<p>2.3.6.2 可选策略方案</p>
<p>分配给缓存的内存大小会极大地影响数量和持续时间。如果内存不足，缓存少量大文件可能是不合需要的，因为缓存许多较少的文件能给出更好的平均性能。如果有更多的内存可用，缓存较大的文件也可能是可行的。</p>
<p>最近最少使用（LRU）缓存：这种缓存替换策略假定大多数对已缓存文件的请求都有着时间局部性（temporal locality），也就是，一个被请求的文件将很快被再度请求。因而，当把新文件插入缓存、要求移去另一个文件时，最近最少使用的文件将会被移除。该策略与提供具有临时特性的内容（比如每日新闻报告和股票报价）的Web系统有关。</p>
<p>最不经常使用（LFU）缓存：这种缓存替换策略假定已被频繁请求的文件最有可能被再度请求，这是另一种形式的时间局部性。因而，最不经常使用的缓存文件将是缓存中第一个被替换的文件。该策略与提供相对静态的内容的Web系统（比如Lexis- Nexis和其他历史事实数据库）有关。</p>
<p>提示式缓存：这种形式的缓存是在[29]中提议的。该策略源于对Web页面获取模式的分析，它们似乎表明Web页面有着空间局部性（spatial locality）。就是说，浏览一个Web页面的用户也很有可能浏览该页面中的链接。提示式缓存与“预取” （pre-fetching）有关，虽然[29]建议修改HTTP协议，以使连接的统计信息（或提示）能够被发回给请求者。此修改允许客户决定预取哪些页面。同样的统计信息还可用于使服务器确定预先缓存哪些页面。</p>
<p>结构化缓存：这种缓存了解正在缓存的数据。对于HTML页面，结构化缓存指的是存储缓存文件、以支持单个Web页面的层次浏览。因而，缓存利用Web页面中出现的结构来确定将要传输给客户的最为相关的部分（例如，页面的顶级视图）。对于带宽和主内存有限的客户，比如PDA，这有可能加快Web访问。结构化缓存与数据库中B树的使用有关，B树能够使获取查询数据所需的磁盘访问的次数最小化。</p>
<p>图2-16 缓存虚拟文件系统的结构</p>
<p>2.3.6.3 JAWS缓存式虚拟文件系统构架</p>
<p>上面描述的解决方案给出了实现文件缓存的若干策略。但是采用固定的缓存策略并不总能提供最佳的性能[31]。JAWS缓存式虚拟文件系统构架以两种方法来解决此问题。其一是使开发者很容易地将缓存替换算法和缓存策略集成进构架中。而且，通过利用策略Profile，可以动态地选择这些算法和策略，以在变化的服务器负载条件下优化性能。<br />
图2-16演示JAWS中的一些组件，它们互相协作、以构造缓存式虚拟文件系统构架。InputOutput对象对Filecache Handle进行实例化，文件交互（比如读和写）通过该句柄来进行管理。Filecache Handle引用Filecache Object，后者是由Filecache组件来管理的。Filecache Object维护在所有引用它的句柄间共享的信息，比如内存映射文件的基地址。Filecache组件是缓存虚拟文件系统构架的心脏。它通过哈希方法来管理Filecache Object，并且在选择Cache Strategy来处理文件请求时遵循状态模式。Cache Strategy组件利用策略模式来使不同的缓存算法（比如LRU和LFU）能够互相替换。<br />
2.3.7 JAWS构架回顾</p>
<p>2.2激发了对通过构架和模式来构建高性能Web服务器的需要。我们使用JAWS作为例子来演示构架和模式是怎样使程序员避开开发Web服务器软件的常见陷阱的。模式和构架共同支持集成化组件和设计抽象的复用 [4]。<br />
2.3描述怎样建构JAWS构架，以及它所提供的策略。为了清晰地说明JAWS的设计组织，我们概述了对JAWS构架有最大影响的战略和战术设计模式。最为重要的战略模式有接受器、反应堆、前摄器、主动对象和服务配置器模式，等等。策略、适配器、状态和单体模式是JAWS中所用的有影响的战术模式。<br />
这些模式被用来提供JAWS体系结构的“脚手架”。它们描述了必需的、形式为较小的组件的协作实体。从这里开始，构架的主要组件（也就是，并发策略、I/O策略、协议流水线和缓存式虚拟文件系统构架）被构建和集成进在一个骨架应用中。通过定制构架的特定子组件（例如，过滤器和缓存策略），开发者可以使用该骨架来构造专门的Web服务器软件系统。<br />
图2-17显示JAWS构架的所有模式和组件是怎样集成的。JAWS构架以下面的方式来推动高性能Web服务器的构建。首先，它提供若干预配置的并发和I/O分派模型、一个提供标准的缓存替换策略的文件缓存，以及一个用于实现协议流水线的构架。其次，JAWS中所用的模式有助于使Web服务器策略与（1）实现细节和（2）配置时间去耦合。这样的去耦合使得新策略可以很容易地集成进JAWS。最后，JAWS的设计允许服务器静态和动态地改变它的行为。例如，通过适当的策略Profile，JAWS可以适应在Web服务器执行期间所发生的不同情况。通过进行动态适配来应用这些可扩展的策略和组件，JAWS简化了高性能Web服务器的开发和配置。</p>
<p>2.4 Web服务器基准测试床和实验结果</p>
<p>2.3描述的模式和构架组件使得JAWS能够静态和动态地适应它的环境。尽管这样的灵活性是有益的，Web服务器的成功最终还是要依赖于它怎样满足Internet以及企业Intranet的性能需求。要满足这些需求，需要对影响Web服务器性能的关键因素有全面的了解。<br />
这一部分描述在系统地将不同负载条件应用于JAWS的不同配置时，我们所获得的性能结果。这些结果说明了为什么没有哪种配置能够在所有负载条件下最优地执行。这也论证了对像JAWS这样的灵活的构架的需要；这样的构架可在变化的负载条件下重配置、以获取最优性能。</p>
<p>图2-17 JAWS Web服务器构架</p>
<p>2.4.1 硬件测试床</p>
<p>我们的硬件测试床如图2-18所示。测试床由两台Micron Millennia PRO2 plus工作站组成。每台PRO2有128 MB RAM，并配有2个Pentium Pro处理器。客户机的时钟速度为200 MHZ，而服务器则为180 MHZ。此外，每台PRO2还有一块由Efficient Networks, Inc制造的ENI-155P-MF-S ATM卡，并由Orca 3.01驱动软件来驱动。两台工作站经由ATM网络相连，网络通过FORE Systems ASX-200BX运行，最大带宽为622 Mbps。但是，由于LAN竞争模式的限制，我们的测试床的最高带宽大约为120 Mbps。</p>
<p>图2-18 基准测试床概览</p>
<p>2.4.2 软件请求生成器（Software Request Generator）</p>
<p>我们使用WebSTONE[32] v2.0基准测试软件来收集客户和服务器端的测试数据。这些数据包括服务器平均吞吐量和客户平均响应时间。WebSTONE是一个标准的基准测试工具，可以生成负载请求、模拟典型的Web服务器文件访问模式。我们的实验使用 WebSTONE来为特定大小的文件生成负载及收集统计数据，以确定不同的并发和事件分派策略的影响。<br />
在此测试中所用的文件访问模式如表2-1所示。该表显示在流行的服务器上的实际负载条件，其数据来源于SPEC所指导的一项对文件访问模式的研究[33]。</p>
<p>文档大小</p>
<p>频度<br />
500字节<br />
5K字节<br />
50K字节<br />
5M字节</p>
<p>35%<br />
50%<br />
14%<br />
1%<br />
表2-1 文件访问模式</p>
<p>2.4.3 实验结果</p>
<p>下面给出的结果比较了JAWS Web服务器的若干不同的适配版本的性能。我们将讨论不同的事件分派和I/O模型对于吞吐量和响应时间的影响。为这次实验，使用了JAWS的三种适配版本。</p>
<p>1. 同步Thread-per-Request：在此适配版本中，JAWS被配置成派生一个新线程来处理每个到来的请求，并且使用同步I/O。<br />
2. 同步线程池：JAWS被配置成在使用同步I/O的同时、预派生一个线程池来处理到来的请求。<br />
3. 异步线程池：对于这种配置，JAWS被配置成在为异步I/O使用TransmitFile的同时、预先派生一个线程池来处理到来的请求。TransmitFile是Win32函数，它在网络连接上同步或异步地发送文件。</p>
<p>吞吐量被定义为每秒钟客户接收到的平均bit数。在客户基准测试软件发送HTTP请求之前，启动了一个高精度的用于吞吐量测量的定时器。只要连接在客户端一被关闭，定时器就会停止。接收到的bit数包括服务器发送的HTML头。<br />
响应时间被定义为从客户发送请求开始，到完整地接受完文件为止、客户所看到的以毫秒为单位的延迟量。它测量在发送HTTP GET请求给Web服务器之后、并且在内容开始到达客户之前，最终用户必须等待多长时间。客户基准测试软件一发送HTTP请求，用于响应时间测量的定时器就会启动；客户一完成对所请求的来自服务器的文件的接收，定时器就会停止。<br />
下面的五幅图分别是实验中所用的不同大小的文件（从500字节到5M字节，因子为10）的测试结果。这些文件大小代表在我们的实验中所测量的文件大小的“谱段”，用以揭示文件大小对性能都有什么影响。</p>
<p>2.4.3.1 吞吐量比较</p>
<p>图2-19到图2-23演示当所请求文件的大小和服务器点击率系统地增加时，吞吐量的变化情况。如我们所预期的，在每秒的连接数增长时，每个连接的吞吐量通常会退化。这源于正在被维护的同时连接数的增长，导致了每个连接吞吐量的下降。<br />
如图2-21所示，当连接负载增长时，对于较小文件，Thread-per-Request的吞吐量有可能迅速退化。相反，同步线程池实现的吞吐量退化要更为温和。这种差异的原因是Thread-per-Request导致更高的线程创建开销，因为要为每个GET请求派生一个新线程。相反，线程池策略中的线程创建开销通过在服务器开始执行时预先派生线程而分摊了。<br />
图2-19到2-23中的结果说明对于小文件（也就是，&lt; 50K字节），TransmitFile执行得异常糟糕。我们的实验表明TransmitFile的性能直接依赖于同时请求数。我们相信在繁重的服务器负载情况下（也就是，高点击率），TransmitFile被迫在内核处理到来的请求时进行等待。这创建了数目很大的同时连接，从而降低了服务器性能。<br />
但是在文件的的大小增长时，TransmitFile很快就胜过了同步分派模型。例如，在5M字节文件（在图2-23中显示）的繁重负载下，它超出下一种最为接近的模型大约40%。TransmitFile被优化以利用Windows NT内核特性，从而减少了数据拷贝和上下切换的次数。</p>
<p>2.4.3.2 响应时间比较</p>
<p>图2-19到2-23演示当所请求文件的大小和服务器点击率增加时，响应性能的变化情况。如我们所预期的，在每秒的连接数增长时，每个连接的响应时间通常也会变长。这反映出加在服务器上的额外负载，降低了它服务新客户请求的能力。<br />
和前面一样，对于小文件，TransmitFile执行得异常糟糕。但是，在文件大小增长时，相对于轻负载情况下的同步分派，它的响应时间得到了迅速的改善。</p>
<p>2.4.3.3 基准测试结果总结</p>
<p>如这一部分中的结果所示，取决于并发和事件分派机制，吞吐量和响应时间有着显著的变化。对于小文件，同步线程池策略提供了更好的整体性能。在中等负载下，同步事件分派模型提供的响应时间要略微优于异步模型。但是，在传输大文件的繁重负载情况下，使用TransmistFile的异步模型提供了更好的服务质量。因而，在Windows NT下，取决于服务器的工作负载和文件请求的分布，理想的Web服务器应该将自身适配到合适的事件分派和文件I/O模型。</p>
<p>图2-19 500字节文件的实验结果</p>
<p>图2-20 5K文件的实验结果</p>
<p>图2-21 50K文件的实验结果</p>
<p>图2-22 500K文件的实验结果</p>
<p>图2-23 5M文件的实验结果</p>
<p>2.4.4 用于优化Web服务器的技术总结</p>
<p>在我们的研究中，我们已经发现有可能通过更好的服务器设计来改善服务器性能（在[34]中给出了类似的观察报告）。因而，在“硬编码”服务器（也就是，使用固定并发、I/O和缓存策略的服务器）能够不可否认地提供极好的性能的同时，灵活的服务器构架，比如JAWS，并不必然与糟糕的性能相联系。<br />
这一部分总结决定Web服务器性能的最为重要的因素。这些观察报告基于我们对现有服务器设计和实现策略、以及我们调谐JAWS的经验的研究 [1, 3]。这些研究揭示了开发高性能Web服务器的主要优化目标。</p>
<p>轻量级并发：如在[3]中所看到的，基于进程的并发机制可能会产生糟糕的性能。在多处理器系统中，基于进程的并发机制可以良好地执行，特别是在进程数目与处理器数目相等时。在这种情况下，每个处理器可以运行一个Web服务器进程，从而使上下文切换开销得以最小化。<br />
通常，进程应被预先生成，以避免动态进程创建的开销。但是，更可取的方法是使用轻量级并发机制（例如，使用POSIX线程）来使上下文切换开销最小化。和进程一样，动态线程创建开销也可以通过在服务启动时将线程预先派生进线程池中来加以避免。</p>
<p>专用OS特性：OS供应商常常会提供能给出更好性能的专用编程接口。例如，Windows NT 4.0提供TransmitFile函数，使用Windows NT虚拟内存缓存管理器来获取文件数据。TransmitFile允许在文件数据之前和之后分别增加数据。这特别适用于Web服务器，因为它们通常与所请求文件一起发送HTTP头数据。因此，所有给客户的数据可以在单个的系统调用中发送，从而使模式切换开销得以最小化。<br />
通常，这些接口必须相对于标准API仔细进行基准测试，以了解特定接口给出更好性能的条件。如2.4所示，在使用TransmitFile的情况下，我们的实验数据表明，在Windows NT上通过Socket传输大文件，异步形式的TransmitFile是最为高效的机制。</p>
<p>请求生存期系统调用开销：在Web服务器中，请求生存期被定义为服务器在它从客户接收HTTP请求之后、以及在它发送出所请求文件之前，所必须执行的一系列指令。执行请求生存期所用的时间直接影响客户观察到的响应时间。因此，在此路径上使系统调用开销和其他处理最小化是很重要的。下面描述在Web服务器中可以减少这样的开销的各种地方。</p>
<p>* 减少同步：在处理并发时，常常需要通过同步来序列化对共享资源的访问（比如缓存式虚拟文件系统）。但是，使用同步会使性能恶化。因而，在请求生存期中使所获取（或释放）的锁的数目最小化是很重要的。在[3]中显示了每个请求所进行的平均锁操作数较低的服务器比进行大量锁操作的服务器执行得要好得多。</p>
<p>在某些情况下，获取和释放锁还可能导致占先（preemption）。因而，如果线程读进HTTP请求，随后试图获取一个锁，它就有可能会被占先，并可能在它被再次分派之前等待相对较长的时间。这会增加Web客户所经受的响应延迟。</p>
<p>* 缓存文件：如果服务器不进行文件缓存，至少会带来两方面的开销。首先是来自open系统调用的开销。其次，反复使用read和 write系统调用来访问文件系统会带来累积的开销，除非文件小到足以在单次调用中被获取或存储。使用在大多数形式的UNIX和Windows NT上可用的内存映射文件，可以有效地进行缓存。<br />
* 使用“集中－写”（gather-write）：在UNIX系统中，writev系统调用允许在单个系统调用中将多个缓冲区写入设备。这对于Web服务器来说是有用的，因为除了所请求的文件，典型的服务器响应还含有许多行头信息。通过使用“集中－写”，不需要在发送前将这些头的行连接进单个缓冲区，从而避免了不必要的数据复制。<br />
* 预先计算的HTTP响应：典型的HTTP请求使得服务器发回HTTP头，其中含有HTTP成功代码和所请求文件的MIME类型（例如，text/plain）。因为这样的响应是预期情况的一部分，它们可以被预先计算。当文件进入缓存时，响应的 HTTP响应也可以和文件存储在一起。于是当HTTP请求到达时，头在缓存中已直接可用了。</p>
<p>日志开销：大多数Web服务器允许管理员对他们所服务的不同页面的点击数进行日志记录。日志常常用于评估服务器在一天的不同时间里的负载情况。它还常常因为商业原因而使用，例如，网站可能基于页面的点击率来确定广告的费率。但是，因为以下原因，对HTTP请求进行日志记录会产生显著的开销：</p>
<p>* 文件系统开销：繁忙的Web服务器执行相当多的I/O调用，从而压迫文件系统和底层硬件。将数据写到日志文件会增加这样的压力，从而导致更低的性能。将日志文件和HTTP文件放置在分开的文件系统上（且在分开的物理设备上，如果可能）可以限制这一开销。<br />
* 同步开销：典型的Web服务器有多个活动线程或进程在对请求进行服务。如果这些线程/进程需要将请求记录到公用的共享日志文件，对该日志文件的访问就需要被同步，也就是，在任何时刻至多只有一个线程/进程可以对该共享日志文件进行写操作。这样的同步引入了额外的开销，从而有害于性能。通过使用多个独立的日志文件，可以减少这种开销。如果使用了内存缓冲区，它们就应该被存储在线程专有存储（thread-specific storage）中，以消除锁定竞争。<br />
* 反向主机名查找：客户的IP地址对于Web服务器来说是在本地的。但是，在日志文件中主机名通常更为有用。因而，客户的 IP地址需要被转换为相应的主机名。这通常是使用反向DNS查找来完成的。因为常常涉及网络I/O，这些查找非常昂贵。因此，它们应该被避免，或者异步地完成（使用线程或异步I/O）。<br />
* Ident查找：Ident协议[35]允许Web服务器获取给定HTTP连接的用户名。这通常涉及设置新的到用户机器的TCP/IP连接，因而也涉及了“往返旅程”（round-trip）延迟。还有，ident查找必须在HTTP连接仍在活动时执行，因此不能够“懒洋洋”地执行。因而，为获得高性能，只要可能，都应该避免进行这样的查找。</p>
<p>传输层优化：应该配置下面的传输层选项，以提高Web服务器在高速网络上的性能：</p>
<p>* 侦听backlog：大多数TCP实现都在驻留内核的“侦听队列”上缓冲到来的HTTP连接，以使服务器能够使用 accept使它们出队、进行服务。如果TCP队列超出了listen调用的“backlog”参数，新的连接就将被TCP拒绝。因而，如果预计到来的连接的流量将会很大的话，就应该通过设置更大的backlog参数（这有可能需要修改OS内核）来增大内核队列的容量。<br />
* Socket发送缓冲区：每个Socket都有一个与之相关联的发送缓冲区，该缓冲区在数据正通过网络传输时持有这些由服务器发送的数据。为获得高性能，该缓冲区的大小应被设置为所允许的最大值（也就是，大缓冲区）。在Solaris，这个限制为64K。<br />
* Nagle算法（RFC 896）：某些TCP/IP实现通过实现Nagle算法来避免拥塞（congestion）。这常常导致数据在实际通过网络发送之前、被网络层所迟滞。若干对响应时间有严格要求的应用（比如X- Windows）禁用了这一算法（例如，Solaris支持TCP_NO_DELAY Socket选项）。通过强制网络层尽可能快地发送数据，禁用这一算法可以改善响应时间。</p>
<p>2.5 结束语</p>
<p>在计算能力和网络带宽在过去十年间戏剧性增长的同时，开发通信软件所涉及的复杂性同样也发生了戏剧性增长。特别地，高性能Web服务器软件的设计和实现是昂贵而易错的。许多代价和工作都来自于对基本的设计模式和构架组件持续的重新发现和发明。而且，越来越多的硬件体系结构异种性和OS及网络平台间的差异使得从头开始构建正确、可移植和高效的Web服务器变得十分困难。<br />
构建高性能Web服务器需要了解服务器中的每个子系统（例如，并发和事件分派、服务器请求处理、文件系统访问和数据传输）对于性能的影响。高效地实现和集成这些子系统要求开发者迎接各种设计挑战，并在可选的解决方案中进行选择。领会在这些可选方案之间进行的权衡对于提供最优性能来说是必需的。但是，在需求（不可避免地）变化时，开发特定设计所需的工作常常并非是经济的。例如，性能可能被证明为不足、可能需要另外的功能，或是软件需要被移植到不同的体系结构。<br />
通过有效利用已被证明的设计模式和实现、以产生可被定制来满足新应用需求的可复用组件，面向对象应用构架和设计模式有助于减少开销、并改善软件的性能。在本论文中描述的JAWS构架演示了怎样简化和统一高性能Web服务器的开发。JAWS成功的关键是它能够捕捉常见的通信软件设计模式，并将这些模式统一进灵活的构架组件中；这些组件高效地封装并增强了低级的OS机制：并发、事件多路分离、动态配置、文件缓存，等等。这里给出的基准测试结果用于演示使用构架来开发高性能应用的有效性。它照亮了这一事实：可适应不同情况的软件与性能并非是对立的。<br />
JAWS的源码和文档可在http://www.cs.wustl.edu/~schmidt/ACE.html找到。</p>
<p>参考文献</p>
<p>[1] J. Hu, I. Pyarali, and D. C. Schmidt, “Measuring the Impact of Event Dispatching and Concurrency Models on Web Server Performance Over High-speed Networks,” in Proceedings of the 2nd Global Internet Conference, IEEE, November 1997.<br />
[2] I. Pyarali, T. H. Harrison, and D. C. Schmidt, “Design and Performance of an Object-Oriented Framework for High-Performance Electronic Medical Imaging,” USENIX Computing Systems, vol. 9, November/December 1996.<br />
[3] J. Hu, S. Mungee, and D. C. Schmidt, “Principles for Developing and Measuring High-performance Web Servers over ATM,” in Proceeedings of INFOCOM ’98, March/April 1998.<br />
[4] R. Johnson, “Frameworks = Patterns + Components,” Communications of the ACM, vol. 40, Oct. 1997.<br />
[5] E. Gamma, R. Helm, R. Johnson, and J. Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software. Reading, MA: Addison-Wesley, 1995.<br />
[6] D. C. Schmidt and T. Suda, “An Object-Oriented Framework for Dynamically Configuring Extensible Distributed Communication Systems,” IEE/BCS Distributed Systems Engineering Journal (Special Issue on Configurable Distributed Systems), vol. 2, pp. 280–293, December 1994.<br />
[7] D. C. Schmidt, “Applying Design Patterns and Frameworks to Develop Object-Oriented Communication Software,” in Handbook of Programming Languages (P. Salus, ed.), MacMillan Computer Publishing, 1997.<br />
[8] D. C. Schmidt, “A Family of Design Patterns for Application-level Gateways,” The Theory and Practice of Object Systems (Special Issue on Patterns and Pattern Languages), vol. 2, no. 1, 1996.<br />
[9] T. H. Harrison, D. L. Levine, and D. C. Schmidt, “The Design and Performance of a Real-time CORBA Event Service,” in Proceedings of OOPSLA ’97, (Atlanta, GA), ACM, October 1997.<br />
[10] D. C. Schmidt and C. Cleeland, “Applying Patterns to Develop Extensible and Maintainable ORB Middleware,” Communications of the ACM, to appear, 1998.<br />
[11] M. K. McKusick, K. Bostic, M. J. Karels, and J. S. Quarterman, The Design and Implementation of the 4.4BSD Operating System. Addison Wesley, 1996.<br />
[12] “Information Technology – Portable Operating System Interface (POSIX) – Part 1: System Application: Program Interface (API) [C Language],” 1995.<br />
[13] W. R. Stevens, UNIX Network Programming, Second Edition. Englewood Cliffs, NJ: Prentice Hall, 1997.<br />
[14] D. C. Schmidt, “Reactor: An Object Behavioral Pattern for Concurrent Event Demultiplexing and Event Handler Dispatching,” in Pattern Languages of Program Design (J.O.Coplien and D. C. Schmidt, eds.), pp. 529–545, Reading, MA: Addison-Wesley, 1995.<br />
[15] R. G. Lavender and D. C. Schmidt, “Active Object: an Object Behavioral Pattern for Concurrent Programming,” in Pattern Languages of Program Design (J. O. Coplien, J. Vlissides, and N. Kerth, eds.), Reading, MA: Addison-Wesley, 1996.<br />
[16] D. C. Schmidt, “Experience Using Design Patterns to Develop Reuseable Object-Oriented Communication Software,” Communications of the ACM (Special Issue on Object-Oriented Experiences), vol. 38, October 1995.<br />
[17] A. Stepanov and M. Lee, “The Standard Template Library,” Tech. Rep. HPL-94-34, Hewlett-Packard Laboratories, April 1994.<br />
[18] D. C. Schmidt, “ACE: an Object-Oriented Framework for Developing Distributed Applications,” in Proceedings of the 6th USENIX C++ Technical Conference, (Cambridge, Massachusetts), USENIX Association, April 1994.<br />
[19] D. C. Schmidt, “Acceptor and Connector: Design Patterns for Initializing Communication Services,” in Pattern Languages of Program Design (R. Martin, F. Buschmann, and D. Riehle, eds.), Reading, MA: Addison-Wesley, 1997.<br />
[20] P. Jain and D. C. Schmidt, “Service Configurator: A Pattern for Dynamic Configuration of Services,” in Proceedings of the 3rd Conference on Object-Oriented Technologies and Systems, USENIX, June 1997.<br />
[21] T. Harrison, I. Pyarali, D. C. Schmidt, and T. Jordan, “Proactor – An Object Behavioral Pattern for Dispatching Asynchronous Event Handlers,” in The 4th Pattern Languages of Programming Conference (Washington University technical report #WUCS-97-34), September 1997.<br />
[22] I. Pyarali, T. H. Harrison, and D. C. Schmidt, “Asynchronous Completion Token: an Object Behavioral Pattern for Efficient Asynchronous Event Handling,” in Pattern Languages of Program Design (R. Martin, F. Buschmann, and D. Riehle, eds.), Reading, MA: Addison-Wesley, 1997.<br />
[23] F. Buschmann, R. Meunier, H. Rohnert, P. Sommerlad, and M. Stal, Pattern-Oriented Software Architecture – A System of Patterns. Wiley and Sons, 1996.<br />
[24] D. C. Schmidt, “GPERF: A Perfect Hash Function Generator,” in Proceedings of the 2nd C++ Conference, (San Francisco, California), pp. 87–102, USENIX, April 1990.<br />
[25] P. Jain and D. C. Schmidt, “Service Configurator: A Pattern for Dynamic Configuration and Reconfiguration of Communication Services,” in The 3rd Pattern Languages of Programming Conference (Washington University technical report #WUCS-97-07), February 1997.<br />
[26] T. Berners-Lee, R. T. Fielding, and H. Frystyk, “Hypertext Transfer Protocol – HTTP/1.0,” Informational RFC<br />
1945, Network Working Group, May 1996. Available from http://www.w3.org/.<br />
[27] R. Fielding, J. Gettys, J. Mogul, H. Frystyk, and T. Berners-Lee, “Hypertext Transfer Protocol – HTTP/1.1,” Standards Track RFC 2068, Network Working Group, January 1997. Available from http://www.w3.org/.<br />
[28] D. C. Schmidt and C. D. Cranor, “Half-Sync/Half-Async: an Architectural Pattern for Efficient and Well-structured Concurrent I/O,” in Pattern Languages of Program Design (J. O. Coplien, J. Vlissides, and N. Kerth, eds.), Reading, MA: Addison-Wesley, 1996.<br />
[29] J. C. Mogul, “Hinted caching in the Web,” in Proceedings of the Seventh SIGOPS European Workshop: Systems Support for Worldwide Applications, 1996.<br />
[30] S. Williams, M. Abrams, C. R. Standridge, G. Abdulla, and E. A. Fox, “Removal Policies in Network Caches for World Wide Web Documents,” in Proceedings of SIGCOMM ’96, (Stanford, CA), pp. 293–305, ACM, August 1996.<br />
[31] E. P. Markatos, “Main memory caching of web documents,” in Proceedings of the Fifth International World Wide Web Conference, May 1996.<br />
[32] Gene Trent and Mark Sake, “WebSTONE: The First Generation in HTTP Server Benchmarking.” Silicon Graphics, Inc. whitepaper, February 1995. Available from http://www.sgi.com/.<br />
[33] A. Carlton, “An Explanation of the SPECweb96 Benchmark.” Standard Performance Evaluation Corporation whitepaper, 1996. Available from http://www.specbench.org/.<br />
[34] H. F. Nielsen, J. Gettys, A. Baird-Smith, E. Prud’hommeaux, H. W. Lie, and C. Lilley, “Network Performance Effects of HTTP/1.1, CSS1, and PNG,” in To appear in Proceedings of ACM SIGCOMM ’97, 1997.<br />
[35] M. S. Johns, “Identification Protocol,” Network Information Center RFC 1413, Feb. 1993.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mzfeng.com/html/y2010/320.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>谷歌放出全球前1000名网站</title>
		<link>http://www.mzfeng.com/html/y2010/318.html</link>
		<comments>http://www.mzfeng.com/html/y2010/318.html#comments</comments>
		<pubDate>Fri, 28 May 2010 14:59:21 +0000</pubDate>
		<dc:creator>mzfeng</dc:creator>
				<category><![CDATA[互联网]]></category>
		<category><![CDATA[GOOGLE]]></category>

		<guid isPermaLink="false">http://www.mzfeng.com/?p=318</guid>
		<description><![CDATA[Google今天宣布全球前1000名网站，并照此数据为广告客户推介它们的投放方案，我们总算有了Alexa之外第二个免费数据。
前十名排名如下:
1  facebook.com
2  yahoo.com
3  live.com
4  wikipedia.org
5  msn.com
6  microsoft.com
7  blogspot.com
8  baidu.com
9  qq.com
10  mozilla.com
Google自己排第几？当然是无冕之王了
查看完整排名:http://www.google.com/adplanner/static/top1000/
]]></description>
			<content:encoded><![CDATA[<p>Google今天宣布全球前1000名网站，并照此数据为广告客户推介它们的投放方案，我们总算有了Alexa之外第二个免费数据。<br />
前十名排名如下:<br />
1  facebook.com<br />
2  yahoo.com<br />
3  live.com</p>
<p>4  wikipedia.org<br />
5  msn.com<br />
6  microsoft.com<br />
7  blogspot.com<br />
8  baidu.com<br />
9  qq.com<br />
10  mozilla.com</p>
<p><span id="more-318"></span>Google自己排第几？当然是无冕之王了</p>
<p>查看完整排名:<a href="http://www.google.com/adplanner/static/top1000/" target="_blank">http://www.google.com/adplanner/static/top1000/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mzfeng.com/html/y2010/318.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
