summaryrefslogtreecommitdiff
path: root/docs/_locale/zh_CN/LC_MESSAGES/async.po
blob: 8b2ea4cdca00dc380fdb1da3f8ab05d6ef7b5903 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2009-2017, Marcel Hellkamp
# This file is distributed under the same license as the Bottle package.
# 
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: bottle\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-12-19 14:15+0100\n"
"PO-Revision-Date: 2015-12-13 21:06+0000\n"
"Last-Translator: Thiago Avelino <thiago@avelino.xxx>\n"
"Language-Team: Chinese (China) (http://www.transifex.com/bottle/bottle/language/zh_CN/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_CN\n"
"Plural-Forms: nplurals=1; plural=0;\n"

#: ../../async.rst:2
msgid "Primer to Asynchronous Applications"
msgstr "异步应用入门"

#: ../../async.rst:4
msgid ""
"Asynchronous design patterns don't mix well with the synchronous nature of "
"`WSGI <http://www.python.org/dev/peps/pep-3333/>`_. This is why most "
"asynchronous frameworks (tornado, twisted, ...) implement a specialized API "
"to expose their asynchronous features. Bottle is a WSGI framework and shares"
" the synchronous nature of WSGI, but thanks to the awesome `gevent project "
"<http://www.gevent.org/>`_, it is still possible to write asynchronous "
"applications with bottle. This article documents the usage of Bottle with "
"Asynchronous WSGI."
msgstr "异步设计模式和 `WSGI <http://www.python.org/dev/peps/pep-3333/>`_ 的同步本质并不能很好地兼容。这就是为什么大部分的异步框架(tornado, twisted, ...)都实现了专有的API来暴露它们的异步特征。Bottle是一个WSGI框架,也继承了WSGI的同步本质,但是谢谢优秀的 `gevent项目 <http://www.gevent.org/>`_ ,我们可以使用Bottle来编写异步应用。这份文档介绍了在Bottle中如何使用异步WSGI。"

#: ../../async.rst:7
msgid "The Limits of Synchronous WSGI"
msgstr "同步WSGI的限制"

#: ../../async.rst:9
msgid ""
"Briefly worded, the `WSGI specification (pep 3333) "
"<http://www.python.org/dev/peps/pep-3333/>`_ defines a request/response "
"circle as follows: The application callable is invoked once for each request"
" and must return a body iterator. The server then iterates over the body and"
" writes each chunk to the socket. As soon as the body iterator is exhausted,"
" the client connection is closed."
msgstr "简单来说, `WSGI标准 (pep 3333) <http://www.python.org/dev/peps/pep-3333/>`_ 定义了下面这一个request/response的循环:每次请求到达的时候,应用中的callable会被调用一次,返回一个主体iterator。接着服务器会遍历该主体,分块写入socket。遍历完整个主体,就关闭客户端的连接。"

#: ../../async.rst:11
msgid ""
"Simple enough, but there is a snag: All this happens synchronously. If your "
"application needs to wait for data (IO, sockets, databases, ...), it must "
"either yield empty strings (busy wait) or block the current thread. Both "
"solutions occupy the handling thread and prevent it from answering new "
"requests. There is consequently only one ongoing request per thread."
msgstr "足够简单,但是存在一个小问题:所有这些都是同步的。如果你的应用需要等待数据(IO, socket, 数据库, ...),除了返回一个空字符串(忙等),就只能阻塞当前线程。两种办法都会占用当前线程,导致线程不能处理新的请求,只能处理当前的一个请求。"

#: ../../async.rst:13
msgid ""
"Most servers limit the number of threads to avoid their relatively high "
"overhead. Pools of 20 or less threads are common. As soon as all threads are"
" occupied, any new connection is stalled. The server is effectively dead for"
" everyone else. If you want to implement a chat that uses long-polling ajax "
"requests to get real-time updates, you'd reach the limited at 20 concurrent "
"connections. That's a pretty small chat."
msgstr "大部分服务器都限制了线程的数量,避免伴随它们而来的资源消耗。常见的是一个线程池,内有20个或更少数量的线程。一旦所有的线程都被占用了,任何新的请求都会阻塞。事实上,对于其他人来说,服务器已经宕机了。如果你想实现一个聊天程序,使用ajax轮询来获取实时消息,很快你就会受到线程数量的限制。这样能同时服务的用户就太少了。"

#: ../../async.rst:16
msgid "Greenlets to the rescue"
msgstr "救星,Greenlet"

#: ../../async.rst:18
msgid ""
"Most servers limit the size of their worker pools to a relatively low number"
" of concurrent threads, due to the high overhead involved in switching "
"between and creating new threads. While threads are cheap compared to "
"processes (forks), they are still expensive to create for each new "
"connection."
msgstr "大多数服务器的线程池都限制了线程池中线程的数量,避免创建和切换线程的代价。尽管和创建进程(fork)的代价比起来,线程还是挺便宜的。但是也没便宜到可以接受为每一个请求创建一个线程。"

#: ../../async.rst:20
msgid ""
"The `gevent <http://www.gevent.org/>`_ module adds *greenlets* to the mix. "
"Greenlets behave similar to traditional threads, but are very cheap to "
"create. A gevent-based server can spawn thousands of greenlets (one for each"
" connection) with almost no overhead. Blocking individual greenlets has no "
"impact on the servers ability to accept new requests. The number of "
"concurrent connections is virtually unlimited."
msgstr "`gevent <http://www.gevent.org/>`_ 模块添加了 *greenlet* 的支持。greenlet和传统的线程类似,但其创建只需消耗很少的资源。基于gevent的服务器可以生成成千上万的greenlet,为每个连接分配一个greenlet也毫无压力。阻塞greenlet,也不会影响到服务器接受新的请求。同时处理的连接数理论上是没有限制的。"

#: ../../async.rst:22
msgid ""
"This makes creating asynchronous applications incredibly easy, because they "
"look and feel like synchronous applications. A gevent-based server is "
"actually not asynchronous, but massively multi-threaded. Here is an "
"example::"
msgstr "这令创建异步应用难以置信的简单,因为它们看起来很想同步程序。基于gevent服务器实际上不是异步的,是大规模多线程。下面是一个例子。"

#: ../../async.rst:39
msgid ""
"The first line is important. It causes gevent to monkey-patch most of "
"Python's blocking APIs to not block the current thread, but pass the CPU to "
"the next greenlet instead. It actually replaces Python's threading with "
"gevent-based pseudo-threads. This is why you can still use ``time.sleep()`` "
"which would normally block the whole thread. If you don't feel comfortable "
"with monkey-patching python built-ins, you can use the corresponding gevent "
"functions (``gevent.sleep()`` in this case)."
msgstr "第一行很重要。它让gevent monkey-patch了大部分Python的阻塞API,让它们不阻塞当前线程,将CPU让给下一个greenlet。它实际上用基于gevent的伪线程替换了Python的线程。这就是你依然可以使用 ``time.sleep()`` 这个照常来说会阻塞线程的函数。如果这种monkey-patch的方式感令你感到不舒服,你依然可以使用gevent中相应的函数 ``gevent.sleep()`` 。"

#: ../../async.rst:41
msgid ""
"If you run this script and point your browser to "
"``http://localhost:8080/stream``, you should see `START`, `MIDDLE`, and "
"`END` show up one by one (rather than waiting 8 seconds to see them all at "
"once). It works exactly as with normal threads, but now your server can "
"handle thousands of concurrent requests without any problems."
msgstr "如果你运行了上面的代码,接着访问 ``http://localhost:8080/stream`` ,你可看到 `START`, `MIDDLE`, 和 `END` 这几个字样依次出现(用时大约8秒)。它像普通的线程一样工作,但是现在你的服务器能同时处理成千上万的连接了。"

#: ../../async.rst:45
msgid ""
"Some browsers buffer a certain amount of data before they start rendering a "
"page. You might need to yield more than a few bytes to see an effect in "
"these browsers. Additionally, many browsers have a limit of one concurrent "
"connection per URL. If this is the case, you can use a second browser or a "
"benchmark tool (e.g. `ab` or `httperf`) to measure performance."
msgstr "一些浏览器在开始渲染一个页面之前,会缓存确定容量的数据。在这些浏览器上,你需要返回更多的数据才能看到效果。另外,很多浏览器限制一个URL只使用一个连接。在这种情况下,你可以使用另外的浏览器,或性能测试工具(例如: `ab` 或 `httperf` )来测试性能。"

#: ../../async.rst:52
msgid "Event Callbacks"
msgstr "事件回调函数"

#: ../../async.rst:54
msgid ""
"A very common design pattern in asynchronous frameworks (including tornado, "
"twisted, node.js and friends) is to use non-blocking APIs and bind callbacks"
" to asynchronous events. The socket object is kept open until it is closed "
"explicitly to allow callbacks to write to the socket at a later point. Here "
"is an example based on the `tornado library "
"<http://www.tornadoweb.org/documentation#non-blocking-asynchronous-"
"requests>`_::"
msgstr "异步框架的常见设计模式(包括 tornado, twisted, node.js 和 friends),是使用非阻塞的API,绑定回调函数到异步事件上面。在显式地关闭之前,socket会保持打开,以便稍后回调函数往socket里面写东西。下面是一个基于 `tornado <http://www.tornadoweb.org/documentation#non-blocking-asynchronous-requests>`_ 的例子。"

#: ../../async.rst:63
msgid ""
"The main benefit is that the request handler terminates early. The handling "
"thread can move on and accept new requests while the callbacks continue to "
"write to sockets of previous requests. This is how these frameworks manage "
"to process a lot of concurrent requests with only a small number of OS "
"threads."
msgstr "主要的好处就是MainHandler能早早结束,在回调函数继续写socket来响应之前的请求的时候,当前线程能继续接受新的请求。这样就是为什么这类框架能同时处理很多请求,只使用很少的操作系统线程。"

#: ../../async.rst:65
msgid ""
"With Gevent+WSGI, things are different: First, terminating early has no "
"benefit because we have an unlimited pool of (pseudo)threads to accept new "
"connections. Second, we cannot terminate early because that would close the "
"socket (as required by WSGI). Third, we must return an iterable to conform "
"to WSGI."
msgstr "对于Gevent和WSGI来说,情况就不一样了:首先,早早结束没有好处,因为我们的(伪)线程池已经没有限制了。第二,我们不能早早结束,因为这样会关闭socket(WSGI要求如此)。第三,我们必须返回一个iterator,以遵守WSGI的约定。"

#: ../../async.rst:67
msgid ""
"In order to conform to the WSGI standard, all we have to do is to return a "
"body iterable that we can write to asynchronously. With the help of "
"`gevent.queue <http://www.gevent.org/gevent.queue.html>`_, we can *simulate*"
" a detached socket and rewrite the previous example as follows::"
msgstr "为了遵循WSGI规范,我们只需返回一个iterable的实体,异步地将其写回客户端。在 `gevent.queue <http://www.gevent.org/gevent.queue.html>`_ 的帮助下,我们可以 *模拟* 一个脱管的socket,上面的例子可写成这样。"

#: ../../async.rst:78
msgid ""
"From the server perspective, the queue object is iterable. It blocks if "
"empty and stops as soon as it reaches ``StopIteration``. This conforms to "
"WSGI. On the application side, the queue object behaves like a non-blocking "
"socket. You can write to it at any time, pass it around and even start a new"
" (pseudo)thread that writes to it asynchronously. This is how long-polling "
"is implemented most of the time."
msgstr "从服务器的角度来看,queue对象是iterable的。如果为空,则阻塞,一旦遇到 ``StopIteration`` 则停止。这符合WSGI规范。从应用的角度来看,queue对象表现的像一个不会阻塞socket。你可以在任何时刻写入数据,pass it around,甚至启动一个新的(伪)线程,异步写入。这是在大部分情况下,实现长轮询。"

#: ../../async.rst:82
msgid "Finally: WebSockets"
msgstr "最后: WebSockets"

#: ../../async.rst:84
msgid ""
"Lets forget about the low-level details for a while and speak about "
"WebSockets. Since you are reading this article, you probably know what "
"WebSockets are: A bidirectional communication channel between a browser "
"(client) and a web application (server)."
msgstr "让我们暂时忘记底层的细节,来谈谈WebSocket。既然你正在阅读这篇文章,你有可能已经知道什么是WebSocket了,一个在浏览器(客户端)和Web应用(服务端)的双向的交流通道。"

#: ../../async.rst:86
msgid ""
"Thankfully the `gevent-websocket <http://pypi.python.org/pypi/gevent-"
"websocket/>`_ package does all the hard work for us. Here is a simple "
"WebSocket endpoint that receives messages and just sends them back to the "
"client::"
msgstr "感谢 `gevent-websocket <http://pypi.python.org/pypi/gevent-websocket/>`_ 包帮我们做的工作。下面是一个WebSocket的简单例子,接受消息然后将其发回客户端。"

#: ../../async.rst:111
msgid ""
"The while-loop runs until the client closes the connection. You get the idea"
" :)"
msgstr "while循环直到客户端关闭连接的时候才会终止。You get the idea :)"

#: ../../async.rst:113
msgid "The client-site JavaScript API is really straight forward, too::"
msgstr "客户端的JavaScript API也十分简洁明了::"