<?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>BTMao &#187; 系统架构</title>
	<atom:link href="http://btmao.org/category/framework/feed/" rel="self" type="application/rss+xml" />
	<link>http://btmao.org</link>
	<description>B小T的幸福生活</description>
	<lastBuildDate>Thu, 06 Oct 2011 02:54:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>缓存，缓存，缓存（二）—— 言归正传说twitter</title>
		<link>http://btmao.org/2009/09/22/cacheandcache_2/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=cacheandcache_2</link>
		<comments>http://btmao.org/2009/09/22/cacheandcache_2/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 15:43:24 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[写程序]]></category>
		<category><![CDATA[系统架构]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[comet]]></category>
		<category><![CDATA[kestrel]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[varnish]]></category>

		<guid isPermaLink="false">http://btmao.org/?p=175</guid>
		<description><![CDATA[上一篇我们花了大部分的口水去说MQ，现在我们要言归正传说说twitter的架构了。 我们说到我们要应付的事情出了大量的消息要转发要处理，还有突然爆发的流量等等。解决这样的问题，思路应该是要提高服务器每秒对请求的响应数。通常我们是将Memcached作为Fragment Cache放在我们前端服务器上。当收到用户请求的时候我们的Router会去判断这样的Fragment Cache是否存在，如果存在的话则直接返回。这样的做法是有效率的，而且就memcahced而言，命中率很高，我们很难去确定请求的来源位置，所以我们不如把预先计算好的数据放在网络前端的RAM上面。 当然在这个之后我们还会有很多的问题，并且在twitter向我们展示的宏大架构中我们找到了一些有用的东西。 首先我们看看twitter用到的这些中间件。 memcached，这个就不说了。 Varnish，是取代Squid的一个HTTP缓存，也就是一个Page Cache，据说性能至少是Squid的四倍。这个数据来源也是据说挪威的在线报纸vg.no，用三台Varnish替代了12台Squid，效果还比之前要好。 Kestrel，是twitter团队开发的一个开源的MQ，持久存储效果不错，听说代码写得也很漂亮1200来行，Kestrel是基于Memcached的文本协议，并对这些协议有所优化和完善。这个东西最初是用Ruby搞的后来又在Scala上实现了一遍。Ruby下的那个版本伸缩性不强，特别是Ruby的GC（垃圾处理）不是分代的，这意味这GC在处理完一个队列之后就会把自己给kill掉，然后MQ就崩溃了。后来移植到Scala上，它有成熟的JVM GC这个机制，而且代码还可以更简要。 Comet，一种服务器push的技术，之前facebook貌似也在用。简单的说，就是Client发送一条请求，然后Server接收到之后进入一个无限循环，将Client需要的数据push到一个response里面并且刷新它，这个response并不会被关闭，而是不断的被push数据然后刷新。知道Client断开连接之后才跳出这个循环。正是这样，我们可以说，Ajax解决了单用户的响应，而Comet则在保障性能的前提下，解决了协同多用户的响应。Comet的优点是它可以随时向客户端发送数据而不是仅仅响应用户的输入请求。而且这个数据是在现有的一个单连接上面进行，所以大大降低了发送数据的延迟时间（建立链接的开销和用户发送请求的开销）。 按照twitter自己的说法，最初他cache的策略简单到无敌，有点让人蛋疼，除了在API那里有一个Page Cache之外，然后啥都没有了。不过还好他80%的流量是来自API的。后来随着发展，twitter进行了强有力的架构的建设，其中cache策略的发展也是飞速。 一、Vector Cache，直接放在Data Pool的上面。存放了tweetID和tweetID之间的关系，tweetID是序列化的64位整数。而直写式的设计保证了极高的命中率，使得程序在Data Pool中工作的效率大大的提高，并且极大程度上加大了Data Pool和上层Cache的关联。 二、再往上是一个Row Cache，存放了数据库信息，主要是用户和tweet详细信息的相互对应。同样是直写式，并且使用了一个叫做Cache-money的程序，这是一个针对rail的ActiveRecord的直写式缓存实现。Rail的ActiveRecord具有很强的灵活性，完全不亚于hibernate，而且使用简单，效率也很高。 三、接着往上依次便是用memcached做的Fragment Cache和用Varnish做的Page Cache。其中Fragment Cache是直接消费Row甚至是Vector中的数据，打包成JSON或者XML。虽然这是一个直读式的Cache，但是由于特殊的层级关系和工作特性，他的命中率依然能达到95%以上。 这样的缓存策略下，数据库的大部分压力都被转到了后端程序中，而后端程序对资源的占用较为平滑，可预估性也比较强。 另外twitter还提到要为Page Cache提供一个独立的池，理由很简单，他们希望能够为Page Cache提供一个永远不会自毁的Cache的，而是一种按时间来划分的键值模式，以致于可以根据HTTP的协议头来对数据进行切片。我不喜欢这样的方式，虽然它应该会很有用，但是当所有的流过的页面都要在留下痕迹时，情况也许就会变得不太可控。 这样的Cache的架构也有他的问题，因为底层的两个直写式的Cache总是要去修补上面直读式Cache中的数据，这必然会造成MQ的压力。但毕竟有舍才有得，或许这才是架构的魅力吧。]]></description>
			<content:encoded><![CDATA[<p><a href="http://btmao.org/2009/09/22/cacheandcache_1/">上一篇</a>我们花了大部分的口水去说MQ，现在我们要言归正传说说twitter的架构了。</p>
<p>我们说到我们要应付的事情出了大量的消息要转发要处理，还有突然爆发的流量等等。解决这样的问题，思路应该是要提高服务器每秒对请求的响应数。通常我们是将Memcached作为Fragment Cache放在我们前端服务器上。当收到用户请求的时候我们的Router会去判断这样的Fragment Cache是否存在，如果存在的话则直接返回。这样的做法是有效率的，而且就memcahced而言，命中率很高，我们很难去确定请求的来源位置，所以我们不如把预先计算好的数据放在网络前端的RAM上面。</p>
<p>当然在这个之后我们还会有很多的问题，并且在twitter向我们展示的宏大架构中我们找到了一些有用的东西。</p>
<p>首先我们看看twitter用到的这些中间件。</p>
<ol>
<li><strong>memcached</strong>，这个就不说了。</li>
<li><strong>Varnish</strong>，是取代Squid的一个HTTP缓存，也就是一个Page Cache，据说性能至少是Squid的四倍。这个数据来源也是据说挪威的在线报纸vg.no，用三台Varnish替代了12台Squid，效果还比之前要好。</li>
<li><strong>Kestrel</strong>，是twitter团队开发的一个开源的MQ，持久存储效果不错，听说代码写得也很漂亮1200来行，Kestrel是基于Memcached的文本协议，并对这些协议有所优化和完善。这个东西最初是用Ruby搞的后来又在Scala上实现了一遍。Ruby下的那个版本伸缩性不强，特别是Ruby的GC（垃圾处理）不是分代的，这意味这GC在处理完一个队列之后就会把自己给kill掉，然后MQ就崩溃了。后来移植到Scala上，它有成熟的JVM GC这个机制，而且代码还可以更简要。</li>
<li><strong>Comet</strong>，一种服务器push的技术，之前facebook貌似也在用。简单的说，就是Client发送一条请求，然后Server接收到之后进入一个无限循环，将Client需要的数据push到一个response里面并且刷新它，这个response并不会被关闭，而是不断的被push数据然后刷新。知道Client断开连接之后才跳出这个循环。正是这样，我们可以说，Ajax解决了单用户的响应，而Comet则在保障性能的前提下，解决了协同多用户的响应。Comet的优点是它可以随时向客户端发送数据而不是仅仅响应用户的输入请求。而且这个数据是在现有的一个单连接上面进行，所以大大降低了发送数据的延迟时间（建立链接的开销和用户发送请求的开销）。</li>
</ol>
<p>按照twitter自己的说法，最初他cache的策略简单到无敌，有点让人蛋疼，除了在API那里有一个Page Cache之外，然后啥都没有了。不过还好他80%的流量是来自API的。后来随着发展，twitter进行了强有力的架构的建设，其中cache策略的发展也是飞速。</p>
<p>一、<strong>Vector Cache</strong>，直接放在Data Pool的上面。存放了tweetID和tweetID之间的关系，tweetID是序列化的64位整数。而直写式的设计保证了极高的命中率，使得程序在Data Pool中工作的效率大大的提高，并且极大程度上加大了Data Pool和上层Cache的关联。</p>
<p>二、再往上是一个<strong>Row Cache</strong>，存放了数据库信息，主要是用户和tweet详细信息的相互对应。同样是直写式，并且使用了一个叫做Cache-money的程序，这是一个针对rail的ActiveRecord的直写式缓存实现。Rail的ActiveRecord具有很强的灵活性，完全不亚于hibernate，而且使用简单，效率也很高。</p>
<p>三、接着往上依次便是用memcached做的<strong>Fragment Cache</strong>和用Varnish做的<strong>Page Cache</strong>。其中Fragment Cache是直接消费Row甚至是Vector中的数据，打包成JSON或者XML。虽然这是一个直读式的Cache，但是由于特殊的层级关系和工作特性，他的命中率依然能达到95%以上。</p>
<p>这样的缓存策略下，数据库的大部分压力都被转到了后端程序中，而后端程序对资源的占用较为平滑，可预估性也比较强。</p>
<p>另外twitter还提到要为Page Cache提供一个独立的池，理由很简单，他们希望能够为Page Cache提供一个永远不会自毁的Cache的，而是一种按时间来划分的键值模式，以致于可以根据HTTP的协议头来对数据进行切片。我不喜欢这样的方式，虽然它应该会很有用，但是当所有的流过的页面都要在留下痕迹时，情况也许就会变得不太可控。</p>
<p>这样的Cache的架构也有他的问题，因为底层的两个直写式的Cache总是要去修补上面直读式Cache中的数据，这必然会造成MQ的压力。但毕竟有舍才有得，或许这才是架构的魅力吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/09/22/cacheandcache_2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>缓存，缓存，缓存（一）—— MQ</title>
		<link>http://btmao.org/2009/09/22/cacheandcache_1/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=cacheandcache_1</link>
		<comments>http://btmao.org/2009/09/22/cacheandcache_1/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 14:28:03 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[写程序]]></category>
		<category><![CDATA[系统架构]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[MQ]]></category>

		<guid isPermaLink="false">http://btmao.org/?p=158</guid>
		<description><![CDATA[今天看了twitter关于cache的策略，领略了cache的威力，抒发了一下情感。 Everything runs from memory in Web 2.0. 优化Cache的策略是为了什么，不外乎三点： 减少IO，减少传输，减少CPU计算，减少同时工作的服务器的数量。 对结果进行共享，比如搜索，通常我们将关键词和结果串化进行Cache，然后在时间范围内使用Cache来对分享服务器工作结果。 更快。这永远都是终极的目标。 通常的架构，对于Cache而言，我们有两层，最前端是一个Page Cache，然后是Memcached，最下来就是Data Pool。 这样的架构下我们能够解决大部分的问题，特别是在处理更多常态化的需求时，访问量平稳，数据提交远小于数据读取。但是这么做有瓶颈特别是对于2.0的网站，我们要应付越来越多的用户数据，要不断的缩短Page Cache的有效时间，我们还得应付更多的异常的流量爆发，于是这样的简单的策略就不顶用了。除非我们不计成本的增加我们的服务器，加大我们的带宽，但也许你的老板会说找你还不如请IDC的人吃饭。我们是架构师嘛，为了不让老板这么说，那我们就得找出策略来。 对于无穷无尽的用户数据的提交，我们通常会想到MQ。说说MQ是个什么东西。他是一种消息队列的处理方式，消息列队是分布式应用间交换数据的一种技术，队列被存在磁盘或者RAM里，队列里面是消息，消息直到它被app读走才被删除。这种机制使得app可以独立的运行，它们不必知道各自的位置和状态，执行过程中也不需要等待其他app的响应。 MQ的最上层是一个消息管理器，下面是队列，队列里存放消息。中间是通道，这里是通道是消息传递的管道，是建立在物理网络中的概念，可以说通道MQ整个概念的精华。通道通常被分为三种，消息通道，MQI，Cluster通道。消息通道是一个单向的通道，有Post, Get, Request, Server等不同的类型，一般是建立在MQ服务器与其他事务服务器之间；MQI是建立在app与MQ之间的，是双向的通道；而Cluster通道则是建立在不同的MQ服务器或者同一MQ集群下的不同消息管理器之间。 MQ的工作原理差不多可以来说。 我们先看看单个系统的情况。app1发送一条消息到MQ，并告诉它消息属于队列1，于是MQ则将消息放到队列1里面，app2便可以读取这个消息然后MQ等待app2读取后把这条消息del掉。 下面这个便要复杂一些。app1发送一条消息到MQ，并告诉它消息属于队列2，然而MQ将消息放到队列2之后发现，这个队列其实是在sysB里面的，这时候MQ会把消息放到一个特殊的传输队列中，然后我们建立一个cluster通道，这个通道更像是一个代理app，这个代理app读到数据并传输到sysB，而在确认sysB真正获取到消息之后MQ才释放掉这条消息。在这里我们意识到MQ在确保消息的准确传输，并且一条消息只有一次这样的传输。 移步：缓存，缓存，缓存（二）—— 言归正传说twitter]]></description>
			<content:encoded><![CDATA[<p>今天看了twitter关于cache的策略，领略了cache的威力，抒发了一下情感。</p>
<blockquote><p>Everything runs from memory in Web 2.0.</p></blockquote>
<p>优化Cache的策略是为了什么，不外乎三点：</p>
<blockquote><ol>
<li>减少IO，减少传输，减少CPU计算，减少同时工作的服务器的数量。</li>
<li>对结果进行共享，比如搜索，通常我们将关键词和结果串化进行Cache，然后在时间范围内使用Cache来对分享服务器工作结果。</li>
<li>更快。这永远都是终极的目标。</li>
</ol>
</blockquote>
<p>通常的架构，对于Cache而言，我们有两层，最前端是一个Page Cache，然后是Memcached，最下来就是Data Pool。<br />
<img src="http://btmao.org/wp-content/2009/09/未标题-1.jpg" alt="simple cache" title="simple cache" width="192" height="343" class="alignnone size-full wp-image-165" /><br />
这样的架构下我们能够解决大部分的问题，特别是在处理更多常态化的需求时，访问量平稳，数据提交远小于数据读取。但是这么做有瓶颈特别是对于2.0的网站，我们要应付越来越多的用户数据，要不断的缩短Page Cache的有效时间，我们还得应付更多的异常的流量爆发，于是这样的简单的策略就不顶用了。除非我们不计成本的增加我们的服务器，加大我们的带宽，但也许你的老板会说找你还不如请IDC的人吃饭。我们是架构师嘛，为了不让老板这么说，那我们就得找出策略来。</p>
<p>对于无穷无尽的用户数据的提交，我们通常会想到MQ。说说MQ是个什么东西。他是一种消息队列的处理方式，消息列队是分布式应用间交换数据的一种技术，队列被存在磁盘或者RAM里，队列里面是消息，消息直到它被app读走才被删除。这种机制使得app可以独立的运行，它们不必知道各自的位置和状态，执行过程中也不需要等待其他app的响应。</p>
<p>MQ的最上层是一个消息管理器，下面是队列，队列里存放消息。中间是通道，这里是通道是消息传递的管道，是建立在物理网络中的概念，可以说通道MQ整个概念的精华。通道通常被分为三种，消息通道，MQI，Cluster通道。消息通道是一个单向的通道，有Post, Get, Request, Server等不同的类型，一般是建立在MQ服务器与其他事务服务器之间；MQI是建立在app与MQ之间的，是双向的通道；而Cluster通道则是建立在不同的MQ服务器或者同一MQ集群下的不同消息管理器之间。</p>
<p>MQ的工作原理差不多可以来说。<br />
<img src="http://btmao.org/wp-content/2009/09/mq1.jpg" alt="mq" title="mq" width="528" height="379" class="alignnone size-full wp-image-169" /><br />
我们先看看单个系统的情况。app1发送一条消息到MQ，并告诉它消息属于队列1，于是MQ则将消息放到队列1里面，app2便可以读取这个消息然后MQ等待app2读取后把这条消息del掉。</p>
<p>下面这个便要复杂一些。app1发送一条消息到MQ，并告诉它消息属于队列2，然而MQ将消息放到队列2之后发现，这个队列其实是在sysB里面的，这时候MQ会把消息放到一个特殊的传输队列中，然后我们建立一个cluster通道，这个通道更像是一个代理app，这个代理app读到数据并传输到sysB，而在确认sysB真正获取到消息之后MQ才释放掉这条消息。在这里我们意识到MQ在确保消息的准确传输，并且一条消息只有一次这样的传输。</p>
<p>移步：<a href="http://btmao.org/2009/09/22/cacheandcache_2/">缓存，缓存，缓存（二）—— 言归正传说twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/09/22/cacheandcache_1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>从海底捞的服务流程想起的</title>
		<link>http://btmao.org/2009/03/13/from-haidilao-service/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=from-haidilao-service</link>
		<comments>http://btmao.org/2009/03/13/from-haidilao-service/#comments</comments>
		<pubDate>Fri, 13 Mar 2009 15:45:43 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[系统架构]]></category>
		<category><![CDATA[敏捷开发]]></category>
		<category><![CDATA[模式]]></category>
		<category><![CDATA[流程]]></category>

		<guid isPermaLink="false">http://www.btmao.org/?p=118</guid>
		<description><![CDATA[这是经过我的观察得出的海底捞的服务流程 从某种程度上说海底捞的服务模式是高效的。 固定服务（Fixed Service）：前端服务，用Listener来侦听事务的数据变化，请求并且在与后台通信后返回一个回馈。后台对于该事务的反馈通常都是这一个模块来处理的。另外这个模块还担负着执行事务的创建和销毁的流程。总之这个模块就是和事务直接进行接触的基础服务模块。 临时服务（Interim Service）：后台服务，该部门是处理系统底层数据的。当它收到前端服务的请求是会进行反馈供前端服务使用。 循环服务（Loop Service）：该部分通常是服务器脚本，它们有明确的智能，比如加水，加糖，换毛巾。它们循环侦听每一个事务的数据变化然后做出处理。 在整个流程中，还有一个部分是例外的请求。当固定服务忙，或者被死锁时，事务提交一个请求，这时候请求或许会被某些其他模块侦听到，应该放入一个缓冲区中最终交给固定服务去处理，以致不破坏流程]]></description>
			<content:encoded><![CDATA[<p>这是经过我的观察得出的海底捞的服务流程</p>
<p><a href="http://www.btmao.org/wp-content/uploads/2009/03/hdl-service.png"><img src="http://www.btmao.org/wp-content/uploads/2009/03/hdl-service.png" alt="hdl-service" title="hdl-service" class="alignnone size-full wp-image-119" /></a></p>
<p>从某种程度上说海底捞的服务模式是高效的。</p>
<p><strong>固定服务（Fixed Service）</strong>：前端服务，用Listener来侦听事务的数据变化，请求并且在与后台通信后返回一个回馈。后台对于该事务的反馈通常都是这一个模块来处理的。另外这个模块还担负着执行事务的创建和销毁的流程。总之这个模块就是和事务直接进行接触的基础服务模块。</p>
<p><strong>临时服务（Interim Service）</strong>：后台服务，该部门是处理系统底层数据的。当它收到前端服务的请求是会进行反馈供前端服务使用。</p>
<p><strong>循环服务（Loop Service）</strong>：该部分通常是服务器脚本，它们有明确的智能，比如加水，加糖，换毛巾。它们循环侦听每一个事务的数据变化然后做出处理。</p>
<p>在整个流程中，还有一个部分是例外的请求。当固定服务忙，或者被死锁时，事务提交一个请求，这时候请求或许会被某些其他模块侦听到，应该放入一个缓冲区中最终交给固定服务去处理，以致不破坏流程</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/03/13/from-haidilao-service/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>关于JS——架构的设计</title>
		<link>http://btmao.org/2009/03/09/jscodemodel/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=jscodemodel</link>
		<comments>http://btmao.org/2009/03/09/jscodemodel/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 12:38:24 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[系统架构]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[模式]]></category>

		<guid isPermaLink="false">http://www.btmao.org/?p=79</guid>
		<description><![CDATA[随着web技术的发展，web2.0开始成为主流，JS在整个系统中的地位越来越重要，而对于JS的优化和架构的建立也越来越受到重视。 一、为自己的系统选择一个合适的框架 prototype和Jquery都是很好的框架。 prototype是一个完全存在于底层的代码，他优化了JS的面向对象的扩展，封装了DOM操作API，很好的处理了事件，AJAX等，体积也很小。要说他的缺点，恐怕就是它本身并没有实现太多的功能。 JQuery，本身实现了很多特效，能帮助工程师完成很多工作，即便是工程师对JS并不那么熟悉。它很重视代码的简介与高效。是一个很不错的库类，鼎鼎大名的YUI都复用了很多他的代码。 选好了一个框架，之后就应该要求工程师按照框架的要求去进行开发。否则，这个框架的选择还有什么意义呢。 二、不要把只有单独的子项目才会使用的JS放在全站都会引用的.js文件里 这个几乎是毋庸置疑的。但是有时候我们需要去减少一张页面的JS文件请求数，这时候我们通常会把子类的代码直接放在基类的文件中，然后随着项目的增多，继承该基类的子类也增多，我们在下载页面的时候需要去加载的无关代码量也开始增大。于是我们在控制JS文件请求数的同时也要考虑到，我们应该如何去规划JS的目录结构。 通常我们把js放在www的js目录下或者是将站点的所有静态文件都放于http://static.yourdomain.com，其中js文件的目录是http://static.yourdomain.com/js。 而我们通常把一些全站都会用到的函数，或者一些简单的极其常用的基类定义在一个类似于global.js的文件里，然后把其他的一些跨应用的基类放在以类名为文件里并放在class/目录下，如class/ajaxlist.js，这个文件是处理ajax下生成和操作数据列表的类的代码。而对不同应用则应该有一个文件是对这些基类的实例化和逻辑处理的相关代码便放在属于他们自己的文件里然后存放于app目录，比如app/album.js是关于相册的代码。 于是，我们的HTML里面应该是这样的。 &#60;script src=&#34;http://static.yourdomain.com/js/prototype.js?124&#34;&#62;&#60;/script&#62; &#60;script src=&#34;http://static.yourdomain.com/js/global.js?326&#34;&#62;&#60;/script&#62; &#60;script src=&#34;http://static.yourdomain.com/js/class/ajaxlist.js?178&#34;&#62;&#60;/script&#62; &#60;script src=&#34;http://static.yourdomain.com/js/app/album.js?768&#34;&#62;&#60;/script&#62; 而这样的代码是很符合优化策略的 三、在HTML里为你的JS加上版本号 这是很必要的。这将利用浏览器的缓存或SQUID等来减少浏览器像服务器进行请求的次数，也将节省用户的下载时间。只要版本号不变化，浏览器就不会重新下载。 四、在用户操作前为用户做好准备工作 有一些过度的结构化的代码反而会造成负担。特别是在IE的JS执行效率还不算很高的现在看来。有时候用服务器端去处理那些没必要交给JS的数据，将完整的初始状态留给用户对用户来说可能是更好的体验。]]></description>
			<content:encoded><![CDATA[<p>随着web技术的发展，web2.0开始成为主流，JS在整个系统中的地位越来越重要，而对于JS的优化和架构的建立也越来越受到重视。</p>
<p><strong>一、为自己的系统选择一个合适的框架</strong></p>
<p>prototype和Jquery都是很好的框架。</p>
<ol>
<li>prototype是一个完全存在于底层的代码，他优化了JS的面向对象的扩展，封装了DOM操作API，很好的处理了事件，AJAX等，体积也很小。要说他的缺点，恐怕就是它本身并没有实现太多的功能。</li>
<li>JQuery，本身实现了很多特效，能帮助工程师完成很多工作，即便是工程师对JS并不那么熟悉。它很重视代码的简介与高效。是一个很不错的库类，鼎鼎大名的YUI都复用了很多他的代码。</li>
</ol>
<p>选好了一个框架，之后就应该要求工程师按照框架的要求去进行开发。否则，这个框架的选择还有什么意义呢。</p>
<p><strong>二、不要把只有单独的子项目才会使用的JS放在全站都会引用的.js文件里</strong></p>
<p>这个几乎是毋庸置疑的。但是有时候我们需要去减少一张页面的JS文件请求数，这时候我们通常会把子类的代码直接放在基类的文件中，然后随着项目的增多，继承该基类的子类也增多，我们在下载页面的时候需要去加载的无关代码量也开始增大。于是我们在控制JS文件请求数的同时也要考虑到，我们应该如何去规划JS的目录结构。</p>
<p>通常我们把js放在www的js目录下或者是将站点的所有静态文件都放于http://static.yourdomain.com，其中js文件的目录是http://static.yourdomain.com/js。</p>
<p>而我们通常把一些全站都会用到的函数，或者一些简单的极其常用的基类定义在一个类似于global.js的文件里，然后把其他的一些跨应用的基类放在以类名为文件里并放在class/目录下，如class/ajaxlist.js，这个文件是处理ajax下生成和操作数据列表的类的代码。而对不同应用则应该有一个文件是对这些基类的实例化和逻辑处理的相关代码便放在属于他们自己的文件里然后存放于app目录，比如app/album.js是关于相册的代码。</p>
<p>于是，我们的HTML里面应该是这样的。</p>

<div class="wp_syntax"><div class="code"><pre class="html">&lt;script src=&quot;http://static.yourdomain.com/js/prototype.js?124&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;http://static.yourdomain.com/js/global.js?326&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;http://static.yourdomain.com/js/class/ajaxlist.js?178&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;http://static.yourdomain.com/js/app/album.js?768&quot;&gt;&lt;/script&gt;</pre></div></div>

<p>而这样的代码是很符合优化策略的</p>
<p><strong>三、在HTML里为你的JS加上版本号</strong></p>
<p>这是很必要的。这将利用浏览器的缓存或SQUID等来减少浏览器像服务器进行请求的次数，也将节省用户的下载时间。只要版本号不变化，浏览器就不会重新下载。</p>
<p><strong>四、在用户操作前为用户做好准备工作</strong></p>
<p>有一些过度的结构化的代码反而会造成负担。特别是在IE的JS执行效率还不算很高的现在看来。有时候用服务器端去处理那些没必要交给JS的数据，将完整的初始状态留给用户对用户来说可能是更好的体验。</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/03/09/jscodemodel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP的MVC</title>
		<link>http://btmao.org/2009/02/26/mvcofphp/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=mvcofphp</link>
		<comments>http://btmao.org/2009/02/26/mvcofphp/#comments</comments>
		<pubDate>Wed, 25 Feb 2009 16:33:05 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[系统架构]]></category>
		<category><![CDATA[mvc]]></category>

		<guid isPermaLink="false">http://www.btmao.org/?p=10</guid>
		<description><![CDATA[PHP的面向对象的特性越来越完善使得，PHP能够更好的从代码结构上进行系统的封装。当一个系统，其中有大量的逻辑存在与流程控制之中，MVC的优势就开始渐渐体现。 MVC的模式要求对系统的总体结构在逻辑上分成三部分 View（界面/视图）：用户界面，网页模板 Controller（控制/流程）：系统业务流程 Model（模型/逻辑）：系统设计中的一些基础类和数据操作 拿一个简单的登陆流程当例子 最常见的登陆流程是这样的，我们假设我们的网站根目录下有一个叫做/user的文件夹来存放所有与用户操作相关的页面，其中有一个页面是/user/login.php。而我们的根目录上有文件/index.php作为网站的首页。当我们打开/index.php的时候进行判断，如果未登陆则跳转到/user/login.php进行登陆，如果成功则跳回/index.php，否则跳到/error.php。 流程图如下： 根据文字和流程图的描述，我们可以开始编码了。 /index.php &#60; ?php //... $userLib = new userLib&#40;&#41;; if &#40;!$userLib-&#62;chkLogin&#40;&#41;&#41; header&#40;'location: /user/login.php'&#41;; //... ?&#62; /user/login.php &#60; ?php //... if &#40;isset&#40;$_POST&#91;'submit'&#93;&#41;&#41; &#123; $userLib = new userLib&#40;&#41;; $succ = $userLib-&#62;login&#40;$_POST&#91;'name'&#93;, $_POST&#91;'pass'&#93;&#41;; header&#40;'location: '.&#40;$succ?'/index.php':'/error.php'&#41;&#41;; &#125; $tpl = new Template&#40;&#41;; $tpl-&#62;show&#40;'user_login.tpl'&#41;; ?&#62; /error.php &#60; ?php $tpl = new Template&#40;&#41;; $tpl-&#62;show&#40;'error.tpl'&#41;; [...]]]></description>
			<content:encoded><![CDATA[<p>PHP的面向对象的特性越来越完善使得，PHP能够更好的从代码结构上进行系统的封装。当一个系统，其中有大量的逻辑存在与流程控制之中，MVC的优势就开始渐渐体现。</p>
<p>MVC的模式要求对系统的总体结构在逻辑上分成三部分</p>
<ol>
<li>View（界面/视图）：用户界面，网页模板</li>
<li>Controller（控制/流程）：系统业务流程</li>
<li>Model（模型/逻辑）：系统设计中的一些基础类和数据操作</li>
</ol>
<p><strong>拿一个简单的登陆流程当例子</strong></p>
<p>最常见的登陆流程是这样的，我们假设我们的网站根目录下有一个叫做/user的文件夹来存放所有与用户操作相关的页面，其中有一个页面是/user/login.php。而我们的根目录上有文件/index.php作为网站的首页。当我们打开/index.php的时候进行判断，如果未登陆则跳转到/user/login.php进行登陆，如果成功则跳回/index.php，否则跳到/error.php。</p>
<p>流程图如下：</p>
<p><img class="alignnone size-full wp-image-12" title="一个简单的登陆流程" src="http://www.btmao.org/wp-content/uploads/2009/02/e69caae6a087e9a298-1.jpg" alt="一个简单的登陆流程" width="451" height="339" /></p>
<p>根据文字和流程图的描述，我们可以开始编码了。</p>
<p>/index.php</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #666666; font-style: italic;">//...</span>
<span style="color: #000088;">$userLib</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> userLib<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$userLib</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">chkLogin</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'location: /user/login.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//...</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>/user/login.php</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #666666; font-style: italic;">//...</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'submit'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$userLib</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> userLib<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$succ</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$userLib</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">login</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'pass'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'location: '</span><span style="color: #339933;">.</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$succ</span>?<span style="color: #0000ff;">'/index.php'</span><span style="color: #339933;">:</span><span style="color: #0000ff;">'/error.php'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000088;">$tpl</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Template<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$tpl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">show</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user_login.tpl'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>/error.php</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #000088;">$tpl</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Template<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$tpl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">show</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'error.tpl'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p><strong>关于Controller</strong></p>
<p>就像上面三段程序就是系统中的controller，他们并不执行什么具体的操作也不输出，只是不断调用Model中的不同方法来处理逻辑。</p>
<p><strong>关于Model</strong></p>
<p>Model则是另一个重要的话题，那便是在PHP中如何更好的类封装。但是在这里我们看到的在/user/login.php中被使用的userLib类和Template类都是系统中的model，他们处理具体的数据操作，并返回值来用controller使用。</p>
<p>从PHP5开始，我们有了接口，从PHP5.3开始，虽然还没有Release，我们有了namespace，PHP真正面向对象的时代已经到来了。这时候我们已经没有必要再去讨论我们应该把userLib写成userLib.function.php还是userLib.class.php，我们要做的只是更好的封装和理解各model之间的从属逻辑结构。更好的设计model中的各个库来保障系统的运行效率和维护效率。</p>
<p><strong>关于View</strong></p>
<p>View的部分往往被看作是前段设计人员的工作，但是作为PHP的程序员也必须关注这一话题。</p>
<p>对于view和controller来说，所有的页面都是围绕着流程来产生的。而controller有时也担负着处理页面与页面之间相互传递的工作。我们要确定页面的元素，特别是表单元素，并通过表单元素来处理用户提交的数据，其次我们还要确定PHP传递给模板的变量，然后才能交付给设计人员。</p>
<p><strong>最后</strong></p>
<p>我们还经常用来一些常用的文件夹名和文件名来暗示程序的阅读者，特别是新的阅读者，该文件夹或文件的作用。这也是相当重要的。</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/02/26/mvcofphp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

