<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_懒人居 - Coding for fun</title><subtitle type="text">要生猛的面对生活</subtitle><id>http://feed.cnblogs.com/blog/u/24254/rss</id><updated>2011-12-11T16:08:26Z</updated><author><name>亚历山大同志</name><uri>http://www.cnblogs.com/Alexander-Lee/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Alexander-Lee/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/24254/rss"/><entry><id>http://www.cnblogs.com/Alexander-Lee/archive/2011/12/11/2284324.html</id><title type="text">用MySQL数据库来支持Schemaless的数据库存储方案</title><summary type="text">在PyCon上有童鞋提供了一个类似概念的分享，不过不大适合一般类型的互联网项目，感觉有点过于另类。不过我实现这个方案是在看到PyCon的分享之前。算是同样的诉求不同的实现方式吧。且我这里只是实现了一个数据访问的组件而不是Server。首先本文的方法来自FriendFeed分享的如何使用MySQL数据库的分享。简而言之就是把Python对象直接dumps后zip压缩存储在MySQL一个字段里。这样不就Schemaless了么？</summary><published>2011-12-11T15:39:00Z</published><updated>2011-12-11T15:39:00Z</updated><author><name>亚历山大同志</name><uri>http://www.cnblogs.com/Alexander-Lee/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Alexander-Lee/archive/2011/12/11/2284324.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Alexander-Lee/archive/2011/12/11/2284324.html"/><content type="html">&lt;p&gt;在PyCon上有童鞋提供了一个类似概念的分享，不过不大适合一般类型的互联网项目，感觉有点过于另类。不过我实现这个方案是在看到PyCon的分享之前。算是同样的诉求不同的实现方式吧。且我这里只是实现了一个数据访问的组件而不是Server。&lt;/p&gt;&#xD;
&lt;p&gt;首先本文的方法来自FriendFeed分享的如何使用MySQL数据库的分享。简而言之就是把Python对象直接dumps后zip压缩存储在MySQL一个字段里。这样不就Schemaless了么？存什么数据类型，类什么结构，MySQL都不需要知道，加个属性什么的都不需要修改数据库表结构，对于业务快速变更、快速增长的互联网业务来说再合适不过了。访问对象直接通过主键查询，快速直接。but，查询怎么办？有的童鞋可能会问。OK，查询这事得分两说，如果是简单的检索，可以通过建索引表的方式来解决，或者呢用外部的索引，比如lucent，还能全文检索哦。现在而今眼目下我实现了索引表索引的方式，因为外部的索引方式比较千奇百怪，所以如果需要可以根据具体情况自己来写一个，反正实现相应的几个方法就行。&lt;/p&gt;&#xD;
&lt;p&gt;直接上一个例子来说明。假设要实现一个blog，需要存blog的信息，先定义一个blog的模型类(需要import什么大家自动脑补)&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&#xD;
&lt;pre&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Blog(DynamicBase):&lt;br /&gt;&lt;span style="color: #008080;"&gt;2&lt;/span&gt;     title=Column(unicode,max_length=200)&lt;br /&gt;&lt;span style="color: #008080;"&gt;3&lt;/span&gt;     content=Column(unicode)&lt;br /&gt;&lt;span style="color: #008080;"&gt;4&lt;/span&gt;     post_date=Column(datetime.datetime,db_index=True)&lt;br /&gt;&lt;span style="color: #008080;"&gt;5&lt;/span&gt;     auther=FkColumn(User)&lt;br /&gt;&lt;span style="color: #008080;"&gt;6&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Meta:&lt;br /&gt;&lt;span style="color: #008080;"&gt;7&lt;/span&gt;         table_name=&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;blogs&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;8&lt;/span&gt;         connection=connections[DB]&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;这个connection是因为我还没想好如何能无缝结合到Django中又能兼顾脱离Django独立使用的暂时措施，完成版会去掉&lt;/p&gt;&#xD;
&lt;p&gt;如果在使用django的话只需要 python manage.py shell 然后 Blog.objects.create_table()&lt;/p&gt;&#xD;
&lt;p&gt;这个时候会自动创建模型定义的表和索引表&lt;/p&gt;&#xD;
&lt;p&gt;数据表 blogs：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;CREATE TABLE `blogs` (&lt;br /&gt;`id` int(11) NOT NULL,&lt;br /&gt;`object` varbinary(20000) NOT NULL,&lt;br /&gt;PRIMARY KEY (`id`)&lt;br /&gt;) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;同时建立两个索引表&lt;/p&gt;&#xD;
&lt;p&gt;CREATE TABLE `blog_idx_post_date` (&lt;br /&gt;`id` int(10) unsigned NOT NULL,&lt;br /&gt;`post_date` DATETIME NOT NULL,&lt;br /&gt;PRIMARY KEY (`id`),&lt;br /&gt;INDEX `idx_blogs_by_post_date` (`post_date`) USING BTREE&lt;br /&gt;) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;CREATE TABLE `blog_idx_auther` (&lt;br /&gt;`id` int(10) unsigned NOT NULL,&lt;br /&gt;`auther` INT NOT NULL,&lt;br /&gt;PRIMARY KEY (`id`),&lt;br /&gt;INDEX `idx_blogs_by_auther` (`auther`) USING BTREE&lt;br /&gt;) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这个时候，可以通过 Blog.objects.create(title=u"标题",content=u"内容",post_date=datetime.datetime.now(),auther=user) 或者Blog.objects.create(title=u"标题",content=u"内容",post_date=datetime.datetime.now(),auther=user.id)&lt;/p&gt;&#xD;
&lt;p&gt;就能够创建一个Blog的对象。这个时候blogs表和两个索引表都会插入数据。不过blogs表中的object列是人类无法理解的火星文..........&lt;/p&gt;&#xD;
&lt;p&gt;通过id直接获取对象 &amp;nbsp;Blog.objects.get(1),根据索引获取 &amp;nbsp;Blog.objects.auther.query(auther=user.id) 或者&amp;nbsp;&amp;nbsp;Blog.objects.auther.query(auther=user)&lt;/p&gt;&#xD;
&lt;p&gt;这个会生成SQL，SELECT `id` FROM &amp;nbsp;`blog_idx_auther` WHERE `auther`=%s 然后取出match到对象的id列表，然后遍历id列表，通过&amp;nbsp;Blog.objects.get(id)获得的对象列表。&lt;/p&gt;&#xD;
&lt;p&gt;Blog.objects.get(id)的时候是有对象缓存的（现阶段通过redis实现），所以经过测试，速度是靠谱的。而相对MangoDB来说，MySQL的数据存储也更加靠谱一点，所以相比换现在而今眼目下还不怎么靠谱的mangodb来作为主存储来说，基于MySQL的Schemaless方案还是相对靠谱的。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;由于现在这个东西还是处于在项目中孵化的阶段还没有能够达到可以独立开源出来供大家娱乐的程度，所以请大家对这个方案多提意见建议咯，源代码估计能够在春节后达到能够公布出来见人的阶段&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Alexander-Lee/aggbug/2284324.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Alexander-Lee/archive/2011/12/11/2284324.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Alexander-Lee/archive/2011/11/12/django_long_connection.html</id><title type="text">让Django支持数据库长连接（可以提高不少性能哦）</title><summary type="text">书接上回 上回我们说到：《在生产系统使用Tornado WebServer来代替FastCGI加速你的Django应用》那么现在很流行用一些高性能的nonblock的app server来host Django的应用，这些Server可以看做是一个单进程单线程的程序，然后用nginx在前端反向代理并且负载均衡到N多个后端工作进城来充分利用多CPU的性能，当然这部分的配置工作在上回已经说得很清楚了。但是对于Django来说有一个问题。因为Django的数据库连接是在查询的时候实时创建的，用完就会关</summary><published>2011-11-11T18:04:00Z</published><updated>2011-11-11T18:04:00Z</updated><author><name>亚历山大同志</name><uri>http://www.cnblogs.com/Alexander-Lee/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Alexander-Lee/archive/2011/11/12/django_long_connection.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Alexander-Lee/archive/2011/11/12/django_long_connection.html"/><content type="html">&lt;p&gt;书接上回&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;上回我们说到：《&lt;span&gt;&lt;a id="ctl02_TitleUrl" href="http://www.cnblogs.com/Alexander-Lee/archive/2011/05/02/tornado_host_django.html"&gt;在生产系统使用Tornado WebServer来代替FastCGI加速你的Django应用&lt;/a&gt;&lt;/span&gt;&lt;span&gt;》&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;那么现在很流行用一些高性能的nonblock的app server来host Django的应用，这些Server可以看做是一个单进程单线程的程序，然后用nginx在前端反向代理并且负载均衡到N多个后端工作进城来充分利用多CPU的性能，当然这部分的配置工作在上回已经说得很清楚了。但是对于Django来说有一个问题。因为Django的数据库连接是在查询的时候实时创建的，用完就会关掉，这样就会频繁的开闭连接。但是对于Tornado这种Server来说这种方式是低效的。这种Server最高效的工作模式是每个进程开启一个连接，并长期保持不关闭。本文的目的就是尝试使Django改变一贯的作风，采用这种高效的工作模式。本文基于Django1.3的版本，如果是低版本可以稍加更改一样可以使用。&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Django的数据库可以通过配置使用专门定制的Backend，我们就从这里入手。&lt;/p&gt;&#xD;
&lt;p&gt;首先我们看看Django自带的Backend是如何实现的。在Django官网上可以看到自带MySql的Package结构，可以点击 &lt;a href="https://code.djangoproject.com/browser/django/trunk/django/db/backends/mysql" target="_blank"&gt;此处&amp;nbsp;&lt;/a&gt;前往瞻仰。&lt;/p&gt;&#xD;
&lt;p&gt;通观源码我们可以发现，Django基本上是封装了MySQLdb的Connection和Cursor这两个对象。而且重头实现整个Backend既不实际而且也不能从根本上解决问题。所以我们可以换一个思路。所有的数据库操作都是从获取Connection对象开始的，而获取Connection对象只有一个入口，就是MySQLdb.connect这个函数。所以我们只需要包装MySQLdb这个模块，用我们自己的connect方法替代原本的，这样就从根源上解决了问题。我们在包装器内部维护MySQLdb的Connection对象，使其保持长连接，每次connect被调用的时候判断一下，如果连接存在就返回现有连接，不就完美了吗？所以我们可以分分钟写下第一个解决方案：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;proxies = {}&#xD;
&#xD;
class _DbWrapper():&#xD;
    def __init__(self,module):&#xD;
        self.connection=None #这个就是维护的长连接对象&#xD;
        self.db=module           #这个是被包装的原生MySQLdb的module&#xD;
&#xD;
    def __getattr__(self, key):&#xD;
        return getattr(self.db, key)   #代理所有不关心的函数&#xD;
&#xD;
    def connect(self,*argv,**kwargv):&#xD;
        &amp;ldquo;&amp;rdquo;&amp;ldquo;&#xD;
        替换原有的connection对象&#xD;
        &amp;rdquo;&amp;ldquo;&amp;rdquo;&#xD;
        if not self.connection:&#xD;
            self.connection=self.db.connect(*argv,**kwargv)&#xD;
        return _ConnectionWrapper(self.connection)&#xD;
&#xD;
def manage(module,keepalive=7*3600):&#xD;
    &amp;ldquo;&amp;rdquo;&amp;ldquo;&#xD;
    返回代替原生MySQLdb模块的对象&#xD;
    &amp;rdquo;&amp;ldquo;&amp;rdquo;&#xD;
    try:&#xD;
        return proxies[module]&#xD;
    except KeyError:&#xD;
        return proxies.setdefault(module,_DbWrapper(module))&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;把上面代码存到一个叫pool.py的文件里。然后把Django源码里的db/backend/mysql这个package拷贝出来，单独存到我们project目录里一个mysql_pool的目录里。然后修改其中的base.py，在顶上import的部分，找到&amp;nbsp;import MySQLdb as Database 这句，用下面代码替换之&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;try:&#xD;
    import MySQLdb as Database&#xD;
    Database = pool.manage(Database)&#xD;
except ImportError, e:&#xD;
    from django.core.exceptions import ImproperlyConfigured&#xD;
    raise ImproperlyConfigured("Error loading MySQLdb module: %s" % e)&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;这样我们就用自己的模块替换了MySQLdb的，当要connect的时候判断到有连接的时候就不重新创建连接了。&lt;/p&gt;&#xD;
&lt;p&gt;把站点跑起来看，结果如何？刷新几次后报错了。Why？看看日志可以看到如下的错误：&lt;/p&gt;&#xD;
&lt;p&gt;Traceback (most recent call last):&lt;br /&gt; File "/home/www/.virtualenvs/django13/lib/python2.7/site-packages/gevent/wsgi.py", line 114, in handle&lt;br /&gt; result = self.server.application(env, self.start_response)&lt;br /&gt; File "/home/www/.virtualenvs/django13/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 275, in __call__&lt;br /&gt; signals.request_finished.send(sender=self.__class__)&lt;br /&gt; File "/home/www/.virtualenvs/django13/lib/python2.7/site-packages/django/dispatch/dispatcher.py", line 172, in send&lt;br /&gt; response = receiver(signal=self, sender=sender, **named)&lt;br /&gt; File "/home/www/.virtualenvs/django13/lib/python2.7/site-packages/django/db/__init__.py", line 85, in close_connection&lt;br /&gt; conn.close()&lt;br /&gt; File "/home/www/.virtualenvs/django13/lib/python2.7/site-packages/django/db/backends/__init__.py", line 244, in close&lt;br /&gt; self.connection.close()&lt;/p&gt;&#xD;
&lt;p&gt;看来我们光是包装了MySQLdb本身还不行，在connect后Django获取了Connection的对象，之后就能为所欲为，他用完后很自觉的关掉了，因为他直觉的以为每次connect都拿到了新的Connection对象。所以我们必须把Connection对象也包装了了。所以升级后的解决方案代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;proxies = {}&#xD;
&#xD;
class _ConnectionWrapper(object):&#xD;
    """&#xD;
    用来包装Connection的类&#xD;
    """&#xD;
    def __init__(self,conn):&#xD;
        self.conn=conn&#xD;
&#xD;
    def close(self):&#xD;
        """&#xD;
        屏蔽掉关闭连接的行为&#xD;
        """&#xD;
        pass&#xD;
&#xD;
    def __getattr__(self,key):&#xD;
        """&#xD;
        把其他属性都原封不动的代理出去&#xD;
        """&#xD;
        return getattr(self.conn, key)&#xD;
&#xD;
class _DbWrapper():&#xD;
    """&#xD;
    代理MySQLdb模块的对象&#xD;
    """&#xD;
    def __init__(self,module):&#xD;
        self.connection=None  #HOLD住的长连接&#xD;
        self.db=module            #原始的MySQLdb模块&#xD;
&#xD;
    def __getattr__(self, key):&#xD;
        """&#xD;
        代理除connect外的所有属性&#xD;
        """&#xD;
        return getattr(self.db, key)&#xD;
&#xD;
    def connect(self,*argv,**kwargv):&#xD;
        if not self.connection:&#xD;
            self.connection=self.db.connect(*argv,**kwargv)&#xD;
        return _ConnectionWrapper(self.connection)&#xD;
&#xD;
def manage(module):&#xD;
    try:&#xD;
        return proxies[module]&#xD;
    except KeyError:&#xD;
        return proxies.setdefault(module,_DbWrapper(module))&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;我们增加了一个_ConnectionWrapper类来代理Connection对象，然后屏蔽掉close函数。把站点跑起来后发现不会出现之前的问题了，跑起来也顺畅不少。但是过了几个小时后问题又来了。因为MySQLdb的Connection有个很蛋痛的问题，就是连接闲置8小时后会自己断掉。不过要解决这个问题很简单，我们发现连接如果闲置了快8小时就close掉重新建立一个连接不就行了么？所以最后解决方案的代码如下：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;import time&#xD;
&#xD;
proxies = {}&#xD;
&#xD;
class _ConnectionWrapper(object):&#xD;
    def __init__(self,conn):&#xD;
        self.conn=conn&#xD;
&#xD;
    def close(self):&#xD;
        pass&#xD;
&#xD;
    def __getattr__(self,key):&#xD;
        return getattr(self.conn, key)&#xD;
&#xD;
class _DbWrapper():&#xD;
    def __init__(self,module,max_idle):&#xD;
        self.connection=None&#xD;
        self.db=module&#xD;
        self.max_idle=max_idle&#xD;
        self.connected=0&#xD;
&#xD;
    def __getattr__(self, key):&#xD;
        return getattr(self.db, key)&#xD;
&#xD;
    def connect(self,*argv,**kwargv):&#xD;
        if not self.connection or time.time()-self.connected&amp;gt;=self.max_idle:&#xD;
            try:&#xD;
                if self.connection:&#xD;
                    self.connection.close()&#xD;
            except:&#xD;
                pass&#xD;
            self.connection=self.db.connect(*argv,**kwargv)&#xD;
        self.connected=time.time()&#xD;
        return _ConnectionWrapper(self.connection)&#xD;
&#xD;
def manage(module,keepalive=7*3600):&#xD;
    try:&#xD;
        return proxies[module]&#xD;
    except KeyError:&#xD;
        return proxies.setdefault(module,_DbWrapper(module,keepalive))&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;就此问题解决，世界终于清净了&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Alexander-Lee/aggbug/2246113.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Alexander-Lee/archive/2011/11/12/django_long_connection.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Alexander-Lee/archive/2011/09/27/tornado_template.html</id><title type="text">翻译处女作欢迎批评指正－tornado的模板系统文档</title><summary type="text">tornado的文档非常的匮乏，不过这是表面现象，其实个中乾坤都在源文件里，源文件的注释里有非常的文档资料，值得仔细研究。今日将模板系统的内容翻译之，以供日后使用。此处意译为主，并未逐字翻译</summary><published>2011-09-27T06:28:00Z</published><updated>2011-09-27T06:28:00Z</updated><author><name>亚历山大同志</name><uri>http://www.cnblogs.com/Alexander-Lee/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Alexander-Lee/archive/2011/09/27/tornado_template.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Alexander-Lee/archive/2011/09/27/tornado_template.html"/><content type="html">&lt;p&gt;tornado的文档非常的匮乏，不过这是表面现象，其实个中乾坤都在源文件里，源文件的注释里有非常的文档资料，值得仔细研究。今日将模板系统的内容翻译之，以供日后使用。此处意译为主，并未逐字翻译&lt;/p&gt;&#xD;
&lt;p &gt;A simple template system that compiles templates to Python code.&lt;/p&gt;&#xD;
&lt;p &gt;一个简单的模板系统，将模板编译成python代码&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;Basic usage looks like::&lt;/p&gt;&#xD;
&lt;p &gt;基本的用法如下：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;t = template.Template("&amp;lt;html&amp;gt;{{ myvalue }}&amp;lt;/html&amp;gt;")&lt;/p&gt;&#xD;
&lt;p &gt;print t.generate(myvalue="XXX")&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;Loader is a class that loads templates from a root directory and caches&lt;/p&gt;&#xD;
&lt;p &gt;the compiled templates::&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;加载器是一个从根目录加载模板文件并编译缓存模板的类&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;loader = template.Loader("/home/btaylor")&lt;/p&gt;&#xD;
&lt;p &gt;print loader.load("test.html").generate(myvalue="XXX")&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;We compile all templates to raw Python. Error-reporting is currently... uh,&lt;/p&gt;&#xD;
&lt;p &gt;interesting. Syntax for the templates::&lt;/p&gt;&#xD;
&lt;p &gt;我们编译所有模板为python代码，（目前会报错。。。。注：可能是开发时候写下来的）&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;### base.html&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;html&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;head&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;title&amp;gt;{% block title %}Default title{% end %}&amp;lt;/title&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;/head&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;body&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;ul&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;{% for student in students %}&lt;/p&gt;&#xD;
&lt;p &gt;{% block student %}&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;li&amp;gt;{{ escape(student.name) }}&amp;lt;/li&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;{% end %}&lt;/p&gt;&#xD;
&lt;p &gt;{% end %}&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;/ul&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;/body&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;/html&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;### bold.html&lt;/p&gt;&#xD;
&lt;p &gt;{% extends "base.html" %}&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;{% block title %}A bolder title{% end %}&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;{% block student %}&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;li&amp;gt;&amp;lt;span style="bold"&amp;gt;{{ escape(student.name) }}&amp;lt;/span&amp;gt;&amp;lt;/li&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;{% end %}&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;Unlike most other template systems, we do not put any restrictions on the&lt;/p&gt;&#xD;
&lt;p &gt;expressions you can include in your statements. if and for blocks get&lt;/p&gt;&#xD;
&lt;p &gt;translated exactly into Python, you can do complex expressions like::&lt;/p&gt;&#xD;
&lt;p &gt;与其他模板系统不同的是，我们没有对你在模板声名中植入的表达式做任何限制。if和for 块完全支持Python的语法，你可以使用完整的写法，如下：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;{% for student in [p for p in people if p.student and p.age &amp;gt; 23] %}&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;li&amp;gt;{{ escape(student.name) }}&amp;lt;/li&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;{% end %}&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;Translating directly to Python means you can apply functions to expressions&lt;/p&gt;&#xD;
&lt;p &gt;easily, like the escape() function in the examples above. You can pass&lt;/p&gt;&#xD;
&lt;p &gt;functions in to your template just like any other variable::&lt;/p&gt;&#xD;
&lt;p &gt;直接转义成&lt;span &gt;python&lt;/span&gt;代码意味着你可以轻松的在表达式里调用方法，譬如上面调用escape函数的例子，你也可以将函数当成任何其他变量一样的传递到模板中&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;### Python code&lt;/p&gt;&#xD;
&lt;p &gt;def add(x, y):&lt;/p&gt;&#xD;
&lt;p &gt;return x + y&lt;/p&gt;&#xD;
&lt;p &gt;template.execute(add=add)&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;### The template&lt;/p&gt;&#xD;
&lt;p &gt;{{ add(1, 2) }}&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;We provide the functions escape(), url_escape(), json_encode(), and squeeze()&lt;/p&gt;&#xD;
&lt;p &gt;to all templates by default.&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span &gt;每个模板默认提供了 &lt;/span&gt;escape(), url_escape(), json_encode(), and squeeze() &lt;span &gt;这几个函数&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;Typical applications do not create `Template` or `Loader` instances by&lt;/p&gt;&#xD;
&lt;p &gt;hand, but instead use the `render` and `render_string` methods of&lt;/p&gt;&#xD;
&lt;p &gt;`tornado.web.RequestHandler`, which load templates automatically based&lt;/p&gt;&#xD;
&lt;p &gt;on the ``template_path`` `Application` setting.&lt;/p&gt;&#xD;
&lt;p &gt;默认的&lt;span &gt;application&lt;/span&gt;不会手动创建&lt;span &gt;Template&lt;/span&gt;和&lt;span &gt;Loader&lt;/span&gt;的实例，而是通过调用`tornado.web.RequestHandler`实例中的 render，render_string 方法。&lt;/p&gt;&#xD;
&lt;p &gt;这些方法通过Application的setting里面的`template_path`这一项的设置自动加载目录里的模板&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;Syntax Reference&lt;/p&gt;&#xD;
&lt;p &gt;语法&lt;/p&gt;&#xD;
&lt;p &gt;----------------&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;Template expressions are surrounded by double curly braces: ``{{ ... }}``.&lt;/p&gt;&#xD;
&lt;p &gt;The contents may be any python expression, which will be escaped according&lt;/p&gt;&#xD;
&lt;p &gt;to the current autoescape setting and inserted into the output.&amp;nbsp; Other&lt;/p&gt;&#xD;
&lt;p &gt;template directives use ``{% %}``.&amp;nbsp; These tags may be escaped as ``{{!``&lt;/p&gt;&#xD;
&lt;p &gt;and ``{%!`` if you need to include a literal ``{{`` or ``{%`` in the output.&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;模板表达式用两个大括号包裹起来：&lt;span &gt;``{{ &amp;hellip; }}``.&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p &gt;内容可以是任何Python表达式，表达式会使用当前的 autoescape设置转义并插入到输出中。&lt;/p&gt;&#xD;
&lt;p &gt;其他模板指令使用 `{%&amp;nbsp; &amp;nbsp; %}`。这些标签会被转义成 ``{{!``和 ``{%!`` ，如果你需要插入 ``{{``或者 ``{%``到输出中。&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% apply *function* %}...{% end %}``&lt;/p&gt;&#xD;
&lt;p &gt;Applies a function to the output of all template code between ``apply``&lt;/p&gt;&#xD;
&lt;p &gt;and ``end``::&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;将这个标签之间的模板输出作为一个参数应用到一个方法，如下：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;{% apply linkify %}{{name}} said: {{message}}{% end %}&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% autoescape *function* %}``&lt;/p&gt;&#xD;
&lt;p &gt;Sets the autoescape mode for the current file.&amp;nbsp; This does not affect&lt;/p&gt;&#xD;
&lt;p &gt;other files, even those referenced by ``{% include %}``.&amp;nbsp; Note that&lt;/p&gt;&#xD;
&lt;p &gt;autoescaping can also be configured globally, at the `Application`&lt;/p&gt;&#xD;
&lt;p &gt;or `Loader`.::&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;这个标签用来设置当前文件的自动转义模式。这项设置对其他文件无效，即时是哪些插入了当前文件的模板。&lt;/p&gt;&#xD;
&lt;p &gt;自动转义也能够在Application和Loader中全局设置。&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;{% autoescape xhtml_escape %}&lt;/p&gt;&#xD;
&lt;p &gt;{% autoescape None %}&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% block *name* %}...{% end %}``&lt;/p&gt;&#xD;
&lt;p &gt;Indicates a named, replaceable block for use with ``{% extends %}``.&lt;/p&gt;&#xD;
&lt;p &gt;Blocks in the parent template will be replaced with the contents of&lt;/p&gt;&#xD;
&lt;p &gt;the same-named block in a child template.::&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;表示一个命名的可以被替换的块， 和``{% extends %}``一起使用。在父模板中的这些块将被自模板中同名的块替代&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;!-- base.html --&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;title&amp;gt;{% block title %}Default title{% end %}&amp;lt;/title&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;&amp;lt;!-- mypage.html --&amp;gt;&lt;/p&gt;&#xD;
&lt;p &gt;{% extends "base.html" %}&lt;/p&gt;&#xD;
&lt;p &gt;{% block title %}My page title{% end %}&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% comment ... %}``&lt;/p&gt;&#xD;
&lt;p &gt;A comment which will be removed from the template output.&amp;nbsp; Note that&lt;/p&gt;&#xD;
&lt;p &gt;there is no ``{% end %}`` tag; the comment goes from the word ``comment``&lt;/p&gt;&#xD;
&lt;p &gt;to the closing ``%}`` tag.&lt;/p&gt;&#xD;
&lt;p &gt;注释块，不会输出。主意不需要&lt;span &gt; `{% end %}` &lt;/span&gt;标签；&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% extends *filename* %}``&lt;/p&gt;&#xD;
&lt;p &gt;Inherit from another template.&amp;nbsp; Templates that use ``extends`` should&lt;/p&gt;&#xD;
&lt;p &gt;contain one or more ``block`` tags to replace content from the parent&lt;/p&gt;&#xD;
&lt;p &gt;template.&amp;nbsp; Anything in the child template not contained in a ``block``&lt;/p&gt;&#xD;
&lt;p &gt;tag will be ignored.&amp;nbsp; For an example, see the ``{% block %}`` tag.&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;继承其他的模板。使用&lt;span &gt;extend&lt;/span&gt;s标签的模板需要包含一个到多个block标签用来替换父模板中的同名的块。子模板中任何不在块中的内容将被忽略掉。例子可参见 ``{% block %}``标签那一节&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% for *var* in *expr* %}...{% end %}``&lt;/p&gt;&#xD;
&lt;p &gt;Same as the python ``for`` statement.&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span &gt;for&lt;/span&gt;循环标签，等同于&lt;span &gt;Python&lt;/span&gt;中的&lt;span &gt;for&lt;/span&gt;表达式&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% from *x* import *y* %}``&lt;/p&gt;&#xD;
&lt;p &gt;Same as the python ``import`` statement.&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;import&lt;span &gt;标签，等同于&lt;/span&gt;import&lt;span &gt;表达式&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% if *condition* %}...{% elif *condition* %}...{% else %}...{% end %}``&lt;/p&gt;&#xD;
&lt;p &gt;Conditional statement - outputs the first section whose condition is&lt;/p&gt;&#xD;
&lt;p &gt;true.&amp;nbsp; (The ``elif`` and ``else`` sections are optional)&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span &gt;if&lt;/span&gt;条件表达式标签，等同于&lt;span &gt;python&lt;/span&gt;的&lt;span &gt;if &lt;/span&gt;&amp;hellip; else &amp;hellip; 表达式&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% import *module* %}``&lt;/p&gt;&#xD;
&lt;p &gt;Same as the python ``import`` statement.&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span &gt;import &lt;/span&gt;标签的另一种写法&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% include *filename* %}``&lt;/p&gt;&#xD;
&lt;p &gt;Includes another template file.&amp;nbsp; The included file can see all the local&lt;/p&gt;&#xD;
&lt;p &gt;variables as if it were copied directly to the point of the ``include``&lt;/p&gt;&#xD;
&lt;p &gt;directive (the ``{% autoescape %}`` directive is an exception).&lt;/p&gt;&#xD;
&lt;p &gt;Alternately, ``{% module Template(filename, **kwargs) %}`` may be used&lt;/p&gt;&#xD;
&lt;p &gt;to include another template with an isolated namespace.&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;引用另外的模板文件。被引入的文件可以访问引入它的模板的所有&lt;span &gt;locals&lt;/span&gt;变量，相当于是直接&lt;span &gt;copy&lt;/span&gt;了被引入模板文件的内容。autoescape节有例子。&lt;/p&gt;&#xD;
&lt;p &gt;另外``{% module Template(filename,**kwargs) %}``可以用来引入一个模板文件在一个独立的namespace中&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% module *expr* %}``&lt;/p&gt;&#xD;
&lt;p &gt;Renders a `~tornado.web.UIModule`.&amp;nbsp; The output of the ``UIModule`` is&lt;/p&gt;&#xD;
&lt;p &gt;not escaped::&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;插入一个&lt;span &gt;UI&lt;/span&gt;模块的标签，&lt;span &gt;UI&lt;/span&gt;模块的输出没有经过转义的&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;{% module Template("foo.html", arg=42) %}&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% raw *expr* %}``&lt;/p&gt;&#xD;
&lt;p &gt;Outputs the result of the given expression without autoescaping.&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;不经过转义输出一个表达式的值&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% set *x* = *y* %}``&lt;/p&gt;&#xD;
&lt;p &gt;Sets a local variable.&lt;/p&gt;&#xD;
&lt;p &gt;创建一个本地变量&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% try %}...{% except %}...{% finally %}...{% end %}``&lt;/p&gt;&#xD;
&lt;p &gt;Same as the python ``try`` statement.&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span &gt;和&lt;/span&gt;Python &lt;span &gt;的&lt;/span&gt;try &amp;hellip; except &amp;hellip;&amp;nbsp; &lt;span &gt;块特性一致&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;``{% while *condition* %}... {% end %}``&lt;/p&gt;&#xD;
&lt;p &gt;Same as the python ``while`` statement.&lt;/p&gt;&#xD;
&lt;p &gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span &gt;和&lt;/span&gt;Python&lt;span &gt;里&lt;/span&gt;while&lt;span &gt;语句一致&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Alexander-Lee/aggbug/2193109.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Alexander-Lee/archive/2011/09/27/tornado_template.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Alexander-Lee/archive/2011/05/02/tornado_host_django.html</id><title type="text">在生产系统使用Tornado WebServer来代替FastCGI加速你的Django应用</title><summary type="text">Tornado是一个异步web框架和服务器，所以在开发longpulling的chat之类应用非常的合适，但是其实本身也是一个高性能的http服务器，也可以作为一个WSGIServer。所以即使你的网站没有使用Tornado的框架，而是用了web.py或者是Django来开发（傻瓜万岁），这个时候Tornado依然可以用来加速你的网站。使用Tornado来代替fastCGI可以大幅提高性能，且可以承载的并发能力也有了成倍的提高</summary><published>2011-05-02T10:30:00Z</published><updated>2011-05-02T10:30:00Z</updated><author><name>亚历山大同志</name><uri>http://www.cnblogs.com/Alexander-Lee/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Alexander-Lee/archive/2011/05/02/tornado_host_django.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Alexander-Lee/archive/2011/05/02/tornado_host_django.html"/><content type="html">&lt;p&gt;由于换了工作，所以之前的游戏引擎暂时放下，但是不会停止的，这个项目会在我的业余时间来完成。&lt;/p&gt;&#xD;
&lt;p&gt;---------------------------------------闷骚的分割线，下面是正文-------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;tornado我在之前的文章里已经有过多次介绍，在此就不详细介绍了，&lt;/p&gt;&#xD;
&lt;p&gt;详细介绍可参见：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a id="homepage1_HomePageDays_DaysList_DayItem_26_DayList_26_TitleUrl_0" href="http://www.cnblogs.com/Alexander-Lee/archive/2010/03/20/1690292.html"&gt;玩蛇记-使用tornado构建高性能Web应用之一&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a id="homepage1_HomePageDays_DaysList_DayItem_24_DayList_24_TitleUrl_0" href="http://www.cnblogs.com/Alexander-Lee/archive/2010/03/24/1693367.html"&gt;玩蛇记-使用Tornado构建高性能Web之二-autoreload&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;由于官网被墙，讨论组也被墙（囧，万恶的墙）所以tornado的资料很少，官网的资料也语焉不详，所以很多童鞋对如何部署使用Tornado心里没底。所以本文的主要目的就是教会刚入门的新手如何在生产环境使用Tornado&lt;/p&gt;&#xD;
&lt;p&gt;Tornado是一个异步web框架和服务器，所以在开发longpulling的chat之类应用非常的合适，但是其实本身也是一个高性能的http服务器，也可以作为一个WSGIServer。所以即使你的网站没有使用Tornado的框架，而是用了web.py或者是Django来开发（傻瓜万岁），这个时候Tornado依然可以用来加速你的网站。使用Tornado来代替fastCGI可以大幅提高性能，且可以承载的并发能力也有了成倍的提高（大家可以自己Profile，本文只介绍如果做）。&lt;/p&gt;&#xD;
&lt;p&gt;下面我们开始来介绍如何配置。这里我们假设你的一个用Django写的网站在一台Linux的服务器上快乐地着（ubuntu or CentOS，没试过在其他发行版折腾过，windows？你在说笑吧），随着网站越来越红火，你越发感觉服务器不堪重负。这个时候Tornado出现了，他可以让你再苟延残喘好几个月，节约一大把的银子去把妹.............回到正题。根据官网的推荐部署方式，我们还是采用Nginx通过upstream来反向代理到N个Tornado的服务器实例上的部署方式。so&lt;/p&gt;&#xD;
&lt;p&gt;Setp1：安装supervisord&lt;/p&gt;&#xD;
&lt;p&gt;由于Tornado并没有自身提供Daemon的能力，所以我们需要用一个服务管理工具来管理Tornado的进程，supervisord是用Python实现的一款非常实用的进程管理工具。可以很方便的管理N过进程，且支持进程分组。Supervisord可以通过sudo easy_install supervisor安装，当然也可以通过&lt;a target="_blank" href="http://supervisord.org/"&gt;Supervisord官网&lt;/a&gt;下载后setup.py install安装。&lt;/p&gt;&#xD;
&lt;p&gt;Step2: 给Django的站点增加一个Tornado的服务器文件（比如serv.py）&lt;/p&gt;&#xD;
&lt;p&gt;创建一个文件Serv.py在Django站点的根目录，内容如下：&lt;/p&gt;&#xD;
&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&#xD;
&lt;pre&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt; &lt;span style="color: #800080;"&gt;__author__&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;alexander&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt; os&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt; sys&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;from&lt;/span&gt;&lt;span style="color: #000000;"&gt; tornado.options &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt; options, define, parse_command_line&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt; django.core.handlers.wsgi&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt; tornado.httpserver&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt; tornado.ioloop&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt; tornado.web&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt; tornado.wsgi&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;_HERE &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; os.path.dirname(os.path.abspath(&lt;/span&gt;&lt;span style="color: #800080;"&gt;__file__&lt;/span&gt;&lt;span style="color: #000000;"&gt;))&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt; &lt;span style="color: #000000;"&gt;sys.path.append(_HERE)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt; &lt;span style="color: #000000;"&gt;sys.path.append(os.path.join(_HERE, &lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;..&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;))&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt; &lt;span style="color: #000000;"&gt;sys.path.append(os.path.join(_HERE, &lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;../contrib&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;))&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt; &lt;span style="color: #000000;"&gt;os.environ[&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;DJANGO_SETTINGS_MODULE&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;] &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;settings&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;def&lt;/span&gt;&lt;span style="color: #000000;"&gt; main(port):&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt; &lt;span style="color: #000000;"&gt;    wsgi_app &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; tornado.wsgi.WSGIContainer(&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt; &lt;span style="color: #000000;"&gt;        django.core.handlers.wsgi.WSGIHandler())&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt; &lt;span style="color: #000000;"&gt;    tornado_app &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; tornado.web.Application(&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt; &lt;span style="color: #000000;"&gt;        [(&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;.*&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;, tornado.web.FallbackHandler, dict(fallback&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;wsgi_app)),&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt; &lt;span style="color: #000000;"&gt;        ])&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt; &lt;span style="color: #000000;"&gt;    server &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; tornado.httpserver.HTTPServer(tornado_app)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;25&lt;/span&gt; &lt;span style="color: #000000;"&gt;    server.listen(port)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;26&lt;/span&gt; &lt;span style="color: #000000;"&gt;    tornado.ioloop.IOLoop.instance().start()&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;27&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;28&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;__name__&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;__main__&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;29&lt;/span&gt; &lt;span style="color: #000000;"&gt;    main(int(sys.argv[&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;]))&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;br /&gt;&#xD;
&#xD;
&lt;p&gt;我这里通过第一个参数来指定Tornado服务监听的端口。这样比较灵活，这点我们在后面的步骤会用到。这个时候我们可以通过&lt;/p&gt;&#xD;
&lt;p&gt;python Serv.py 8000&lt;/p&gt;&#xD;
&lt;p&gt;这个命令来启动服务器&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;Step3: 配置Supervisord&lt;/p&gt;&#xD;
&lt;p&gt;第一步安装的Supervisord还没有配置，所以我们需要先创建一个配置文件的样板。在root权限下执行&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span &gt;echo_supervisord_conf&lt;/span&gt;&amp;nbsp;&lt;span &gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span &gt;/etc/supervisord.conf&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这个时候在/etc/创建了配置文件，用vim打开这个文件，在配置文件的屁股后面加上以下这一段&lt;/p&gt;&#xD;
&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&#xD;
&lt;pre&gt;&lt;div&gt;&lt;span style="color: #800000; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #800000;"&gt;program:web&lt;/span&gt;&lt;span style="color: #800000; font-weight: bold;"&gt;]&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;command&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;python /var/www/site/Serv.py &lt;/span&gt;&lt;span style="color: #000000;"&gt;80&lt;/span&gt;&lt;span style="color: #000000;"&gt;%(process_num)02d&lt;br /&gt;process_name&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;%(program_name)s_%(process_num)02d&lt;br /&gt;umask&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;022&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;startsecs&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;stopwaitsecs&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;redirect_stderr&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;true&lt;br /&gt;stdout_logfile&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;/tmp/codoon.log&lt;br /&gt;numprocs&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;4&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;numprocs_start&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;br /&gt;&#xD;
&#xD;
&lt;p&gt;这个配置会启动4个Tornado的服务进程分别监听 8001,8002,8003,8004 这四个端口&lt;/p&gt;&#xD;
&lt;p&gt;command这一行是要执行的命令，这里是用 python /var/www/site/Serv.py 端口号来启动Tornado的服务进程&amp;nbsp;&lt;span&gt;80&lt;/span&gt;&lt;span&gt;%(process_num)02d 的用途是通过进程编号来生成端口号。下面的process_name这个参数也会用到。这里要指定的文件名就是上一步我们创建那个Serv.py文件&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;process_name是进程的名字，由于这里要启动4个进程，所以要用process_num来区分&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;umask是程序执行的权限参数&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;startsecs这个参数是程序启动的等待时间&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;stopwaitsecs这个参数是程序停止的等待时间&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;redirect_stderr这个参数将错误流重定向到std的流输出，这样可以省去一个日志文件的配置，当然也可以不用这个参数分开配置日志文件&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span&gt;stdout_logfile 这个参数是STD流输出日志文件的路径，Tornado会输出所有的请求和错误信息，通过这个可以统一做日志处理，分隔什么的，在程序里就只需要print到std流就行了。&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;numprocs 这个参数指定了进程的数量，这里是4，表明要启动4个Tornado进程&lt;/p&gt;&#xD;
&lt;p&gt;numprocs_start 这个参数指定了进程号的起始编号，这里是1，这样前面的command和process_name里的%(process_num)02d部分就会在执行的时候被替换为01~05的字符串&lt;/p&gt;&#xD;
&lt;p&gt;配置修改完成后:wq保存退出，执行：&lt;/p&gt;&#xD;
&lt;p&gt;supervisorctl reload&lt;/p&gt;&#xD;
&lt;p&gt;重新加载配置后，这些进程就启动起来了&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;Step4：修改配置Nginx&lt;/p&gt;&#xD;
&lt;p&gt;首先找到在vhost目录里你的站点配置文件，打开后，在头上增加upstream的内容&lt;/p&gt;&#xD;
&lt;p&gt;upstream frontends {&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;server 127.0.0.1:8001;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;server 127.0.0.1:8002;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;server 127.0.0.1:8003;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;server 127.0.0.1:8004;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;然后在Server配置节里找到&lt;/p&gt;&#xD;
&lt;p&gt;location / { 这个配置节&lt;/p&gt;&#xD;
&lt;p&gt;以前是用的FastCGI，所以里面的配置可能是这样子的&lt;/p&gt;&#xD;
&lt;p&gt;# host and port to fastcgi server &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;br /&gt;#fastcgi_pass 127.0.0.1:8081;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;#fastcgi_param PATH_INFO $fastcgi_script_name;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;#fastcgi_param REQUEST_METHOD $request_method;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;#fastcgi_param QUERY_STRING $query_string;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;#fastcgi_param CONTENT_TYPE $content_type;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;#fastcgi_param CONTENT_LENGTH $content_length;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;#fastcgi_pass_header Authorization;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;#fastcgi_param REMOTE_ADDR $remote_addr;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;#fastcgi_param SERVER_PROTOCOL $server_protocol;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;#fastcgi_param SERVER_PORT $server_port;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;#fastcgi_param SERVER_NAME $server_name;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;#fastcgi_intercept_errors off;&lt;/p&gt;&#xD;
&lt;p&gt;把这些统统删掉，变成了这样&lt;/p&gt;&#xD;
&lt;p&gt;location / {&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;在{}中加入upstream的配置，变成如下样子&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;location / {&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;br /&gt;　　proxy_pass_header Server;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;br /&gt;　　proxy_set_header Host $http_host;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;br /&gt;　　proxy_set_header X-Real-IP $remote_addr;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;br /&gt;　　proxy_set_header X-Scheme $scheme;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;br /&gt;　　proxy_pass http://frontends;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;br /&gt;　　proxy_next_upstream error;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;保存配置文件后执行 &amp;nbsp;让nginx重启的指令 nginx -s reload(注意 nginx文件在不同发行版中位置有差别)&lt;/p&gt;&#xD;
&lt;p&gt;然后你就能够通过域名看到你的网站了，试试是不是快多了&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;注意：生产系统下开启多少个Tornado进程比较好呢，这个见仁见智了，据我压力测试的结果看来，用CPU核数*2的数量最好，再多 就浪费了没有提升（为什么乘2？因为有种CPU上的技术叫超线程）。我的VPS上用的4个进程。如果是8核IntelCPU要挖尽CPU潜能的话需要开16个进程&lt;/p&gt;&#xD;
&#xD;
&#xD;
&lt;img src="http://www.cnblogs.com/Alexander-Lee/aggbug/2034499.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Alexander-Lee/archive/2011/05/02/tornado_host_django.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Alexander-Lee/archive/2011/01/19/1939617.html</id><title type="text">高性能MMORPG通用服务端引擎设计之-&amp;gt;基本概念篇二</title><summary type="text">书接上回&amp;lt;高性能MMORPG通用服务端引擎设计之-&amp;gt;基本概念篇&amp;gt;上回说道我们将服务器组的职责划分为了，前端服务器，场景服务器，登录服务器，数据服务器...etc.如图：Logic-Service  Logic-Service  DB-Service | | | ----------------------------------- | Scene Manager | ------------------------------------- | | | Front Server  Front Server Login Server | | Client Client 不过经过思考后发现这个结构</summary><published>2011-01-19T12:10:00Z</published><updated>2011-01-19T12:10:00Z</updated><author><name>亚历山大同志</name><uri>http://www.cnblogs.com/Alexander-Lee/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Alexander-Lee/archive/2011/01/19/1939617.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Alexander-Lee/archive/2011/01/19/1939617.html"/><content type="html">&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;书接上回&amp;lt;&lt;a href="http://www.cnblogs.com/Alexander-Lee/archive/2010/11/20/ViewOfHightPerformanceMMORPGGameServer.html" target="_blank"&gt;高性能MMORPG通用服务端引擎设计之-&amp;gt;基本概念篇&lt;/a&gt;&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;上回说道我们将服务器组的职责划分为了，前端服务器，场景服务器，登录服务器，数据服务器...etc.&lt;/p&gt;&#xD;
&lt;p&gt;如图：&lt;/p&gt;&#xD;
&lt;p&gt;Logic-Service &amp;nbsp; Logic-Service &amp;nbsp; &amp;nbsp;DB-Service&lt;/p&gt;&#xD;
&lt;p&gt;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;/p&gt;&#xD;
&lt;p&gt;-----------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;|&lt;/p&gt;&#xD;
&lt;p&gt;Scene Manager&lt;/p&gt;&#xD;
&lt;p&gt;|&lt;/p&gt;&#xD;
&lt;p&gt;-------------------------------------&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|&lt;/p&gt;&#xD;
&lt;p&gt;Front Server &amp;nbsp; Front Server &amp;nbsp; &amp;nbsp; Login Server&lt;/p&gt;&#xD;
&lt;p&gt;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|&lt;/p&gt;&#xD;
&lt;p&gt;Client &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Client &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;不过经过思考后发现这个结构有点问题。&lt;/p&gt;&#xD;
&lt;p&gt;问题何在呢？我们来好好分析一下游戏的逻辑后会发现，整个MMORPG的服务端逻辑，其实是对服务端事件的响应，这里有两种事件，一种是对自身属性的改变（比如切换技能，向腰带放入药瓶之类的），一种是改变其他玩家属性，或者是需要通知其他玩家知道的自身属性改变（比如，攻击对方，自己回血，换装，移动等），也就是前文中我们分析发生在场景中的事件，第二种事件远远超过第一种事件，而且大部分的业务逻辑也发生在这些事件中，所以这类事件的处理需要消耗更多的CPU。这样就带来问题了，前端服务器的压力主要在IO，而场景服务器的压力主要在CPU，那么如果分开在不同的机器上部署，那么这两边服务器的压力就不均衡了，前端服务器的CPU剩余很多，场景服务器的CPU又不够用。所以我决定将这两个部分再次合并起来，合成Logic服务，然后多个Logic服务并行运行。&lt;/p&gt;&#xD;
&lt;p&gt;所有的游戏逻辑都在逻辑服务中运算，但是按照MMORPG的业务，所有的逻辑基本都是按照场景来分布的，所以这个时候我门又面临2难的选择题了。第一种方案是，我们可以按照场景来组织逻辑，比如服务器A负责1，3，5，7场景，服务器B负责2，4，6场景，因为场景之间的人数不平均，有的场景人多（比如某某城内，正在被大批人追杀的BOSS所在地），有的场景人少（比如运行一段时间后的新手村），而且游戏中的热点场景是动态变化的，随着游戏进程的发展会有变化。所以这个情况下我们需要一个场景管理服务，这个服务用于监控每个逻辑服务，将热点场景所在的服务里的其他场景迁移到空闲逻辑服务器。这个逻辑需要客户端提供支持，要实现服务器的软切换。还有一种方式是将场景的逻辑随机分布到所有逻辑服务器上，场景间的联系通过消息来传递，由一个消息服务器来为所有场景提供广播组来分发消息。这样就会多个消息服务器出来。这两个方案中第一个对单个玩家来说延迟最小，但是如果场景管理做得不好就会造成CPU资源分布不均匀，还有就是场景容量受到单个进程处理能力极限的局限。第二种方案延迟肯定大过第一种，但是场景的容量不受单个进程计算能力的影响，扩展性更好一点。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;最后我决定用Python来实现这个想法，一，有丰富的基础框架可以选择，比如用高性能的Gevnet或者Eruasia来作为TCP Server的基础。二是Python本来就是动态的，所以不需要再嵌入另一个动态语言来适应多变的业务逻辑了。其三是Python是动态类型的，在实现消息服务的时候更方便。本来打算用erlang的，不过暂时对OTP还不是很熟悉所以暂时作罢，不过如果采用第二种方式的话我可能会用Erlang来实现消息服务器。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;下一章直接进入实现阶段，并且无论如何我都会把这个玩意儿弄出来，如果没有公司愿意花钱让我弄，我就业余时间自己弄出来开源，哼哼&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1939617.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Alexander-Lee/archive/2011/01/19/1939617.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Alexander-Lee/archive/2010/11/20/ViewOfHightPerformanceMMORPGGameServer.html</id><title type="text">高性能MMORPG通用服务端引擎设计之-&amp;gt;基本概念篇</title><summary type="text">鉴于公司保密协议，本系列文章将不涉及具体的游戏细节以及实现。由于本人也是第一次参与此类引擎的设计，所以难免有所失误，如有异见欢迎业内人士讨论，发表本系列文章的目的不在于说教，重在分享以及讨论。</summary><published>2010-11-19T17:22:00Z</published><updated>2010-11-19T17:22:00Z</updated><author><name>亚历山大同志</name><uri>http://www.cnblogs.com/Alexander-Lee/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Alexander-Lee/archive/2010/11/20/ViewOfHightPerformanceMMORPGGameServer.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Alexander-Lee/archive/2010/11/20/ViewOfHightPerformanceMMORPGGameServer.html"/><content type="html">&lt;p&gt;鉴于公司保密协议，本系列文章将不涉及具体的游戏细节以及实现。由于本人也是第一次参与此类引擎的设计，所以难免有所失误，如有异见欢迎业内人士讨论，发表本系列文章的目的不在于说教，重在分享以及讨论。&lt;br /&gt;MMORPG的服务端引擎是驱动整个游戏的总要部件，而且对于现在外挂满天飞的年代，服务端的地位变得愈发重要，很多游戏都将很多原来由客户端处理的逻辑交给了服务端来处理，以避免各类外挂对游戏公平性造成的影响。要设计一款通用的且高性能的MMORPG服务引擎是一个非常艰巨的工作，总的来说，一款网游能够承载多少人，能够实现什么功能，能够开展什么运营活动，都是跟有一款够不够强悍的服务端引擎有密切的关系，可以说服务端引擎就是游戏的心脏，如果设计不好，就会&amp;ldquo;心率不齐&amp;rdquo;，&amp;ldquo;心肌梗塞&amp;rdquo;，然后不能支撑足够的在线人数，操作&amp;ldquo;卡&amp;rdquo;，最后死掉翘辫子。设计精良的引擎，比如WOW，EVE Online等，则给运营和策划留下来大量的空间，这样游戏的成功也就不存在&amp;ldquo;技术问题&amp;rdquo;了。&lt;br /&gt;一般来说，当然是想一个游戏装的用户越多越好，当然这里有很多现实上的制约，第一是运营上，游戏里总是老玩家等级更高、实力更强，由于游戏的竞争性，玩家都喜欢进新服，所以一组服务器总是在开服的时候开始在线人数持续攀升，然后在某个点后就会下降并趋于稳定。其二是因为游戏中的场景不是无限大的，有固有的玩家密度限制，如果一个游戏屏幕上到处都塞满人，估计你也不会觉得好玩。并且根据这两个特点就决定了，MMORPG的服务引擎需要有高性能，这样才能在开服的时候承载尽可能多的用户进入，并且要具备高度的可伸缩性，在开服用户在线高峰的时候可以用比较多的服务器资源来拉动用户，在平稳运行后能够省出多余的服务器资源来挪给其他的服务器组。&lt;br /&gt;从最简单的来说，MMORPG游戏基本上就是经典的C-S结构的系统，所以最简单的结构就是&lt;br /&gt;Server &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;|&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;|&lt;/p&gt;&#xD;
&lt;p&gt;Client&lt;/p&gt;&#xD;
&lt;p&gt;这个时候Server端什么都要处理，就是忒累点，所以承载能力也就不用指望了，扩展能力就更不用想了，不过胜在简单，如果好好设计性能还是有保障的。有个开源的C#开发的UO的服务引擎实现大家可以借鉴一下，http://www.runuo.com/。其实从本质上来说MMORPG的服务端和企业应用没有差别，所以我们解决问题的方式也是很相似的，如果性能有问题，一台服务器无法解决问题，就用两台，属于叫分而治之的策略，所以要提高性能，我们需要从系统的最慢的地方开始。如果有点经验的开发人员都知道，系统中最慢的就是数据库了。所以要提高系统的响应，我们一般是在用户的角色登录的时候直接将角色的数据读进内存来处理，但是内存的数据不怎么保险，万一服务器当掉或者掉电了怎么办呢，这个问题就需要定时将用户的数据变更发给数据库了，这样就不存在读写数据库的延迟了，当然掉电的时候在上一次保存后的数据还是会掉，这个时候就叫服务器回档，这种小几率事件一般我们不用特殊处理，一般游戏偶尔出现故障回档的话基本都是对在线的用户赔点经验装备了事。以后架构还有可能扩张，而为了让你不必将SQL写得满世界都是，我们将数据库操作抽象成数据库服务，为了多台服务器都可以一视同仁的使用，也也可以单独用一台服务器来作为数据库服务的主机，如下图：&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;DB-Service&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp;Server&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;CLient&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这张图看着很眼熟吧，恩，啥三层架构不就是这么画的嘛。囧&amp;nbsp;这个时候系统的压力就不在数据存储上了，于是压力到了游戏的逻辑上，现在游戏既要同时处理大量的并发网络请求，且还要对游戏的逻辑进行运算，一边是高IO应用，一边是高CPU运算，都放在一块那就是一半火焰一半海水，不是烧死就是淹死了。高网络IO并不需要很强的CPU运算性能，比如路由器，一台城域网的核心路由器负担了整个城市的出口网络路由，IO高得吓人，路由器其实也就是一台特殊的电脑，但是这台核心路由器的CPU其实并不比我们的家用PC的CPU高，甚至有可能低一点。但是游戏的逻辑运算对CPU的消耗就是实打实的消耗了，假设游戏有1000个玩家在线，这个时候每处理一个事件需要1ms，那么假设每个玩家每秒有4个事件需要处理，那么1000个玩家就把一颗4核CPU或者2颗双核CPU的计算能力耗尽了，这里还是假设的理想情况，如果再加上NPC，怪物，物品之类的要处理，那就需要非常多的CPU资源，如果所有CPU资源都给了逻辑运算，网络消息处理所需的CPU能力就不足了，虽然消耗低，但是总是消耗的，所以我们继续采取分而治之的办法来处理，我们把前端服务器和逻辑服务器分开，前端服务器用来处理大量的用户链接和消息分发，而逻辑服务器用来处理游戏逻辑。由于游戏逻辑更消耗CPU，所以一个前端服务器可以带N台逻辑服务器，所以结构改成了下图：&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Logic-Service &amp;nbsp; Logic-Service &amp;nbsp; &amp;nbsp;DB-Service&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -------------------------------------&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Front Server&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Client&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;我们可以继续将游戏逻辑进行分类，由于MMORPG的每一个玩家从经入游戏开始就是处于一个个的场景当中的，所以逻辑服务器也可以叫场景服务器（地图服务器），有的游戏即使没有场景切换，其实也是分了很多场景的，只是采用了无缝拼接的技术让你觉得是没有分开的。玩家的逻辑就可以分为连续事件逻辑和瞬时逻辑。连续事件逻辑是在场景中需要和其他用户发生反映的事件，也可以称之为场景事件，比如我攻击了一个怪，这一个事件需要通知场景里所有的玩家知道，并且会影响怪接下来的行动。所谓的瞬时事件，就是只会影响玩家自身的状态且不需要通知其他玩家或者说是对场景产生影响的（当然如果对场景产生了影响势必需要通知场景内其他玩家）。有的事件甚至会跨场景通知系统内所有用户（比如某玩家击杀了某著名BOSS，或者通知师父自己的徒弟在某处遭到了攻击[假如要实现师徒系统的话]）。玩家大部分的逻辑都是在场景内完成的，所以场景逻辑的实现非常的重要。在这个部分的运算涉及到多个对象间的互动，如果想用多线程来提高并行度来提高性能其实反而会适得其反，因为要保证计算的数据安全避免脏读，在多线程的环境下就需要处理大量的锁，相信在游戏的业务逻辑里还需要处理锁，防止死锁这里的处理会宁所有的程序员抓狂，对于这种高CPU运算的场景来说，大量的线程也会将宝贵的CPU时间浪费不少在线程切换上，所以一般来说游戏的逻辑服务器都是单进程单线程的结构，通过一个大循环来驱动整个事件逻辑。那么你可能会问，如果有单进程单线程岂不是只能利用一颗CPU内核了么？当然一个游戏也不可能只有一个场景嘛，我们可以在一台服务器上跑N个场景服务，处理N个场景的逻辑（根据经验来说，N=CPU内核数量性能最好）。所以你可以看到为啥上图我不写Logic Server而是写的Logic Service了。&lt;br /&gt;当玩家连接上Front Server后怎么知道要把数据发到那一个Logic Service呢？这里就需要场景管理服务了，根据我的想法，我想在场景管理服务里提供一个用户代理，用户代理知道用户在那个场景中，代理了用户登录场景，离开场景的行为，以及帮助用户将数据转发到正确的场景服务上，所以结构图继续进化成下图：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;&amp;nbsp;Logic-Service &amp;nbsp; Logic-Service &amp;nbsp; &amp;nbsp;DB-Service&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ------------------------------------&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Scene Manager&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|&lt;/p&gt;&#xD;
&lt;p&gt;Front Server&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Client&lt;br /&gt;由于Front Server的数据都由场景管理服务器转发到场景上，所以我们在前端可以部署多个Front Server，因为一个Front Server只有100M的带宽，当Front Server性能不足或者带宽不足的时候我们可以通过两个来搞定，而Scene Manager只通过用户代理来做包转发，所以承载能力相当的高。再次增强后系统如下图：&lt;br /&gt;&amp;nbsp;Logic-Service &amp;nbsp; Logic-Service &amp;nbsp; &amp;nbsp;DB-Service&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;------------------------------------&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Scene Manager&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;----------------&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Front Server &amp;nbsp; Front Server&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Client &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Client&lt;/p&gt;&#xD;
&lt;p&gt;考虑到Front Server有可能会存在CPU剩余的情况，所以也可以将一部分瞬时事件交给Front Server来处理，当然有一个公共的很耗时的瞬时逻辑需要被剥离出来，那就是登录的逻辑，登录的逻辑每一组服务器都一样，所以我们可以将N组服务器的登录交给一个统一的登录服务器来处理，所以我们再次进化&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Logic-Service &amp;nbsp; Logic-Service &amp;nbsp; &amp;nbsp;DB-Service&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -----------------------------------&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Scene Manager&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -------------------------------------&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Front Server &amp;nbsp; Front Server &amp;nbsp; &amp;nbsp; Login Server&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Client &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Client &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;现在看起来大体上已经有点模样了，但是其实还可以根据不同的需求做一些细节上的调整，比如怪物的AI运算，如果仅仅是很简单的逻辑运算，其实就可以直接在场景服务器的逻辑中处理了（其实有点像把怪物当作了场景的一部分）。如果需要很复杂的AI，就需要将怪物的AI拿到单独的进程里运算了，其实就是把怪物当成一个特殊的玩家来对待，这种模式比较特殊，由于比较耗资源，一般都对大BOSS采用这种方式。&lt;br /&gt;写了这么多也不知道是不是说明白道清楚了，不过今天先说到此处打住，下一回我们从细节上来看这每一部分的具体设计，或许还有部分实现。如果在我下一篇写出来前有兴趣和我继续讨论的可以加MSN superpowerlee@hotmail.com或者Gtalk superpowerlee@gmail.com&lt;br /&gt;感谢iiegg的刘洋以及王秋婷同学给我的大力支持，作为一个新人来说得到业界前辈的无私帮助真是非常幸运的事情。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;本文为亚历山大同志独立思考之结果，有可能在最终结果可能于某些网络上已有资料不谋而合，皆因为相同产品设计理念相同，非抄袭之过。本文欢迎讨论，欢迎转载，如转载请注明出处，谢谢。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1882332.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Alexander-Lee/archive/2010/11/20/ViewOfHightPerformanceMMORPGGameServer.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Alexander-Lee/archive/2010/11/04/1869400.html</id><title type="text">蛋痛的腾讯把WebQQ自杀了</title><summary type="text">昨天在QQ上转发了3次 网民告腾讯书，两秒后我的QQ就被踢下线，然后再次登录后被告知QQ号因为安全问题被冻结，因为正在跟朋友侃这件事情所以用手机激活的方式打算解冻，那知道根据QQ网站的提示发一次，短信告知命令不存在，发两次还是告知命令不存在，最后在几分钟后突然又回复出一条验证码短信这才算激活了QQ号码。这还是昨天的情况，今天的新黄历是蛋痛的腾讯把自己的WebQQ也自杀掉了，见下图不知道这个情况是腾...</summary><published>2010-11-04T13:16:00Z</published><updated>2010-11-04T13:16:00Z</updated><author><name>亚历山大同志</name><uri>http://www.cnblogs.com/Alexander-Lee/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Alexander-Lee/archive/2010/11/04/1869400.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Alexander-Lee/archive/2010/11/04/1869400.html"/><content type="html">&lt;p&gt;&lt;br /&gt;昨天在QQ上转发了3次 网民告腾讯书，两秒后我的QQ就被踢下线，然后再次登录后被告知QQ号因为安全问题被冻结，因为正在跟朋友侃这件事情所以用手机激活的方式打算解冻，那知道根据QQ网站的提示发一次，短信告知命令不存在，发两次还是告知命令不存在，最后在几分钟后突然又回复出一条验证码短信这才算激活了QQ号码。这还是昨天的情况，今天的新黄历是蛋痛的腾讯把自己的WebQQ也自杀掉了，见下图&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/Screenshot.jpg" alt="" width="1024" height="576" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="file:///home/alex/Pictures/Screenshot.jpg" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;不知道这个情况是腾讯的误伤还是故意的，因为大家看图也知道，我用的Ubuntu系统上是不会有360存在的，如果是前者那么我非常质疑腾讯的技术实例，如果是后者那么我只有质疑腾讯的RP了。&lt;/p&gt;&#xD;
&lt;p&gt;作为一个互联网公司来说，如果免费用户的权益就不是权益，免费用户的尊严就能随意践踏的话，那么这家公司最好立马倒掉，哪怕这家公司号称民族互联网企业的骄傲，6亿用户，不管是付钱没付钱的统统成了被腾讯绑架的人质，被绑架的是6亿多用户在网上的社会关系。&lt;/p&gt;&#xD;
&lt;p&gt;当然作为打酱油的友邦，更让我惊诧的是居然有网友这样的回复：&lt;/p&gt;&#xD;
&lt;p&gt;小AI：楼主你不是在自打嘴巴吗，你编上QQ，边骂，那三个字应该用在你身上啊&lt;/p&gt;&#xD;
&lt;p&gt;真是很惊诧了，作为一个用户，不管是付费的还是没付费的，都是有自己的权益的，当自己权益受到侵害的时候，哪怕是抱怨都能有人这样打自己嘴巴，这真是悲哀了。&lt;/p&gt;&#xD;
&lt;p&gt;换句话说，这6亿用户付费的有一亿没？就算有吧，那么试想，如果没有另外5亿没给钱的，&amp;ldquo;吃白食&amp;rdquo;的免费用户，另外一亿人还能留下一半不？&lt;/p&gt;&#xD;
&lt;p&gt;从现在开始我会从自己做起，劝说身边的人不要使用QQ这种封闭的，可怕的软件，摆脱腾讯的控制&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1869400.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Alexander-Lee/archive/2010/11/04/1869400.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Alexander-Lee/archive/2010/09/16/1827587.html</id><title type="text">一个很Cool的Idear-&amp;gt;Python的尾递归优化</title><summary type="text">偶然在国外一个网站瞅到的，非常的酷，发出来共享一下。一般来说，Python和Java，C#一样是没有尾递归自动优化的能力的，递归调用受到调用栈长度的限制被广泛的诟病，但是这个狂人用一个匪夷所思的方法解决了这个问题并在Python上实现了，从此Python的递归调用再也不用受到调用栈长度的制约，太酷了。首先我们还是从递归说起，之前我发过一篇 《浅谈递归过程以及递归的优化》其中用到了斐波那契数来作为例...</summary><published>2010-09-15T16:46:00Z</published><updated>2010-09-15T16:46:00Z</updated><author><name>亚历山大同志</name><uri>http://www.cnblogs.com/Alexander-Lee/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Alexander-Lee/archive/2010/09/16/1827587.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Alexander-Lee/archive/2010/09/16/1827587.html"/><content type="html">&lt;p&gt;偶然在国外一个网站瞅到的，非常的酷，发出来共享一下。一般来说，Python和Java，C#一样是没有尾递归自动优化的能力的，递归调用受到调用栈长度的限制被广泛的诟病，但是这个狂人用一个匪夷所思的方法解决了这个问题并在Python上实现了，从此Python的递归调用再也不用受到调用栈长度的制约，太酷了。&lt;/p&gt;&lt;p&gt;首先我们还是从递归说起，之前我发过一篇 《&lt;span  style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; line-height: 19px; font-size: 13px; font-weight: bold; "&gt;&lt;a id="homepage1_HomePageDays_DaysList_ctl09_DayItem_DayList_ctl00_TitleUrl" href="http://www.cnblogs.com/Alexander-Lee/archive/2010/07/21/1782543.html" style="color: #0066aa; text-decoration: none; "&gt;浅谈递归过程以及递归的优化&lt;/a&gt;&lt;/span&gt;》其中用到了&lt;span  style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; line-height: 19px; font-size: 13px; "&gt;斐波那契数来作为例子.线性递归的算法由于太过一低效就被我们Pass掉了，我们先来看尾递过方式的调用：&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;def&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Fib(n,b1&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,b2&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,c&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;):&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;n&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;n&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;c:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;b1&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;b2&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;8&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Fib(n,b1&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;b2,b2&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;b1&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;b2,c&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;c&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;9&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;这段程序我们来测试一下，调用 Fib(1001)结果：&lt;/p&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; def Fib(n,b1=1,b2=1,c=3):&lt;/p&gt;&lt;p&gt;... &amp;nbsp; &amp;nbsp; if n&amp;lt;3:&lt;/p&gt;&lt;p&gt;... &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return 1&lt;/p&gt;&lt;p&gt;... &amp;nbsp; &amp;nbsp; else:&lt;/p&gt;&lt;p&gt;... &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if n==c:&lt;/p&gt;&lt;p&gt;... &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return b1+b2&lt;/p&gt;&lt;p&gt;... &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else:&lt;/p&gt;&lt;p&gt;... &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return Fib(n,b1=b2,b2=b1+b2,c=c+1)&lt;/p&gt;&lt;p&gt;...&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; Fib(1001)&lt;/p&gt;&lt;p&gt;70330367711422815821835254877183549770181269836358732742604905087154537118196933579742249494562611733487750449241765991088186363265450223647106012053374121273867339111198139373125598767690091902245245323403501L&lt;/p&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;如果我们用Fib(1002)，结果，茶几了，如下：&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;.....&lt;/p&gt;&lt;p&gt;File "&amp;lt;stdin&amp;gt;", line 8, in Fib&lt;/p&gt;&lt;p&gt;File "&amp;lt;stdin&amp;gt;", line 8, in Fib&lt;/p&gt;&lt;p&gt;File "&amp;lt;stdin&amp;gt;", line 8, in Fib&lt;/p&gt;&lt;p&gt;File "&amp;lt;stdin&amp;gt;", line 8, in Fib&lt;/p&gt;&lt;p&gt;File "&amp;lt;stdin&amp;gt;", line 8, in Fib&lt;/p&gt;&lt;p&gt;File "&amp;lt;stdin&amp;gt;", line 8, in Fib&lt;/p&gt;&lt;p&gt;RuntimeError: maximum recursion depth exceeded&lt;/p&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;好了，现在我们来尾递归优化&lt;/p&gt;&lt;p&gt;我们给刚才的Fib函数增加一个Decorator,如下：&lt;/p&gt;&lt;p&gt;&lt;span  style="font-family: 'Courier New'; font-size: 13px; "&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;@tail_call_optimized&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;def&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Fib(n,b1&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,b2&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,c&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;):&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;n&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;n&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;c:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;b1&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;b2&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;8&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;9&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Fib(n,b1&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;b2,b2&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;b1&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;b2,c&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;c&lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;恩，就是这个@tail_call_optimized的装饰器 ，这个装饰器使Python神奇的打破了调用栈的限制。&lt;/p&gt;&lt;p&gt;这下即使我们Fib(20000)，也能在780ms跑出结果（780ms是以前博文提到那台2000元的上网本跑出来的结果）&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;不卖关子了，下面我们来看看这段神奇的代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;sys&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;TailRecurseException:&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;def&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;__init__&lt;/span&gt;&lt;span style="color: #000000;"&gt;(self,&amp;nbsp;args,&amp;nbsp;kwargs):&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.args&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;args&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.kwargs&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;kwargs&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;def&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;tail_call_optimized(g):&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"""&lt;/span&gt;&lt;span style="color: #800000;"&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;&amp;nbsp;&lt;span style="color: #800000;"&gt;&amp;nbsp;&amp;nbsp;This&amp;nbsp;function&amp;nbsp;decorates&amp;nbsp;a&amp;nbsp;function&amp;nbsp;with&amp;nbsp;tail&amp;nbsp;call&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt;&amp;nbsp;&lt;span style="color: #800000;"&gt;&amp;nbsp;&amp;nbsp;optimization.&amp;nbsp;It&amp;nbsp;does&amp;nbsp;this&amp;nbsp;by&amp;nbsp;throwing&amp;nbsp;an&amp;nbsp;exception&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;&amp;nbsp;&lt;span style="color: #800000;"&gt;&amp;nbsp;&amp;nbsp;if&amp;nbsp;it&amp;nbsp;is&amp;nbsp;it's&amp;nbsp;own&amp;nbsp;grandparent,&amp;nbsp;and&amp;nbsp;catching&amp;nbsp;such&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;&amp;nbsp;&lt;span style="color: #800000;"&gt;&amp;nbsp;&amp;nbsp;exceptions&amp;nbsp;to&amp;nbsp;fake&amp;nbsp;the&amp;nbsp;tail&amp;nbsp;call&amp;nbsp;optimization.&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt;&amp;nbsp;&lt;span style="color: #800000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt;&amp;nbsp;&lt;span style="color: #800000;"&gt;&amp;nbsp;&amp;nbsp;This&amp;nbsp;function&amp;nbsp;fails&amp;nbsp;if&amp;nbsp;the&amp;nbsp;decorated&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt;&amp;nbsp;&lt;span style="color: #800000;"&gt;&amp;nbsp;&amp;nbsp;function&amp;nbsp;recurses&amp;nbsp;in&amp;nbsp;a&amp;nbsp;non-tail&amp;nbsp;context.&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt;&amp;nbsp;&lt;span style="color: #800000;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"""&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;def&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;func(&lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;args,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;**&lt;/span&gt;&lt;span style="color: #000000;"&gt;kwargs):&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;sys._getframe()&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;f.f_back&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;and&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;f.f_back.f_back&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;and&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;f.f_back.f_back.f_code&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;f.f_code:&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;raise&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;TailRecurseException(args,&amp;nbsp;kwargs)&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;while&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;try&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;25&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;g(&lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;args,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;**&lt;/span&gt;&lt;span style="color: #000000;"&gt;kwargs)&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;26&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;except&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;TailRecurseException,&amp;nbsp;e:&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;27&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;args&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;e.args&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;28&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;kwargs&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;e.kwargs&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;29&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;func.&lt;/span&gt;&lt;span style="color: #800080;"&gt;__doc__&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;g.&lt;/span&gt;&lt;span style="color: #800080;"&gt;__doc__&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;30&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;func&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;31&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;使用的方法前面已经展示了，令我感到大开眼界的是，作者用了抛出异常然后自己捕获的方式来打破调用栈的增长，简直是太匪夷所思了。而且效率问题，和直接尾递归Fib相比大概造成了五倍的时间开销。&lt;/p&gt;&lt;p&gt;最后很不可思议的，尾递归优化的目的达成了。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;本代码的出处：&lt;a href="http://code.activestate.com/recipes/474088/"&gt;http://code.activestate.com/recipes/474088/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;还有一个JavaScript的实现：&lt;span  style="font-family: arial, helvetica, clean, sans-serif; line-height: 19px; color: #333333; "&gt;&lt;a href="http://w3future.com/weblog/2006/02/#tailCallEliminationInJavascript" rel="nofollow" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; outline-width: 0px; outline-style: initial; outline-color: initial; font-size: 14px; vertical-align: baseline; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; color: #026981; background-position: initial initial; background-repeat: initial initial; "&gt;http://w3future.com/weblog/2006/02/#tailCallEliminationInJavascript&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;如果有同学出了C#或者Java的实现,请发出来供大家瞻仰，呵呵&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1827587.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Alexander-Lee/archive/2010/09/16/1827587.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Alexander-Lee/archive/2010/09/13/1825353.html</id><title type="text">手把手教你自己写一个js表单验证框架</title><summary type="text">其实我自己也就能简单用用js而已，但是呢，相对很多初学者来说多懂了点Know How所以斗胆孟浪一下，将一些所得记录下来，以供更多的初学者能够知道一个东西的实现过程，省去在源码里摸索的过程。在表单程序中，在页面上需要很多的Js代码来验证表单，每一个field是否必须填写，是否只能是数字，是否需要ajax到远程验证,blablabla。</summary><published>2010-09-13T15:38:00Z</published><updated>2010-09-13T15:38:00Z</updated><author><name>亚历山大同志</name><uri>http://www.cnblogs.com/Alexander-Lee/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Alexander-Lee/archive/2010/09/13/1825353.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Alexander-Lee/archive/2010/09/13/1825353.html"/><content type="html">&lt;div&gt;其实我自己也就能简单用用js而已，但是呢，相对很多初学者来说多懂了点Know How所以斗&lt;/div&gt;&lt;div&gt;胆孟浪一下，将一些所得记录下来，以供更多的初学者能够知道一个东西的实现过程，省去&lt;/div&gt;&lt;div&gt;在源码里摸索的过程。&lt;/div&gt;&lt;div&gt;在表单程序中，在页面上需要很多的Js代码来验证表单，每一个field是否必须填写，是否&lt;/div&gt;&lt;div&gt;只能是数字，是否需要ajax到远程验证,blablabla。&lt;/div&gt;&lt;div&gt;如果一个一个单独写势必非常的繁琐，所以我们的第一个目标就是构建一个类似DSL的东西，&lt;/div&gt;&lt;div&gt;用表述的语句而非控制语句来实现验证。&lt;/div&gt;&lt;div&gt;其次一个个单独写的话还有一个问题就是必须全部验证通过才能提交，但是单独验证会因为&lt;/div&gt;&lt;div&gt;这个特征而增加很多额外的控制代码，且经常会验证不全面。所以第二个目标就是能够全面&lt;/div&gt;&lt;div&gt;的整合整个验证的过程。&lt;/div&gt;&lt;div&gt;最后不能是一个无法扩展的一切写死的实现，必要的扩展性还是要的。&lt;/div&gt;&lt;div&gt;首先，我们需要一个能够描述对字段验证的类&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('b22c5c8e-de6e-4185-8e1f-266b2094f3df')"&gt;&lt;img src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"  id="code_img_opened_56e56e6a-e2ea-4f09-92fe-1b1849134fd4" onclick="cnblogs_code_hide('56e56e6a-e2ea-4f09-92fe-1b1849134fd4',event)"&gt;&lt;div id="cnblogs_code_open_56e56e6a-e2ea-4f09-92fe-1b1849134fd4"&gt;&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;meta&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;http-equiv&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="Content-Type"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;content&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="text/html;&amp;nbsp;charset=utf-8"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;test&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;src&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="jquery-1.4.2.min.js"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;src&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="kernel.js"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #0000FF;"&gt;var&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;form;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;$(&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #0000FF;"&gt;function&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;(){&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #0000FF;"&gt;var&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;uf&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;UserForm([&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;Field({&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fid:&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;f1&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;,&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;val:[&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;Len_val(&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;1&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;,&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;5&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;,&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;长度错误&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;),&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;Exp_val(v_int,&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;不是数字&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;)],&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;suc:&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #0000FF;"&gt;function&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;(text){&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$(&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;t1&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;).val(&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;''&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$(&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;t1&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;).attr(&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;class&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;,&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;suc&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;err:&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #0000FF;"&gt;function&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;(text){&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;t1&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;).val(text);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$(&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;t1&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;).attr(&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;class&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;,&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;error&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;'&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uf.set_submit(&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;25&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;bt&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;,&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;26&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #0000FF;"&gt;function&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;(form){&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;27&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert(&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;表单已经提交了&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;28&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;29&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;30&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;31&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;32&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;33&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;style&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;34&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;.suc&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;{&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #FF0000;"&gt;&amp;nbsp;background-color&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #0000FF;"&gt;#00ff00&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;}&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;35&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;.error&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;{&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #FF0000;"&gt;&amp;nbsp;background-color&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;:&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #0000FF;"&gt;#ff0000&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;;&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #000000;"&gt;}&lt;/span&gt;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;36&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: #F5F5F5; color: #800000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;style&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;37&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;38&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;39&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;input&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="text"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;id&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="f1"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;name&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="f1"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;span&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="t1"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;span&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;br&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;40&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;input&amp;nbsp;&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="button"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;id&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="bt"&lt;/span&gt;&lt;span style="color: #FF0000;"&gt;&amp;nbsp;value&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;="提交"&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;41&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;42&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;要注意的地方就是在&lt;span style="color: red; "&gt;&lt;strong&gt;循环中使用闭包会茶几&lt;/strong&gt;&lt;/span&gt;，必须用一个方法来代理一下，呵呵&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;希望对初学js但是还不知道该做点什么怎么做的朋友能有所帮助&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1825353.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Alexander-Lee/archive/2010/09/13/1825353.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/Alexander-Lee/archive/2010/09/08/1821049.html</id><title type="text">Bottle(Flask)样的tornado开发</title><summary type="text">起因：今年春节后发现有个tornado web的东西，app server+web framework的集合体，正好工作中有个项目需要其中的异步远程调用的特性，遂研究之，用到现在感触良多，其性能尚可，但是作为Web Framework看来其封装方式我并不喜欢，窃以为不够紧凑，需要设置的地方不够清晰，很多功能的使用稍显繁琐。并且在新创建一个app的时候如果不参看已有的app做为参考，重头写起来很困难...</summary><published>2010-09-07T16:16:00Z</published><updated>2010-09-07T16:16:00Z</updated><author><name>亚历山大同志</name><uri>http://www.cnblogs.com/Alexander-Lee/</uri></author><link rel="alternate" href="http://www.cnblogs.com/Alexander-Lee/archive/2010/09/08/1821049.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/Alexander-Lee/archive/2010/09/08/1821049.html"/><content type="html">&lt;p&gt;&lt;strong&gt;起因：&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;今年春节后发现有个tornado web的东西，app server+web framework的集合体，正好工作&lt;/div&gt;&lt;div&gt;中有个项目需要其中的异步远程调用的特性，遂研究之，用到现在感触良多，其性能尚可，&lt;/div&gt;&lt;div&gt;但是作为Web Framework看来其封装方式我并不喜欢，窃以为不够紧凑，需要设置的地方不&lt;/div&gt;&lt;div&gt;够清晰，很多功能的使用稍显繁琐。并且在新创建一个app的时候如果不参看已有的app做为&lt;/div&gt;&lt;div&gt;参考，重头写起来很困难。&lt;/div&gt;&lt;div&gt;举个例子 ：&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('7fb61ccd-78bb-47bb-bf2a-36117c906bc0')"&gt;&lt;img src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"  id="code_img_opened_7fb61ccd-78bb-47bb-bf2a-36117c906bc0" onclick="cnblogs_code_hide('7fb61ccd-78bb-47bb-bf2a-36117c906bc0',event)"&gt;&lt;div id="cnblogs_code_open_7fb61ccd-78bb-47bb-bf2a-36117c906bc0"&gt;&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;tornado.httpserver&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;tornado.ioloop&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;tornado.options&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;tornado.web&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;from&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;tornado.options&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;define,&amp;nbsp;options&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;define(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;port&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;default&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;8888&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;help&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;run&amp;nbsp;on&amp;nbsp;the&amp;nbsp;given&amp;nbsp;port&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;type&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;int)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;MainHandler(tornado.web.RequestHandler):&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;def&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;get(self):&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.write(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Hello,&amp;nbsp;world&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;def&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;main():&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tornado.options.parse_command_line()&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;application&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;tornado.web.Application([&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(r&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;MainHandler),&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;])&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http_server&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;tornado.httpserver.HTTPServer(application)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http_server.listen(options.port)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tornado.ioloop.IOLoop.instance().start()&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;__name__&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;__main__&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;25&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;main()&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;26&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;从官网的例子就能看出，首先启动一个服务就很麻烦了，加之Python在开发的时候智能感知&lt;/div&gt;&lt;div&gt;能起的作用不是很大，所以开发起来相当的纠结。而且其中我最需要的远程页面异步访问的&lt;/div&gt;&lt;div&gt;功能，就需要涉及到N个地方。&lt;/div&gt;&lt;div&gt;最近新出的Flask，Bottle等框架简洁的API让我很是眼热，但是如果在tornado后端用wsgi&lt;/div&gt;&lt;div&gt;来使用Bottle又没有办法使用异步远程访问，相当于阉割了一个我最需要的功能，所以怒由&lt;/div&gt;&lt;div&gt;心中起恶向胆边生，自起炉灶在tornado的Web Framework基础上实现了这个东西，由于是简&lt;/div&gt;&lt;div&gt;化了tornado的开发方式，所以就称之为 easytor 吧&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;从DEMO开始：&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;同样是实现一个HelloWorld的APP，我们用easytor来做做看：&lt;/div&gt;&lt;div&gt;easytor只有一个文件，你可以直接放在项目的目录中，或者安装后使用&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;from&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;easytor.app&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;apprun,route&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;@route(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;^/hello/([^/]+)$&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;def&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;hello(tor,name):&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;u&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;hello&amp;nbsp;%s&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;%&lt;/span&gt;&lt;span style="color: #000000;"&gt;name&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;__name__&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;__main__&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;8&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;apprun()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;我们import easytor.app模块中的 apprun和route，apprun是启动服务器的方法，而route&lt;/div&gt;&lt;div&gt;是一个Decorator，用来把一个handler函数和映射到的url一起注册到easytor的处理器列表&lt;/div&gt;&lt;div&gt;中。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;url映射：&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;easytor中定义了很多Decorator，用于注册一些特定方法并挂载到相应的事件中。最重要的&lt;/div&gt;&lt;div&gt;就是route。&lt;/div&gt;&lt;div&gt;用route注册的函数至少有一个参数，第一个参数是tornado的handler对象，访问参数，&lt;/div&gt;&lt;div&gt;headers，cookie，是从这个参数开始，详细的内容参见tornado的文档。&lt;/div&gt;&lt;div&gt;url映射通过route这个Decorator来注册，同时route还可以通过参数指定访问这个url是否&lt;/div&gt;&lt;div&gt;需要认证，是否是Ajax请求和接受请求的方法。&lt;/div&gt;&lt;div&gt;route可以将正则表达式中的组取出来成为Handler函数的参数，如同Demo里那样，如果访问&lt;/div&gt;&lt;div&gt;/hello/alex，就显示 hello alex&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;输出Response：&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;easytor通过Handler函数的返回值向浏览器输出内容，返回值可以是str,unicode，或者几&lt;/div&gt;&lt;div&gt;个包装类，json,view,static_file,redirect,remote,async。实例化后将实例直接return&amp;nbsp;&lt;/div&gt;&lt;div&gt;即可。&lt;/div&gt;&lt;div&gt;比如要输出json，只需要&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;json(dict(name&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;alex&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;view用于包装render输出数据到模板。&lt;/div&gt;&lt;div&gt;redirect用于专跳页面。&lt;/div&gt;&lt;div&gt;remote是对远程异步获取页面的封装&lt;/div&gt;&lt;div&gt;async是一个空包装，用于挂起当前的请求（详见tornado的Demo：chat）&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;异步访问：&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;异步访问通过remote类来实现，看下面的例子：&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;@route(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;^/remoteacc$&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;def&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;get_page(tor):&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;remote(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;http://target..&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,method&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;GET&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;def&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;on_get_page(tor,response):&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;response.body&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;对比tornado原本的例子，可以看到整个API简单了不少&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;目的：&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;span style="font-size: 18pt; color: red; "&gt;少写代码，少写代码，还是少写代码&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;项目地址：http://bitbucket.org/alexander_lee/easytor&lt;/div&gt;&lt;div&gt;如果你也在用，或者打算用tornado来构建自己的Web应用，不妨试试easytor&lt;/div&gt;&lt;div&gt;同时也期待你的加入&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;PS:项目文档整理中，DEMO正在写，代码8号中午push上来&lt;/div&gt;&lt;p&gt;下一步目标：植入Session支持的扩展接口，加入fsdal代替tornado本身的数据访问模块&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1821049.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/Alexander-Lee/archive/2010/09/08/1821049.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
