一、IE读取XML

    var xmlDoc;
  
  xmlDoc = new ActiveXObject( "Msxml2.DOMDocument" );
  xmlDoc.loadXML(xml);
//取的节点
var points = xmlDoc.documentElement.getElementsByTagName("point");
//取得节点的内容值
points[i].childNodes[1].text



、firefox读取XML

Firefox中创建一个XML DOM,需要调用document.implementation对象的createDocument()查看有关“方法”的文章">方法。该方法接受三个参数:第一个参数是包含文档所使用的命名空间URI的字符串;第二个参数是包含文档根元素名称的字符串;第三个参数是要创建的文档类型(也称为doctype)。如果要创建空的DOM文档,则代码如下所示:

var oXmlDom = document.implementation.createDocument("", "", null);

前两个参数是空字符串,第三个参数为null,这样可以确保生成一个彻底的空文档。事实上,现在Firefox中并不提供针对文档类型的JavaScript支持,所以第三个参数总是为null。如果要创建包含文档元素的XML DOM,那么可以在第二个参数中指定标签名称:

var oXmlDom = document.implementation.createDocument("", "books", null);

这段代码创建了一个XML DOM,其documentElement是<books/>。如果要创建包含指定命名空间的DOM,可以在第一个参数中指定命名空间URI:

var oXmlDom = document.implementation.createDocument("http://www.site1.com",

       "books", null);

当在createDocument()方法中指定命名空间时, Firefox会自动附上前缀a0以表示命名空间URI:

<a0:books xmlns:a0="http://www.site1.com" />

接着,你可以通过程序来填充XML文档,不过在一般情况下,还需要在空的XML DOM对象中载入现有的XML文档。

1. 在Firefox中载入XML数据

在Firefox中,将XML载入XML DOM的方法和微软采用的方法大致相同,只存在一个显著区别:Firefox只支持load()方法。因此,在这两种浏览器中载入外部XML数据的代码是相同的:

oXmlDom.load("books.xml");

与微软的IE一样,Firefox同样实现了async属性,该属性的行为也与其一致:将async设置为
false,表示以同步模式载入文档;否则,以异步模式载入文档。

Firefox的XML DOM实现和微软的XML DOM实现还存在另一个不同,即Firefox不支持readyState属性及onreadystatechange事件处理函数。在Firefox中,支持load事件和onload事件处理函数。在文档完全载入后将触发load事件:

oXmlDom.load("books.xml");

oXmlDom.onload = function () {

    //文档完全载入后的操作

};

正如前面所说,在Firefox的XML DOM实现中,并没有loadXML()方法,不过通过Firefox中的DOMParser类可以模拟loadXML()的行为。该类有一个名为parseFromString()的方法,用来载入字符串并解析成文档:

var sXml = "<root><person><name>Jeremy McPeak</name></person></root>";

var oParser = new DOMParser();

var oXmlDom = oParser.parseFromString(sXml,"text/xml");

在这段代码中,创建了一个XML字符串,并作为参数传递给DOMParser的parseFromString()方法。parseFromString()方法的两个参数分别是XML字符串和数据的内容类型(一般设置为text/xml)。parseFromString()方法返回XML DOM对象,因此这里得到的oXmlDom与第一个例子相同。

2. 在Firefox中获取XML数据

尽管存在这样那样的不同,但IE和Firefox中用于获取文档中XML数据的大多数属性和方法是一致的。正如在IE中,可以使用documentElement属性来获取文档的根元素,例如:

var oRoot = oXmlDom.documentElement;

Firefox同样支持W3C标准属性,包括childNodes、firstChild、lastChild、nextSibling、nodeName、nodeType、nodeValue、ownerDocument、parentNode和previousSibling。不幸的是,对于微软专有的text和xml属性,Firefox并不支持,不过可以利用其他方法来模拟该属性的行为。

大家应该还记得,text属性返回了当前节点的内容,或者是当前节点及其子节点的内容。这不仅仅返回当前节点的文本,还有所有子节点的文本,因此要模拟该功能实现是十分容易的。下面这个简单的函数就能够完成该功能,该函数唯一的参数是一个节点:

function getText(oNode) {

    var sText = "";

    for (var i = 0; i < oNode.childNodes.length; i++) {

       if (oNode.childNodes[i].hasChildNodes()) {

           sText += getText(oNode.childNodes[i]);

       } else {

           sText += oNode.childNodes[i].nodeValue;

       }

    }

    return sText;

}

在getText()函数中,sText变量用来保存获取的所有文本。接着对oNode的子节点使用for循环进行遍历,检查每个子节点是否包含子节点。如果有子节点,那么就将其childNode传给getText()函数,并进行同样的处理;如果没有子节点,那么将当前节点的nodeValue加到字符串中(对文本节点而言,这只是文本字符串)。处理了所有子节点后,该函数返回变量sText。

IE中的xml属性将存放对当前节点包含的所有XML进行序列化的结果。在Firefox中,提供了一个名为XMLSerializer对象来完成这一功能。该对象提供一个使用JavaScript可访问的serializeToString()方法,使用该方法可以对XML数据进行序列化。

function serializeXml(oNode) {

    var oSerializer = new XMLSerializer();

    return oSerializer.serializeToString(oNode);

}

serializeXml()函数以XML节点作为参数,创建一个XMLSerializer对象,并将该节点传给serializeToString()方法。该方法将向调用者返回XML数据的字符串表示。

对于节点操作的DOM方法,Firefox与IE大致相同。参见“在IE中操作DOM”小节。

3. 在Firefox中处理错误

Firefox与IE的错误处理并不一样
。当IE遇到错误时,它会填充parseError对象;而当Firefox遇到错误时,它会将包含错误信息的XML文档载入到XML DOM文档中。看下面的这个例子:

var sXml = "<root><person><name>Jeremy McPeak</name></root>";

var oParser = new DOMParser();

var oXmlDom = oParser.parseFromString(sXml,"text/xml");



if (oXmlDom.documentElement.tagName != "parsererror") {

    //没有错误发生,进行所需操作

} else {

    alert("An Error Occurred");

}

在突出显示的代码行中,你会发现其中将产生一个错误:XML字符串格式不正确(因为<person>元素不完整,没有相应的</person>元素)。当载入错误的XML时,XML DOM对象将会载入一个documentElement为<parsererror/>的错误文档。我们可以通过检查documentElement的tagName属性来很容易地确定是否发生错误。如果tagName属性不是parsererror,就可以确定没有发生任何错误。

在本例中,可能会生成如下所示的错误文档:

<parsererror xmlns="http://www.mozilla.org/newlayout/xml/parsererror.xml">XML

Parsing Error: mismatched tag. Expected: </person>.

Location: http://yoda/fooreader/test.htm

Line Number 1, Column 43:<sourcetext><root><person><name>Jeremy

McPeak</name></root>

------------------------------------------^</sourcetext></parsererror>

所有的错误信息都包含在错误文档的文本中。如果要通过程序使用这些错误信息,那么首先就要对其进行解析。最简单的方法是使用一个稍长的正则表达式:

var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column

    (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;

该正则表达式将错误文档分为五个部分:错误消息、发生错误的文件名、行号、该行中发生错误的位置,以及发生错误的源代码。使用正则表达式对象的test()方法可以使用这些信息:

if (oXmlDom.firstChild.tagName != "parsererror") {

    //没有错误发生,进行所需操作

} else {

    var oXmlSerializer = new XMLSerializer();

    var sXmlError = oXmlSerializer.serializeToString(oXmlDom);

    var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column

       (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;

    reError.test(sXmlError);

正则表达式捕获到的第一部分数据是错误消息,第二部分是文件名,第三部分是行号,第四部分是行内位置,第五部分是源码。你可以使用这些解析后的信息来创建自定义的错误消息:

var str = "An error occurred!!\n" +

    "Description: " + RegExp.$1 + "\n" +

    "File: " + RegExp.$2 + "\n" +

    "Line: " + RegExp.$3 + "\n" +

    "Line Position: " + RegExp.$4 + "\n" +

    "Source Code: " + RegExp.$5;



alert(str);

style="font-family: 宋体;">如果发生错误,那么alert()方法会以易于阅读的格式在警告框中来显示相关的错误信息。
查看有关“网站”的文章">网站怎么做,才会成功呢?从个人的经验和思考,认为有以下几点:

1、做一个为顾客创造价值的网站

网站建设的目标,毫无疑问,是为顾客提供方便和价值。在顾客使用了你的网站后,是否赞好,才是网  
站建设者真正要关注的地方。一个优秀的网站,是一个为顾客提供价值的网站,是不愁推广的,顾客使用了你的网站后,会把网站记住,同时也会把网站传递给他周围的亲朋好友。

2、抓住重点和特色

百度之特色在于搜索,新浪之特色在于资讯,腾讯之特色在于及时通讯,淘宝之特色在于购物。一个网站,必须要有自己的特色。有特色才会有优势,也才会有价值。

3、做好细节,以细取胜

网站是否做好,细节是关键。一个网站,有正确的战略,有正确的方法,有正确的领导人,但未必能成功。关键还要看细节,是否做得到位。信息内的一段文 字失误,一张图片不得体,一个应用流程不能畅通,一个页面布局不够整洁或不协调,一个功能使用不够方便,都会影响顾客的使用,甚至顾客的情绪。所以,细节 是网站制胜的关键。

4、重赢利,轻排名

网站建成后,赢利是重点。大部份的人,做成网站后,就以为大功告成,便不断地做推广,提高Alexa排名,吸引更多的人来浏览。以为如此,便能获得 顾客的青睐,便能从顾客的腰包里掏出钱来。如是操作,恐怕只能赚点可怜的广告费。一个网站,在创业初期,大部分还是明确的赢利点,要抓住赢利点,不放松。 争取先赢利,先生存,再求发展。

5、坚持和专注;

网站的规模赢利非一日之寒,务必还要坚持和专注。坚持是成功之要决,我想,这是大家所共知的。在此,我想多谈一点的是专注。专注于做我们的服务,做我们的特色,做我们的产品。以此,来吸引我们的目标顾客,让他们能在我们的网站上能获得价值和好处。

6、坚持推广

网站的推广工作,是一件系统工程。从网站建立之起,就要引以为重。从网站关键字优化到搜索引擎登录,再到友情链结增加PR值,网站广告、论坛精华贴等等方法,都需要认真研究,仔细分析。才能得到比较好的效果。

在此,特别想提到是搜索引擎优化。时下,搜索引擎是引用人数最多的工具。大多数的网民,是通过搜索引擎来寻找所需信息。所以,搜索引擎优化,是一件非常重要的工作。优化工作,需落实到每个频道、每个栏目,乃至每篇文章页面。都需要仔细斟酌,方可达到比较满意的优化效果。

推广工作是一项长期的工作。各种推广方法,必须持之以恒,不懈努力,才能有望使网站积累更多的人气,留住更多的顾客,才能有望赢利。

最近公司在外面租用一台查看有关“服务器”的文章">服务器,服务器是在河南。服务器租用的猫腻我想地球人都知道,以旧抵新是常有的事。毕竟大家图都是便宜,看的过去就行了。在要求对方安装好FreeBSD7.2(还是要求mini+man+ports,忘了对分盘做出要求,对方没有合理的分盘,遗憾了。)之后,我使用SSH远程查看。最重要看了看CPU和内存、硬盘等信息。

硬盘划分查看:#df -h

内存查看:top  信息里有

CPU
#cat /var/run/dmesg.boot | grep CPU

一、Linux

查看cpu信息:

$ cat /proc/cpuinfo

二、Freebsd

大致下面几个可以显示 参考下:

dmesg 最简单的方法

freebsd# cat /var/run/dmesg.boot |grep CPU 可以查看 cpu信息

sysctl hw.model 看cpuid

sysctl machdep.tsc_freq 看cpu频率

或者直接通过ports

cd /usr/ports/misc/cpuid

make install clean

然后

可以直接通过cpuid来查看

/usr/local/bin/cpuid

查看有关“mysql”的文章">mysql和postgresql都是非常好的开源数据库,在这里我们不讨论谁优谁劣。因为简单粗暴靠几个参数去判断好坏,还是对技术的不负责。不同的生产环境和不同的应用,选择最匹配的数据库才是架构师的责任,而不是一味追求新颖、牛B,更没有必要去追求功能越多越强。

下面是一片07年的文章,尽管现在Mysql已经是5.X了,也多了事务的支持;尽管postgresql8.x了,对windows的支持也今非昔比;但是任何一个软件都有他积累过程和核心优势,我想仍然非常的借鉴意义。 如何结合自己的需求用好每一种数据库的优势,这才是一个架构师明智的选择。

适合的才是最好的。

一、前言

在这篇文章中,我们选用MySQL 4.0.2-alpha与PostgreSQL 7.2进行比较,因为MySQL 4.0.2-alpha开始支持事务的概念,因此这样的比较对于MySQL应该较为有利。

我们这样的比较不想仅仅成为一份性能测试报告,因为至少从我个人来看,对于一个数据库,稳定性和速度并不能代表一切。对于一个成熟的数据库,稳定性肯定会日益提供。而随着硬件性能的飞速提高,速度也不再是什么太大的问题。

二、两者的共同优势

这两个产品都属于开放源码的一员,性能和功能都在高速地提高和增强。MySQL AB的人们和PostgreSQL的开发者们都在尽可能地把各自的数据库改得越来越好,所以对于任何商业数据库使用其中的任何一个都不能算是错误的选择。

三、两者不同的背景

MySQL的背后是一个成熟的商业公司,而PostgreSQL的背后是一个庞大的志愿开发组。这使得MySQL的开发过程更为慎重,而PostgreSQL的反应更为迅速。这样的两种背景直接导致了各自固有的优点和缺点。

四、MySQL的主要优点

1、首先是速度,MySQL通常要比PostgreSQL快得多。MySQL自已也宣称速度是他们追求的主要目标之一,基于这个原因,MySQL在以前的文档中也曾经说过并不准备支持事务和触发器。但是在最新的文档中,我们看到 MySQL 4.0.2-alpha已经开始支持事务,而且在MySQL的TODO中,对触发器、约束这样的注定会降低速度的功能也列入了日程。但是,我们仍然有理由相信,MySQL将有可能一直保持速度的优势。

2、MySQL比PostgreSQL更流行,流行对于一个商业软件来说,也是一个很重要的指标,流行意味着更多的用户,意味着经受了更多的考验,意味着更好的商业支持、意味着更多、更完善的文档资料。

3、与PostgreSQL相比,MySQL更适宜在Windows环境下运行。 MySQL作为一个本地的Windows应用程序运行(在NT/Win2000/WinXP下,是一个服务),而PostgreSQL是运行在 Cygwin模拟环境下。PostgreSQL在Windows下运行没有MySQL稳定,应该是可以想象的。

4、MySQL使用了线程,而PostgreSQL使用的是进程。在不同线程之间的环境转换和访问公用的存储区域显然要比在不同的进程之间要快得多。

5、MySQL可以适应24/7运行。在绝大多数情况下,你不需要为MySQL运行任何清除程序。PostgreSQL目前仍不完全适应24/7运行,这是因为你必须每隔一段时间运行一次VACUUM。

6、MySQL在权限系统上比PostgreSQL某些方面更为完善。 PostgreSQL只支持对于每一个用户在一个数据库上或一个数据表上的INSERT、SELECT和UPDATE/DELETE的授权,而MySQL 允许你定义一整套的不同的数据级、表级和列级的权限。对于列级的权限,PostgreSQL可以通过建立视图,并确定视图的权限来弥补。MySQL还允许你指定基于主机的权限,这对于目前的PostgreSQL是无法实现的,但是在很多时候,这是有用的。

7、由于MySQL 4.0.2-alpha开始支持事务的概念,因此事务对于MySQL不再仅仅成为劣势。相反,因为MySQL保留无事务的表类型。这就为用户提供了更多的选择。

8、MySQL的MERGE表提供了一个独特管理多个表的方法。

9、MySQL的myisampack可以对只读表进行压缩,此后仍然可以直接访问该表中的行。

五、PostgreSQL的主要优点:

1、对事务的支持与MySQL相比,经历了更为彻底的测试。对于一个严肃的商业应用来说,事务的支持是不可或缺的。

2、MySQL对于无事务的MyISAM表。采用表锁定,一个长时间运行的查询很可能会长时间地阻碍对表的更新。而PostgreSQL不存在这样的问题。

3、PostgreSQL支持存储过程,而目前MySQL不支持,对于一个严肃的商业应用来说,作为数据库本身,有众多的商业逻辑的存在,此时使用存储过程可以在较少地增加数据库服务器的负担的前提下,对这样的商业逻辑进行封装,并可以利用数据库服务器本身的内在机制对存储过程的执行进行优化。此外存储过程的存在也避免了在网络上大量的原始的SQL语句的传输,这样的优势是显而易见的。

4、对视图的支持,视图的存在同样可以最大限度地利用数据库服务器内在的优化机制。而且对于视图权限的合理使用,事实上可以提供行级别的权限,这是MySQL的权限系统所无法实现的。

5、对触发器的支持,触发器的存在不可避免的会影响数据库运行的效率,但是与此同时,触发器的存在也有利于对商业逻辑的封装,可以减少应用程序中对同一商业逻辑的重复控制。合理地使用触发器也有利于保证数据的完整性。

6、对约束的支持。约束的作用更多地表现在对数据完整性的保证上,合理地使用约束,也可以减少编程的工作量。

7、对子查询的支持。虽然在很多情况下在SQL语句中使用子查询效率低下,而且绝大多数情况下可以使用带条件的多表连接来替代子查询,但是子查询的存在在很多时候仍然不可避免。而且使用子查询的SQL语句与使用带条件的多表连接相比具有更高的程序可读性。

8、支持R-trees这样可扩展的索引类型,可以更方便地处理一些特殊数据。

9、PostgreSQL可以更方便地使用UDF(用户定义函数)进行扩展。

六、那么我究竟应该使用MySQL还是PostgreSQL

这个问题很难说得清,而且事实上除了MySQL和PostgreSQL外,使用Oracle、Sybase、Informix等也是明智的选择。如何你确定只在MySQL和PostgreSQL中进行选择,以下规则总是有效的。

1、如果你的操作系统是Windows,你应该使用MySQL。

2、如果你对数据库并不了十分了解,甚至不知道事务、存储过程等究竟是什么,你应该使用MySQL。

3、如果你的应用对数据的完整性和严肃性要求不高,但是追求处理的高速度。例如是一个论坛和社区,你应该使用MySQL。

4、你的应用是一个严肃的商业应用,对数据完整性要求很高。而且你希望对一些商业数据逻辑进行很好的封装,例如是一个网上银行,你应该使用PostgreSQL。

5、你的应用处理的是地理数据,由于R-TREES的存在,你应该使用PostgreSQL。

6、你是一个数据库内核的狂热爱好者,你甚至希望拥有你自己版本的数据库,毫无疑问,你必须使用PostgreSQL,没准下一个PostgreSQL版本中某一个模块的作者就是你。
当自己拥有一个查看有关“服务器”的文章">服务器以后,就希望把自己的博客迁到新的服务器上。

新的服务器是Centos5+nginx+php+mysql,不能再跑ASP的程序了,也就无从使用ZBLOG了。

自己不可能再花冤枉钱去买ASP虚拟主机的钱了,同时也想尝试一下PHP+MYSQL的博客程序。

从ASP+ACCESS迁移到PHP+MYSQL,有点麻烦。

之前之所以选择ZBLOG。有两个原因:

一、之前一直害怕mysql的数据的备份、导入、导出不方便,所以不敢选择PHP的博客程序。(现在觉得好笑)

二、受月光博客的影响,也想把自己的博客做成他的样子,每天有那么多的访问量。

使用之后发现ZBLOG确实是ASP博客里最优秀单人博客程序,良好的静态化设计,可以让搜索引擎快速的收录。尽管买的虚拟主机很烂,但竟然很少不能访问,我想静态化的作用不小。

在众多的PHP博客程序面前,我花了眼,网上有说这个好的,有说那个好的。

于是,我都下载下来体验了一把。有wordpress,bo-blog,emblog等等,都还不错。

wordpress是全球下载最多,使用量最多的PHP博客程序,但是我用了之后,不是很习惯,到不是语言的问题,而是整个用户习惯的问题。外国人设计的东西,而国内的用户习惯就是一样,而且写博客的时候加载特别慢,编辑器里,尽然没有CODE,不能加入代码,很是不方便。也需你会告诉wordpress有很多插件可以实现你要的功能,是你不知道用吧了。你说的很对,我就是不喜欢搞那么多杂七杂八的东西,我需要的是简单,能快速方便的书写博客的系统。所以,我不想选择wordpress。

Bo-blog试用之后,感觉还行,毕竟是中国人自己设计的博客系统,虽然比较简单,但是很符合我的用户习惯。再说,张宴的博客就是用的BOBLOG,访问的人挺多的,应该是款不错的博客程序。我很想把博客转到bo-blog上,可以一直在网上没有发现转换程序,找不到zblog to bo-blog的转换程序。不可能从头再来的,所以只能放弃。

emblog没有详细试用,感觉比较普通,没有什么特别吸引我的地方,一个比较普通的Php博客而已。

为了放自己的博客能顺利转到PHP博客上,我好选择了Wordpress因为网上,唯一提供的ZBLOG转PHP的就是WORDPRESS。

最后由ZBLOG顺利转换到WORDPRESS上,开始使用这款很火的程序,但最终我还是受不了了,他的用户习惯让我难以忍受。

于是,我继续寻找更适合我的PHP程序……

我想,我的博客系统,应该是简单方便的,能像ZBLOG生成真的静态页面的(这样方便搜索引擎能快速收录),而不需要太多我不要的复杂功能,也不需要多美化简单就是美……

最后,我找到现在用这个JBLOG,他第一吸引我的地方是可以生成真实的静态博客页面,而不是伪静态,这样对与服务器和搜索引擎都有好处。安装试用后,感觉真的很简单,就是一个发博客和管理评论的功能,也正好符合我的个人需求。

刚好,我又找到了wordpress转到Jblog的转换工具(这个工具不怎么样,需要自己做太多的工作,另外写文说明),于是一并转到了jblog上。

现在比较担心的JBLOG的问题是,他是一个人开发的,而是他发布时间不长,变化会比较大,可能会频繁升级。

我喜欢真实的静态化,所以我选择JBLOG了,尽管它有很多不成熟的地方,他的简单打动了我。

最后,我还打算做一个测试,我之前的博客百度收录210篇左右的静态文本在目录/post/nnn.html,我这次全部删除,生成新的article/2009-05/nnn.html的路径,我看看搜索引擎如何对待我这个网站,我现在PR是3,看搜索引擎需要多久变过来。

之前我用的是www.gisblogs.net ,我现在改成了gisblogs.net ,我设置了一个网站www.gisblogs.net让他跳转到gisblogs.net ,空间做了个错误页面,也是转到gisblogs.net ,看搜索引擎如何对待这次转换。

得出结论后,再发文与大家分享。

偶然间看到一篇云风的CSDN的讲座,让在游戏服务器方面的经验,让我突然眼前一亮:

一。引擎三大部分

基于 freebsd 的服务器
跨平台的客户端
二进制跨平台
支持 Win32 MacOs Linux Freebsd
3d 部分基于 openGL
C 语言编写底层、逻辑部分动态脚本语言
开发用相关工具
跨平台命令行工具
Windows 下的视觉编辑工具

二。服务器的设计
底层全部由 C 语言编写
逻辑层语言无关
类 COM 的模块化设计
多语言混合编程
多进程单线程结构
服务器组内各进程功能有明显的层次划分
数据和逻辑分离

三。服务器群
单一登陆点做进入系统的认证
全局数据库仅保存用户身份信息
不保持常连接
玩家可以在整个大世界中发生联系
物理上玩家分属不同服务器组管理
用户数据库各自独立,无须实时交互
虚拟世界中的距离即物理世界上的距离

四。服务器组间消息传递
避免交互性协议
游戏设计上考虑远程通讯的时间差
允许数据复制,并考虑多个副本相遇时的处理
每组服务器有唯一的数据输入输出点
海关服务
玩家的交互受游戏设计的限制
限制是为了更丰富的可能性
虚拟世界的战争、贸易以及资源分配

五。外部连接处理
多个外部接入点
国情问题:电信网通问题
特别通道:用于管理人员进入
组播
分组管理的问题
心跳控制
流水线作业
时间控制
录象回放调试(监督数据合法性)
聊天信息分离
利用广播服务器减低负载
广义聊天信息

六。时间校对
校对玩家机器和服务器组的时间
防止时间作弊
估算消息发生时刻,更流畅的完成交互动作
精确保证时间的一致性
NTP 协议的问题
Client 的不合作(区分恶意和无意)
服务器组间的时间校对
心跳控制

七。数据服务
唯一的数据储存点
使用本地文件系统
使用简单文本结构
使用简单的交互协议
物品发放服务
虚拟物品的控制
数据监控和备份

八。开发经验和教训
曾经追求大一统的设计
过分信赖 C++
设计模式滥用
数据应当文本化
应将每单个任务足够简化
不为尚不存在的需求做设计

  云风,之前我拜读过他的《我的编程感悟》,牛人一个。看过他的演讲ppt内容,正是我需要的解决的许多问题,一直搜寻这个讲座的视频。



未果,寻一连接:


http://subject.csdn.net/2009video/content-635659.html

以前零零散散的玩过,没有一个系统的理解,正好趁放假研究了一下,主要资料来自handbook。

概念

Jail是chroot机制的一种进化后的机制,可以提高更为高级和灵活的隔离和监管机制,除了文件系统监管外,还实现了设备隔离,用户隔离,系统资源隔离,使其更像是一种虚拟机机制了,与此相似的概念有linux下的openvz,以及Solaris下的Container。在下认为此类的技术会与虚拟化技术逐渐融合并逐渐集成入操作系统本身甚至硬件,最终成为新的操作系统资源分配机制(继多用户,多进程,Virtual Memory架构之后新的隔离机制)。

设计

Jail可以说是一种轻量级的虚拟机制,就我目前所了解到的资料来看,它实现了文件系统隔离,进程隔离,用户隔离,设备隔离。比较起linux下的openvz,差的地方有网络地址分配,共享库控制这两大方面,当然细节会有很大不同了。

部署

写了一大堆废话,下面才是真正开始安装使用了。

构建一个Jail,必备的几个参数有Jail的根目录,用户态程序,主机名以及IP地址,还有一个可选的dev。根据用户态程序的不同考虑可以将Jail做成完整的系统型Jail以及服务型Jail。下面搞的一种,其实个人比较感兴趣的是服务型Jail,但是handbook没有提及,资料也较少。

时至当前6.2的版本,各项脚本以及工具可以说是十分成熟了,因此也就有一个比较统一的部署和管理方式了,基本可以按照handbook来做了,具体如下:

1,构建Jail的根目录,假设建立一个名为test的Jail,放在/jail/test下。很简单,就一句命令:

#mkdir /jail/test

2,构建用户态程序,因为是完整的系统型Jail,自然这些用户态程序也就是FreeBSD的world了,make world实现:

# cd /usr/src
# make world DESTDIR=/jail/test
这里make world=make buildworld + make installworld,因此如果以前做过buildworld的话可以偷懒直接用以前build好的安装,可以节省大量时间,也就是

#make installworld DESTDIR=/jail/test
3,构建jail内系统运行需要的配置文件,也就是jail的etc了,也就一条:

# make distribution DESTDIR=/jail/test
4,修改rc.conf添加jail服务运行的必要参数,必备的有:
jail_enable="YES" # 如果设为 NO 则表示不自动启动 jail
jail_list="test" # 以空格分隔的 jail 名字列表


还需指定单个jail的必备参数:
jail_test_rootdir="/jail/test" # jail 的根目录
jail_test_hostname="jail.dawnh.net" # jail 的主机名
jail_test_ip="192.168.1.81" # jail 的 IP 地址

另外还有可选的devfs,可用于控制jail里面可以使用哪些设备

jail_test_devfs_enable="YES" # 在 jail 中挂接 devfs
jail_test_devfs_ruleset="test_ruleset" # 在 jail 中应用的devfs 规则集


至此Jail基本就建立完成了,可以启动了。

这里注意还有一点是handbook没有提到但必须做的事情,就是设置IP,前面虽然为Jail指定了IP,但这个IP似乎是指定这个Jail可以从宿主系统接受数据报的IP,要其真正起作用,还必须在宿主系统配置上这个IP才可以,一般的做法是在宿主系统的接口上设置alias,命令如下:

#ifconfig re0 inet 192.168.1.81 netmask 255.255.255.0 alias
这样才算真正完成了,然后就是启动这个jail了。

#/etc/rc.d/jail start
如果前面做的都没问题的话可以看到Jail服务正常启动。

使用

然后的问题就是怎么进到这个Jail里面去使用了。因为刚构建好的Jail类似刚安装好的FreeBSD,是一个任何服务都没启用,连root密码都为空的系统,此时只能从控制台登陆进去配置各项服务,然而这里关键的问题就是–Jail是没有控制台的!

当然不会有人傻到对这种问题束手无策,最容易想到的是直接通过宿主系统进到/jail/test/etc里去修改各种配置文件,貌似这也是大部分网上有的资料所写的办法。然而由于我玩openvz的习惯,总以为会有那么一个jailctl enter test的命令可以直接从宿主进入到jail中去,不幸的是–没有。

然而我却找到了jexec这样一个命令可以执行jail里的命令,于是就简单多了,按照安装FreeBSD系统的经验,装好后第一步就是设置root密码并开启ssh,这样才方便下面登陆进去管理嘛,于是这样做:

#jls

此命令列出当前运行的jail,这里的关键是取得这个jail的jid,因为下面要用到。我这里假设id为1

#jexec 1 passwd root

要求输入密码了,和平时该密码一样的效果。

#jexec /etc/rc.d/sshd forcestart

启动ssh

至此这个Jail就可以ssh上去管理了。

参考:http://www.wangchao.net.cn/bbsdetail_61107.html
http://www.ooso.net/archives/436

mysql 5.1支持触发器以及自定义函数接口(UDF)的特性,如果配合libmemcache以及Memcached Functions for MySQL,就能够实现memcache的自动更新。简单记录一下安装测试步骤。

安装步骤
安装memcached,这个步骤很简单,随处可见
安装mysql server 5.1RC,安装办法也很大众,不废话了
编译libmemcached,解压后安装即可./configure; make; make install
编译Memcached Functions for MySQL,在http://download.tangent.org/找一个最新的版本下载就是,./configure --with-mysql=/usr/local/mysql/bin/mysql_config --libdir=/usr/local/mysql/lib/mysql/
make
make install
接下来有两个办法让Memcached Functions for MySQL在mysql中生效
在mysql的shell中执行memcached_functions_mysql源码目录下的sql/install_functions.sql,这会把memcache function作为UDF加入mysql
运行memcached_functions_mysql源码目录下的utils/install.pl,这是一个perl脚本,作用同上一条
测试memcache function
以下测试脚本摘自memcached_functions_mysql的源码目录,有兴趣可以试试

PLAIN TEXTCODE:
drop table if exists urls;
create table urls (
  id int(3) not null,
  url varchar(64) not null default '',
  primary key (id)
  );

select memc_servers_set('localhost:11211');
select memc_set('urls:sequence', 0);

DELIMITER |

DROP TRIGGER IF EXISTS url_mem_insert;
CREATE TRIGGER url_mem_insert
BEFORE INSERT ON urls
FOR EACH ROW BEGIN
    SET NEW.id= memc_increment('urls:sequence');
    SET @mm= memc_set(concat('urls:',NEW.id), NEW.url);
END |

DELIMITER ;

insert into urls (url) values ('http://google.com');
insert into urls (url) values ('http://www.ooso.net/index.php');
insert into urls (url) values ('http://www.ooso.net/');
insert into urls (url) values ('http://slashdot.org');
insert into urls (url) values ('http://mysql.com');
select * from urls;

select memc_get('urls:1');
select memc_get('urls:2');
select memc_get('urls:3');
select memc_get('urls:4');
select memc_get('urls:5');

继续参看:
http://www.jackxiang.com/post/2628/
SOA宣称的一大优势是异构系统服务整合,最大化利用现有的,旧系统的功能。

但怎么热论的都是B/S结构的,基于WebService的系统之间的SOA解决方案呢?甚至大多都是基于java的,也有.net和java之间的,但这有什么稀奇的呢? 在SOA这个概念出来之前, B/s结构的系统之间通信,整合方法本来就很多(http,xml,soap,webservice等等),SOA只不过把这些方法归拢,并形成一个标准的模式,也即包装而已。当然SOA提出的构建系统的理念还是很值得吸取的。

问题在由,SOA强调的它最大的功能就是,异构,任何语言编写的,新的,旧的系统之间都能共享服务,数据。

那么如果是3个旧的系统(C/S结构的),分别用vb, delphi, c++ 或者其它任何语言编写的系统之间,如何通过应用SOA来让这三个旧的系统协同工作,服务,流程,数据共享呢?  如果有办法,那是否需要花费大量的时间对这些系统进行重新开发呢?

如果没有办法,或有办法太花费的代价太大,那是不是可以说,能够应用SOA这个概念进行整合的系统,其开发时必须遵守SOA的标准规范呢? 如果不遵守,将不能应用SOA, 或者说将付出很大的代价才能SOA. 那这对于那些想整合共享异构的老系统的服务的用户来说还有什么意义呢? SOA的“充分发挥,利用legacy system 服务”的这一优势又如何体现呢?

以或这里的legacy system是指的不能太老? 至少能支持web service的?
也就是说,不是任何系统的改造都能套用SOA的,但是SOA的概念里面可是说的任何系统,所有语言啊,这可是让很多客户为止狂欢的主要原因啊
B/S基本都是通过web service来干的吧?
像LZ这样几个C/S来搞SOA的,以前还真没想过。如果是不同的语言编写的话又要协同,应该要使用一种通用的数据格式了,最直接的大概是XML吧,那不又像WS一样了?
期待高人的想法出现

是啊,我们给客户吹了半天SOA,人家很感兴趣。但人家的系统都是C/S的老系统,而且用的很好,不愿意重新开发新的,只是希望能在这几个旧系统里做整合。
怎么做? 到处宣扬平台,语言无关性,但到处讨论的都是有局限性的,基于java, .net的应用。

遇到这种老式语言开发的C/S系统怎么应用呢? 会不会经过调研,预算后得出结论:在这种结构上应用SOA代价过大,因此SOA不适用!那就又和SOA的最亮点冲突了。

期待指点,谢谢!

SOA只是个名词,落到实处,异构应用的整合问题,也就是要让说不同语言的人之间能够交流,本来就没有什么灵丹妙药,只能设定出一个世界语让大家来通用。妄想扔个SOA锦囊进去,世界就马上大同了,这是天方夜谭,呵呵。

好像SOA不是一种技术吧,在我看来SOA是一种态度. 以前老的系统怎么样了.如果跑的很好又何必重新开发呢?你要做的只是把老的系统提供的功能适配成你的SOA平台能够识别的服务.

“把老的系统提供的功能适配成你的SOA平台能够识别的服务” 这句话是核心。但是怎么做呢? 我想用一些传统的,老套的办法也可能解决问题,但这是不是SOA呢? 怎么做才算的上是正宗的SOA呢。

还是SOA说了"只要你整合,共享服务了,就都属于我SOA了”

太过强调SOA的概念。其实客户关心的是如何整合原来老的系统,共享数据,提高效率。是否采用SOA和如何采用SOA不是他们关心的事情。抓住事情的本质

SOA确实就是个大忽悠,没有它之前异构系统的整合的案例照样存在,而且实施的很好

如果把SOA理解成技术,首先看SCA的C++版能不能很容易的封装旧代码,如果不能,就直接考虑数据级别的整合吧,你们可以针对数据库开发一个web service的应用然后和SOA平台进行整合


SOA的目的就是为了整合老应用系统,实现数据交互,并且,最重要的,减少耦合,降低二次开发量。
讨论少的原因是,这里许多人没有(VC,带耳非,VB)等工作经验,也没用过。怎么交流?而且,每本书上,每个人都在谈C/S维护难的问题,自然没人愿意去趟这浑水。

SOA其实也是要解决新系统和老系统的互联问题。 当然还是得通过web services. 用JBI举例, 对老的C/S结构的系统, 你需要开发一个BC作为老系统的web services接口和其他系统通信, 同时这个BC也是老系统的一个Client。这也是为什么会有很多JDBC, File, SMTP等等BC的原因

不同意这个说法,SOA不一定要通过WS 通过WS的SOA我觉得很危险,不论你是内部路由调度还是服务发布用WS接口 后期性能都将极其的低.特别是内部路由这块,服务发布用ws倒是可以考虑. 在SOA平台内部建议使用长连接去进行通信. 根据我的测试结果  简单一个报文在短连接的情况下 要比长连接的情况最少慢一个到两个数量级. 而且SOA是不暴露WS的 他暴露的仅仅是一个访问接入的接入点(服务的协议发布形式是不暴露的).应用统一通过这个接入点接入到SOA平台内,如果你直接暴露服务的协议那这个平台缺少安全性和规范性.

SOA是概念, 集成构架, 而JBI是一种实现SOA的技术。两个是不同层次的东西。 JBI是要求用SOAP进行通信, 但SOA完全可以不基于Web services, 更何况SOAP。

SOA是不暴露WS的: 我觉得SOA是一种理念, 只有一个应用才有暴露WS的问题。

至于性能,你的BC可以保持长连接, 但ESB内部还是通过消息传递(都不一定是IPC), 这也是在实施时考虑的具体优化问题

SOA是概念, 集成构架, 而JBI是一种实现SOA的技术。两个是不同层次的东西。 JBI是要求用SOAP进行通信, 但SOA完全可以不基于Web services, 更何况SOAP。

SOA是不暴露WS的: 我觉得SOA是一种理念, 只有一个应用才有暴露WS的问题。

至于性能,你的BC可以保持长连接, 但ESB内部还是通过消息传递(都不一定是IPC), 这也是在实施时考虑的具体优化问题。

RMI也可以实现SOA的,前面很多人说过,SOA只是一种架构方式.
兄弟我经常需要用到bash 的好用的快捷键,ctrl+l:清屏,相当于clear。
装了个金山词霸(当然盗版啦),发现ctrl+l:清屏没有用了,于是在软件设置里面有个朗读的快捷键也是ctrl+l,去掉了就ok了。嘻嘻
命令重定向:
在Bash命令执行中,除了有>符号,还有3种输出输入状况,分别是:
1 标准输入: 代码为0,或称为stdin,使用方式为<
2 标准输出: 代码为1,或称为stdout,使用方式为1>
3 错误输出: 代码为2,或称为stderr,使用方式为2>
>>  累加到文件中,文件累加,旧数据保留.
例:
[test @test test]# ls –al 1>list.txt 2>list.err
将显示数据正确输出到list.txt,错误的数据输出到list.err

>与>>比较,区别:

>: 将原来由屏幕输出的正确数据输出到>右边的文件或设备
>>: 将原来由屏幕输出的正确数据输出到>>右边,与>不同的是,该文件将不会被覆盖,而新的数据将以累加方式添加到文件的最后面.
/dev/null是什么呢?

答: 基本上,它有点象一个无底洞,专门收集垃圾,当您输入的任何东西导向到这个虚拟的垃圾桶,它就会凭空消失,非常有用.

例:
[test @test test]# find /-name testing 1> list_right 2> /dev/null

如果要把数据都写到同一个文件中
[test @test test]# find /-name testing 1> list_right 2>&1



          管线命令
管线命令使用的是”|”界定符号
管线命令”|”仅能处理经由前一个指令传来的正确信息,也就是标准输出(stdout)信息,对于标准错误信息并没有直接处理能力.

每个管线部分都是指令,而后一个指令的输入乃是前一个指令的输出.


常用的管线命令:
cut
语法:
[root @test /root]# cut –d “分隔字符” [-cf] fields
参数说明:
-d: 后面接的是分割字符,默认是空格符
-c: 后面接的是第几个字符
-f: 后面接的是第几个区块
cut的主要用途在于将同一行里的数据进行分解,最常用在分析一些数据或文件数据的时候,因为有时候我们会以某些字符当作分割参数,然后将数据加以切割,以取得我们需要的数据(常用与分析我们的日志文件).


sort
语法:
[root @test /root]# sort [-t 分隔符] [(+起始)(-结束)][-nru]

参数说明:
-t 分隔符: 使用分隔符隔开不同区块,默认是tab
+start –end: 由第start区块排序到end区块
-n: 使用纯数字排序(否则会以字母方式排序)
-r: 反向排序
-u: 相同出现的一行,只列出一次

[root @test /root]# cat /etc/passwd | sort
将列出来的个人帐号排序


wc
语法:
[root @test /root]#  wc [-lmw]

参数说明:
-l: 多少行
-m: 多少符号
-w: 多少字

例:
[root @test /root]# cat /etc/passwd | wc –l
这个文件里有多少行.


uniq
语法:
[root @test /root]#uniq

uniq删除重复的行从而只显示一个



tee
例:
[root @test /root]# last | tee last.list | cut –d “ ” –fi
使用tee,会将数据同时传给下一个命令执行,也会将数据写入last.list文件中



tr
语法:
[root @test /root]# tr [-ds] SET1
参数说明:
-d: 删除SET1这个字符串
-s: 取代重复的字符

例:
[root @test /root]# cat /etc/passwd | tr –d:
“:”这个符号在/etc/passwd中不见了



split
语法:
[root @test /root]# split [bl] 输入文件 输出文件前导字符
参数说明:
-b: 以文件SIZE来分
-l: 以行数来分

例:
[root @test /root]# split –l 5 /etc/passwd test
会产生testaa,testab,testac等文件
curl_close — 关闭一个curl会话
curl_copy_handle — 拷贝一个curl连接资源的所有内容和参数
curl_errno — 返回一个包含当前会话错误信息的数字编号
curl_error — 返回一个包含当前会话错误信息的字符串
curl_exec — 执行一个curl会话
curl_getinfo — 获取一个curl连接资源句柄的信息
curl_init — 初始化一个curl会话
curl_multi_add_handle — 向curl批处理会话中添加单独的curl句柄资源
curl_multi_close — 关闭一个批处理句柄资源
curl_multi_exec — 解析一个curl批处理句柄
curl_multi_getcontent — 返回获取的输出的文本流
curl_multi_info_read — 获取当前解析的curl的相关传输信息
curl_multi_init — 初始化一个curl批处理句柄资源
curl_multi_remove_handle — 移除curl批处理句柄资源中的某个句柄资源
curl_multi_select — Get all the sockets associated with the cURL extension, which can then be "selected"
curl_setopt_array — 以数组的形式为一个curl设置会话参数
curl_setopt — 为一个curl设置会话参数
curl_version — 获取curl相关的版本信息
curl_init()函数的作用初始化一个curl会话,curl_init()函数唯一的一个参数是可选的,表示一个url地址。
curl_exec()函数的作用是执行一个curl会话,唯一的参数是curl_init()函数返回的句柄。
curl_close()函数的作用是关闭一个curl会话,唯一的参数是curl_init()函数返回的句柄。
<?php
$ch = curl_init("http://www.baidu.com/");
curl_exec($ch);
curl_close($ch);
?>
curl_version()函数的作用是获取curl相关的版本信息,curl_version()函数有一个参数,不清楚是做什么的
<?php
print_r(curl_version())
?>
curl_getinfo()函数的作用是获取一个curl连接资源句柄的信息,curl_getinfo()函数有两个参数,第一个参数是curl的资源句柄,第二个参数是下面一些常量:
<?php
$ch = curl_init("http://www.baidu.com/");
print_r(curl_getinfo($ch));
?>
可选的常量包括:
CURLINFO_EFFECTIVE_URL
最后一个有效的url地址
CURLINFO_HTTP_CODE
最后一个收到的HTTP代码
CURLINFO_FILETIME
远程获取文档的时间,如果无法获取,则返回值为“-1”
CURLINFO_TOTAL_TIME
最后一次传输所消耗的时间
CURLINFO_NAMELOOKUP_TIME
名称解析所消耗的时间
CURLINFO_CONNECT_TIME
建立连接所消耗的时间
CURLINFO_PRETRANSFER_TIME
从建立连接到准备传输所使用的时间
CURLINFO_STARTTRANSFER_TIME
从建立连接到传输开始所使用的时间
CURLINFO_REDIRECT_TIME
在事务传输开始前重定向所使用的时间
CURLINFO_SIZE_UPLOAD
上传数据量的总值
CURLINFO_SIZE_DOWNLOAD
下载数据量的总值
CURLINFO_SPEED_DOWNLOAD
平均下载速度
CURLINFO_SPEED_UPLOAD
平均上传速度
CURLINFO_HEADER_SIZE
header部分的大小
CURLINFO_HEADER_OUT
发送请求的字符串
CURLINFO_REQUEST_SIZE
在HTTP请求中有问题的请求的大小
CURLINFO_SSL_VERIFYRESULT
Result of SSL certification verification requested by setting CURLOPT_SSL_VERIFYPEER
CURLINFO_CONTENT_LENGTH_DOWNLOAD
从Content-Length: field中读取的下载内容长度
CURLINFO_CONTENT_LENGTH_UPLOAD
上传内容大小的说明
CURLINFO_CONTENT_TYPE
下载内容的“Content-type”值,NULL表示服务器没有发送有效的“Content-Type: header”
curl_setopt()函数的作用是为一个curl设置会话参数。curl_setopt_array()函数的作用是以数组的形式为一个curl设置会话参数。
<?php
$ch = curl_init();
$fp = fopen("example_homepage.txt", "w");
curl_setopt($ch, CURLOPT_FILE, $fp);
$options = array(
CURLOPT_URL => 'http://www.baidu.com/',
CURLOPT_HEADER => false
);
curl_setopt_array($ch, $options);
curl_exec($ch);
curl_close($ch);
fclose($fp);
?>

本文来自: 脚本之家(www.jb51.net) 详细出处参考:http://www.jb51.net/article/16224.htm
 这次是Fotolog的经验,传说中比Flickr更大的网站,Fotolog在21台服务器上部署了51个memcached实例,总计有254G缓存空间可用,缓存了多达175G的内容,这个数量比很多网站的数据库都要大的多,原文是A Bunch of Great Strategies for Using Memcached and MySQL Better Together,我这里还是选择性的翻译以及按照我的理解补充,感谢Todd Hoff,总能给我们一些学习的案例,从这里也能看出国外技术的开放态度,不似我们,其实就那么点小九九还藏着掖着,好了,进入正题。
一、关于memcached
  还不知道这个?那你去面试的时候要吃亏了,赶紧去官方网站看一下http://www.danga.com/memcached/,另外google一下用法,硬盘总是太慢,把数据存在内存里面吧,如果你只有一台服务器,推荐用一下APC(Facebook在用)或者eaccelerator或者Xcache(国人开发的),这些产品单机效果更好,如果你需要分布式的缓存方案,那么用memcached吧。
二、memcached如何与mysql并肩作战?

    * 通过数据库分片来解决数据库写扩展的问题把数据库分片,部署到不同的服务器上,免得只有一个主服务器,写操作成为瓶颈以及可能有的“单点故障”,一般的数据库分片主要是按照业务来分,尽可能的拆分业务,不相干的都独立起来做成服务也好
    * 前端mysql和一堆memcached服务器来应付读的问题应用程序首先从memcached中获取数据,获取不到再从数据库中获得并保存在 memcached中,以前看过一篇文章说好的应用95%的数据从memcache的中获得,3%的数据从mysql的query cache中获得,剩下2%才去查表,对比一下你的应用,差距有多远?
    * 通过mysql复制(master-slave)来解决读的问题
      首先mysql数据库通过master-slave读写分离,多个slave来应对应用程序读的操作。

三、为什么不用mysql的query cache?
  我们都知道mysql有个query cache,可以缓存上次查询的结果,可实际上帮不上太多的忙,下面是mysql quety cache的不足:

    * 只能有一个实例
      意味着你能存储内容的上限就是你服务器的可用内存,一台服务器能有多少内存?你又能存多少呢?
    * 只要有写操作,mysql的query cache就失效
      只要数据库内容稍有改变,那怕改变的是其他行,mysql的query cache也会失效
    * mysql的query cache只能缓存数据库数据行
      意味着其他内容都不行,比如数组,比如对象,而memcached理论上可以缓存任何内容,甚至文件^_^

四、Fotolog的缓存技术

    * 非确定性缓存你不确定你要的数据缓存中有没有,你也不知道是不是过期了,于是你就试探性的问memcached,我要的什么什么数据你那有吗?我可不要过期的数据啊,memcached告诉你说有并且给你,你就开心了,如果没有呢,你就要从数据库或者别的地方去获取了,这是 memcached典型的应用。主要应用在:
      1.复杂的数据需要多次读取,你的数据库做了分片处理,从多个数据库中获取数据并组合起来是一个非常大的开销,你大可以把这些数据取出来之后存到memcached中
      2.mysql query cache的一个好的替代方案,这样数据库其他部门改变了,只要自己没改变就没问题(注意数据库更新的问题,后面会提到)
      3.把关系或者列表缓存起来,比如某个栏目下的多篇文章列表
      4.被多个页面调用并且获取起来很慢的数据,或者是更新很慢的数据,比如文章浏览排行榜
      5.如果cache的开销超过重新获取的开销,那么不要缓存它吧
      6.标签云和自动建议(类似google sugest)
      例如:当一个用户上传一个图片,这个用户的好友页面上都要列出这张图片来,那么把它缓存起来吧。
      潜在问题:
      memcached消耗的主要是服务器内存,对CPU消耗很小,所以Fotolog把memcached部署在他们的应用服务器上(貌似我们也是这样),他们遇到了CPU搞到90%的使用率(怎么会那么高?哪出问题了吧)、内存回收(这是个大问题)等等问题。
    * 状态缓存把应用服务的当前状态存在memcached中主要应用在:
      1.“昂贵”的操作,开销大的操作
      2.sessions会话,Flickr把session存在数据库中,个人感觉还是存memcached比较“便宜”些,如果memecached服务器down掉了,那么重新登录吧。
      3.记录用户在线信息(我们也是这样做的)
    * 确定性缓存对于某些特定数据库的全部内容,都缓存到memcached,有一个专门的应用服务来保障你要的数据都在memcached中,其他应用服务直接从memcached中获取数据而不去取数据库,因为数据库已经全部保存到memcached中并保持同步。主要应用在:
      1.读取伸展,所有的读取都从memcached中获得,数据库没有负载
      2.”永不过期“(相对的)的数据,比如行政规划数据,变动很小吧
      3.经常调用的内容
      4.用户的认证信息
      5.用户的概要信息
      6.用户的参数设置
      7.用户当前常用的媒体文件列表,比如用户的图片
      8.用户登录,不走数据库,只走memcached(个人觉得这个不太好,登录信息还是需要持久化的,用类似BDB这样效果也不错)
      使用方式:
      1.多个专门的缓存池而不是一个大的缓存服务器,多个缓存池保障了高可用性,一个缓存实例挂掉了走其他的缓存实例,所有的缓存实例挂掉了,走数据库(估计数据库抗不住^_^)
      2.所有的缓存池都用程序来维护,比如数据库有更新时,程序自动把更新后的内容同步到多个缓存实例中
      3.服务器重启之后,缓存要比网站先启动,这就意味着当网站已经启动了,所有的缓存都可用
      4.读取的请求可以负载均衡到多个缓存实例中去,高性能,高可靠性
      潜在的问题:
      1.你需要足够多的内存来存储那么多的数据
      2.数据以行记录数据,而memcached以对象来存储数据,你的逻辑要把行列的数据转换成缓存对象
      3.要维护多个缓存实例非常麻烦,Fotolog用Java/Hibernate,他们自己写了个客户端来轮询
      4.管理多个缓存实例会增加应用程序的许多开销,但这些开销相对于多个缓存得到的好处来说算不了什么
    * 主动缓存数据魔法般的出现在缓存中,当数据库中有更新的时候,缓存立马填充,更新的数据被调用的可能性更高(比如一篇新文章,看的的人当然多),是非确定性缓存的一种变形(原文是It’s non-deterministic caching with a twist.我觉得这样翻译怪怪的)。主要应用在:
      1.预填充缓存:让memcached尽可能的少调用mysql如果内容不展现的话。
      2.“预热”缓存:当你需要跨数据中心复制的时候
      使用步骤:
      1.解析数据库更新的二进制日志,发现数据库更新时对memcached也进行同样的更新
      2.执行用户自定义函数,设置触发器调用UDF更新,具体参考http://tangent.org/586/Memcached_Functions_for_MySQL.html
      3.使用BLACKHOLE策略,传说中Facebook也用mysql的Blackhole存储引擎来填充缓存,写到Blackhole的数据复制到缓存中,Facebook用这来设置数据作废以及跨国界的复制,好处是数据库的复制不走mysql,这就意味着没有二进制日志以及对CPU使用不那么多(啊?难道通过memcached 存储二进制日志,然后复制到不同的数据库?有经验的同志在这个话题上可以补充。)
    * 文件系统缓存把文件直接缓存在memcached中,哇,够BT的,减轻NFS的负担,估计只缓存那些过于热门的图片吧。
    * 部分页面内容缓存如果页面的某些部分获取起来非常费劲,以其缓存页面的原始数据还不如把页面的部分内容直接缓存起来直接调用
    * 应用程序级别的复制通过API来更新缓存,API的执行细节如下:1.一个应用把数据写到某个缓存实例,这个缓存实例把内容复制到其他缓存实例(memcached同步)
      2.自动获得缓存池地址以及实例个数
      3.同时对多个缓存实例更新
      4.如果某个缓存实例down掉了,跳到下一个实例,直到更新成功
      整个过程非常高效以及低开销
    * 其他技巧1.多节点以应对”单点故障”2.使用热备技术,当某个节点down掉了,另外一台服务自动替换成它的IP,这样客户端不用更新memcached的IP地址
      3.memcached可以通过TCP/UDP访问,持续连接可以减轻负载,系统设计成可同时承受1000个连接
      4.不同的应用服务,不同的缓存服务器群
      5.检查一下你的数据大小是否匹配你分配的缓存,更多请参考http://download.tangent.org/talks/Memcached%20Study.pdf
      6.不要考虑数据行缓存,缓存复杂的对象
      7.不要在你的数据库服务器上跑memcached,两个都是吃内存的怪兽
      8.不要被TCP延迟困扰,本地的TCP/IP对内存复制是做了优化的
      9.尽可能的并行处理数据
      10.并不是所有的memcached的客户端都是一样的,仔细研究你用的语言所对应的(好像php和memcached配合的不错)
      11.尽可能的是数据过期而不是使数据无效,memcached可以设定过期时间
      12.选择一个好的缓存标识key,比如更新的时候加上版本号
      13.把版本号存储在memcached中
这两天在做WEB SERVICE,想详细了解一下soap提交的数据,于是把$_SERVER和$_REQUEST两个数组全打在日志里,但就是没有看见POST的内容. 没法只得找了个本地抓包软件抓了下.想了一下肯定是$_REQUEST或$_POST数组都是解析过的数据,对于非a=b方式的数据无法解析,所以是空的!

今天在看XMLRPC的一文章时(http://www.programfan.com/article/2944.html),发现了 $HTTP_RAW_POST_DATA 这个变量能取到post的内容.网上有文章如下介绍



The RAW / uninterpreted HTTP POST information can be accessed with:   $GLOBALS['HTTP_RAW_POST_DATA'] This is useful in cases where the post Content-Type is not something PHP understands (such as text/xml).

意思是,由于PHP默认只识别application/x-www.form-urlencoded标准的数据类型,因此,对型如text/xml的内容无法解析为$_POST数组,故保留原型,交给$HTTP_RAW_POST_DAT来接收。
telnet到memcached服务器后有很多的命令可以使用,除了大家熟知的add、get、set、incr、decr、replace、delete等赋值命令外,还有一系列的获取服务器信息的命令,这部分命令都是以stats开头的。
用PHP的Memcache::getStats($cmd)也可以访问这些命令

常用的命令



stats
显示服务器信息、统计数据等

stats reset
清空统计数据



stats malloc
显示内存分配数据

stats maps
这个不太确定,看源代码是把/proc/self/maps的数据显示出来。这个文件的数据貌似是动态库的映射地址?

stats maps
00365000-00378000 r-xp 00000000 08:01 149004     /lib/libnsl-2.3.4.so
00378000-00379000 r--p 00012000 08:01 149004     /lib/libnsl-2.3.4.so
00379000-0037a000 rw-p 00013000 08:01 149004     /lib/libnsl-2.3.4.so
0037a000-0037c000 rw-p 0037a000 00:00 0
0070c000-00722000 r-xp 00000000 08:01 147620     /lib/ld-2.3.4.so
00722000-00723000 r--p 00015000 08:01 147620     /lib/ld-2.3.4.so
00723000-00724000 rw-p 00016000 08:01 147620     /lib/ld-2.3.4.so
00726000-0084c000 r-xp 00000000 08:01 147621     /lib/tls/libc-2.3.4.so
0084c000-0084e000 r--p 00125000 08:01 147621     /lib/tls/libc-2.3.4.so
0084e000-00850000 rw-p 00127000 08:01 147621     /lib/tls/libc-2.3.4.so
00850000-00852000 rw-p 00850000 00:00 0
00891000-0089f000 r-xp 00000000 08:01 147624     /lib/tls/libpthread-2.3.4.so
0089f000-008a0000 r--p 0000d000 08:01 147624     /lib/tls/libpthread-2.3.4.so
008a0000-008a1000 rw-p 0000e000 08:01 147624     /lib/tls/libpthread-2.3.4.so
008a1000-008a3000 rw-p 008a1000 00:00 0
008a5000-008b4000 r-xp 00000000 08:01 147628     /lib/libresolv-2.3.4.so
008b4000-008b5000 r--p 0000f000 08:01 147628     /lib/libresolv-2.3.4.so
008b5000-008b6000 rw-p 00010000 08:01 147628     /lib/libresolv-2.3.4.so
008b6000-008b8000 rw-p 008b6000 00:00 0
009c7000-009cf000 r-xp 00000000 08:01 149005     /lib/tls/librt-2.3.4.so
009cf000-009d0000 r--p 00007000 08:01 149005     /lib/tls/librt-2.3.4.so
009d0000-009d1000 rw-p 00008000 08:01 149005     /lib/tls/librt-2.3.4.so
009d1000-009db000 rw-p 009d1000 00:00 0
00d28000-00d3b000 r-xp 00000000 08:02 688822     /usr/local/sinawap/lib/libevent-1.4.so.2.0.0
00d3b000-00d3c000 rw-p 00013000 08:02 688822     /usr/local/sinawap/lib/libevent-1.4.so.2.0.0
00d3c000-00d3d000 rw-p 00d3c000 00:00 0
08048000-08052000 r-xp 00000000 08:02 905179     /usr/local/sinawap/bin/memcached
08052000-08053000 rw-p 0000a000 08:02 905179     /usr/local/sinawap/bin/memcached
08053000-08056000 rw-p 08053000 00:00 0
08499000-084ba000 rw-p 08499000 00:00 0
b7f64000-b7fa8000 rw-p b7f64000 00:00 0
bff9f000-c0000000 rw-p bff9f000 00:00 0
ffffe000-fffff000 r-xp 00000000 00:00 0



stats cachedump slab_id limit_num
显示某个slab中的前limit_num个key列表,显示格式如下
ITEM key_name [ value_length b; expire_time|access_time s]
其中,memcached 1.2.2及以前版本显示的是  访问时间(timestamp)
1.2.4以上版本,包括1.2.4显示 过期时间(timestamp)
如果是永不过期的key,expire_time会显示为服务器启动的时间

stats cachedump 7 2
ITEM copy_test1 [250 b; 1207795754 s]
ITEM copy_test [248 b; 1207793649 s]

stats slabs
显示各个slab的信息,包括chunk的大小、数目、使用情况等

stats items
显示各个slab中item的数目和最老item的年龄(最后一次访问距离现在的秒数)

stats detail [on|off|dump]
设置或者显示详细操作记录

参数为on,打开详细操作记录
参数为off,关闭详细操作记录
参数为dump,显示详细操作记录(每一个键值get、set、hit、del的次数)

stats detail dump
PREFIX copy_test2 get 1 hit 1 set 0 del 0
PREFIX copy_test1 get 1 hit 1 set 0 del 0
PREFIX cpy get 1 hit 0 set 0 del 0
memcached的服务器客户端通信并不使用复杂的XML等格式,而使用简单的基于文本行的协议。因此,通过telnet 也能在memcached上保存数据、取得数据。下面是例子。

$ telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
set foo 0 0 3     (保存命令)
bar               (数据)
STORED            (结果)
get foo           (取得命令)
VALUE foo 0 3     (数据)
bar               (数据)

delete foo

DELETED



Tencent:~ # telnet 172.24.18.5* 11211  
Trying 172.24.18.56...
Connected to 172.24.18.56.
Escape character is '^]'.
set foo 0 0 3
bar
STORED
get foo
VALUE foo 0 3
bar
END
delete foo
DELETED


清空全部Memcached的变量,shell下的Telnet操作如下:
[/usr/local/apache2/*/vhost.d]# telnet 172.25.*.70 12000
Trying 172.25.38.70...
Connected to 172.25.38.70.
Escape character is '^]'.
flush_all
OK


另辟蹊径-检查memcached中指定的key是否存在:
们都知道,memcached的协议中是没有任何一个协议提供给我们检查某个key是否存在的。但是我们可能会有这样的需求。
    一些开源的客户端提供了KeyExists()这样的方法,但是其实现原理是调用了memcached的get协议,以此来达到判断某个key是否存在的目的:能取到表示这个key存在,取不到则不存在。这样的效率是比较低的,特别是当数据包比较大的情况下。

    在不读取memcached的数据的情况下,如何高效的判断某个key是否存在呢?

    大家都知道memcached的cas(check and set)协议吧,该协议在写memcached时先判断是否有人在你之前更新过数据,如果有更新过,则此次写memcached失败。

    那我们来看一下cas的语法:

    cas key flag exptime bytes version\r\n

    其中的version是memcached内部维护的一个版本号,是个uint64_t的值,这个值是调用memcached的gets协议获得的,version从1开始,memcached刚启动的时候,节点数为0,从存储第一个节点开始,version不断累加。因此,version是不可能出现0这个情况,这点很重要,是达到我们的目的的一个关键点。

    好了,我们已经知道了cas的用法,根据它的特性可以实现我们检查一个key是否存在的目的,聪明的读者可能已经知道该怎么做了吧。

    比如要检查foo这个key是否存在,可以构造这样的命令

  

    cas foo 0 0 1 0\r\n

    这里构造一个字节的数据包,将version字段设置成0,尝试写memcached。

    如果foo已经存在,因为它的version不可能等于0,所以memcached提示EXISTS

    如果foo不存在,memcached提示NOT_FOUND

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

    set foo 0 0 3                # 先写入
    bar
    STORED
    cas foo 0 0 1 0             # 判断foo是否存在,系统提示EXISTS
    a
    EXISTS
    delete foo                     # 将foo删除
    DELETED
    cas foo 0 0 1 0             # 判断foo是否存在,系统提示NOT_FOUND
    a
    NOT_FOUND

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

    这样,我们就知道foo这个key是否存在了。


----------------------------------------------引用-------------------------------------------------

memcached的基本设置:

-p 监听的端口
-l 连接的IP地址, 默认是本机
-d start 启动memcached服务
-d restart 重起memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-d install 安装memcached服务
-d uninstall 卸载memcached服务
-u 以的身份运行 (仅在以root运行的时候有效)
-m 最大内存使用,单位MB。默认64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25
-n 最小分配空间,key+value+flags默认是48
-h 显示帮助

mixi的设置,单台:

每台memcached服务器仅启动一个memcached进程。分配给memcached的内存为3GB,启动参数如下:

/usr/bin/memcached -p 11211 -u nobody -m 3000 -c 30720
由于使用了x86_64的操作系统,因此能分配2GB以上的内存。32位操作系统中,每个进程最多只能使用2GB内存。也曾经考虑过启动多个分配2GB以下内存的进程,但这样一台服务器上的TCP连接数就会成倍增加,管理上也变得复杂,所以mixi就统一使用了64位操作系统。

另外,虽然服务器的内存为4GB,却仅分配了3GB,是因为内存分配量超过这个值,就有可能导致内存交换(swap)。连载的第2次中前坂讲解过了memcached的内存存储“slab allocator”,当时说过,memcached启动时指定的内存分配量是memcached用于保存数据的量,没有包括“slab allocator”本身占用的内存、以及为了保存数据而设置的管理空间。因此,memcached进程的实际内存分配量要比指定的容量要大,这一点应当注意。

mixi保存在memcached中的数据大部分都比较小。这样,进程的大小要比指定的容量大很多。因此,我们反复改变内存分配量进行验证,确认了3GB的大小不会引发swap,这就是现在应用的数值。


Redhat5下利用yum安装SVN客户端

由于Redhat5自带的SVN的版本是1.4.1的,比较老,不能读取SVN1.5的库,所有要更新:
直接运行:yum update subversion
会抱错:
http://ftp.sjtu.edu.cn/centos/5/updates/i386/repodata/repomd.xml: [Errno 14] HTTP Error 403: Forbidden
将repo地址改称USTC(科大的),
即:/etc/yum.repos.d/rhel-debuginfo.repo中的所有ftp.sjtu.edu.cn改成centos.ustc.edu.cn
然后运行yum update subversion就可以了. ......
分页: 211/339 第一页 上页 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 下页 最后页 [ 显示模式: 摘要 | 列表 ]