-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathservices-python-threads-tornado-rabbitmq.html
More file actions
161 lines (132 loc) · 8.51 KB
/
services-python-threads-tornado-rabbitmq.html
File metadata and controls
161 lines (132 loc) · 8.51 KB
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
<!DOCTYPE html>
<html lang="en" itemscope itemtype="http://schema.org/Article">
<head>
<title>Running services in Python as threads: Tornado server and RabbitMQ client</title>
<meta charset="utf-8">
<meta property="og:title" content="Running services in Python as threads: Tornado server and RabbitMQ client">
<meta property="og:site_name" content="Modesto Mas | Blog">
<meta property="og:image" content="https://mmas.github.io/images/profile.jpg">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta property="og:url" content="https://mmas.github.io/services-python-threads-tornado-rabbitmq">
<meta property="og:locale" content="en_GB">
<meta name="twitter:image" content="https://mmas.github.io/images/profile.jpg">
<meta name="twitter:url" content="https://mmas.github.io/services-python-threads-tornado-rabbitmq">
<meta name="twitter:card" content="summary">
<meta name="twitter:domain" content="mmas.github.io">
<meta name="twitter:title" content="Running services in Python as threads: Tornado server and RabbitMQ client">
<meta name="description" content="Using the threading module we can easily start multiple services in our application. In this simple example we are going to run a Tornado web server a...">
<meta name="twitter:description" content="Using the threading module we can easily start multiple services in our application. In this simple example we are going to run a Tornado web server a...">
<meta property="og:description" content="Using the threading module we can easily start multiple services in our application. In this simple example we are going to run a Tornado web server a...">
<meta name="keywords" content="multithreading,python,rabbitmq,tornado">
<meta property="og:type" content="blog">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta property="og:type" content="article">
<meta property="article:author" content="https://github.com/mmas">
<meta property="article:section" content="multithreading">
<meta property="article:tag" content="multithreading,python,rabbitmq,tornado">
<meta property="article:published_time" content="2017-07-07">
<meta property="article:modified_time" content="2017-07-07">
<link rel="stylesheet" type="text/css" href="/css/main.css">
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
CommonHTML: {
scale: 93,
showMathMenu: false
},
tex2jax: {
"inlineMath": [["$","$"], ["\\(","\\)"]]
}
});
</script>
<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"></script>
</head>
<body class="entry-detail">
<header>
<div>
<img src="https://mmas.github.io/images/profile.jpg">
<a class="brand" href="/">Modesto Mas</a>
<span>Data/Python/DevOps Engineer</span>
<nav>
<ul>
<li><a href="/tags">Tags</a></li>
<li><a href="https://github.com/mmas/mmas.github.io/issues" target="_blank">Issues</a></li>
</ul>
</nav>
</div>
</header>
<section id="content" role="main">
<article>
<header>
<h1><a href="/services-python-threads-tornado-rabbitmq">Running services in Python as threads: Tornado server and RabbitMQ client</a></h1>
<time datetime="2017-07-07">Jul 07, 2017</time>
<a class="tag" href="/tags?tag=multithreading">multithreading</a>
<a class="tag" href="/tags?tag=python">python</a>
<a class="tag" href="/tags?tag=rabbitmq">rabbitmq</a>
<a class="tag" href="/tags?tag=tornado">tornado</a>
</header>
<aside id="article-nav"></aside>
<section class="body">
<p>Using the <a target="_blank" href="https://docs.python.org/2/library/threading.html">threading</a> module we can easily start multiple services in our application. In this simple example we are going to run a <a target="_blank" href="http://www.tornadoweb.org/en/stable/">Tornado</a> web server and a <a target="_blank" href="https://www.rabbitmq.com/">RabbitMQ</a> consumer queue using <a target="_blank" href="https://pika.readthedocs.io">Pika</a>.</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="im">import</span> threading
<span class="im">import</span> pika
<span class="im">import</span> tornado.ioloop
<span class="im">import</span> tornado.web</code></pre></div>
<p>Define a Tornado application with an endpoint to publish a message into the <code>"test"</code> queue:</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="kw">class</span> MessageHandler(tornado.web.RequestHandler):
<span class="kw">def</span> post(<span class="va">self</span>):
<span class="bu">print</span> <span class="st">'POST /'</span>
channel.basic_publish(exchange<span class="op">=</span><span class="st">''</span>,
routing_key<span class="op">=</span><span class="st">'test'</span>,
body<span class="op">=</span><span class="va">self</span>.get_argument(<span class="st">'message'</span>))
<span class="va">self</span>.set_status(<span class="dv">202</span>)
<span class="kw">def</span> run_tornado():
<span class="bu">print</span> <span class="st">'running tornado...'</span>
app <span class="op">=</span> tornado.web.Application([(<span class="vs">r'/'</span>, MessageHandler)])
app.listen(<span class="dv">8888</span>)
ioloop.start()</code></pre></div>
<p>Create a RabbitMQ consumer and print the messages received:</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="kw">def</span> consumer_callback(channel, method, properties, body):
<span class="bu">print</span> <span class="st">'message received: "</span><span class="sc">%s</span><span class="st">"'</span> <span class="op">%</span> body
<span class="kw">def</span> run_pika():
<span class="bu">print</span> <span class="st">'running pika...'</span>
channel.basic_consume(consumer_callback, queue<span class="op">=</span><span class="st">'test'</span>)
channel.start_consuming()</code></pre></div>
<p>In the <code>__main__</code> define the Tornado event loop and the RabbitMQ channel, run the two services as daemons and allow the user to exit:</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">'__main__'</span>:
ioloop <span class="op">=</span> tornado.ioloop.IOLoop.instance()
rabbit <span class="op">=</span> pika.BlockingConnection()
channel <span class="op">=</span> rabbit.channel()
channel.queue_declare(queue<span class="op">=</span><span class="st">'test'</span>)
<span class="cf">for</span> target <span class="op">in</span> (run_pika, run_tornado):
thread <span class="op">=</span> threading.Thread(target<span class="op">=</span>target)
thread.daemon <span class="op">=</span> <span class="va">True</span>
thread.start()
<span class="bu">print</span> <span class="st">'services running, press ctrl+c to stop'</span>
<span class="cf">try</span>:
<span class="cf">while</span> <span class="va">True</span>:
<span class="bu">raw_input</span>(<span class="st">''</span>)
<span class="cf">except</span> <span class="pp">KeyboardInterrupt</span>:
<span class="bu">print</span> <span class="st">'stopping services...'</span>
ioloop.stop()
<span class="bu">print</span> <span class="st">'tornado server stopped'</span>
rabbit.close()
<span class="bu">print</span> <span class="st">'rabbitmq connection closed'</span>
exit(<span class="dv">0</span>)</code></pre></div>
<p>To test it, run the file:</p>
<pre><code>$ python app.py
running pika...
running tornado...
services running, press ctrl+c to stop</code></pre>
<p>Send a message to the queue via the web server:</p>
<pre><code>$ curl -X POST --data "message=hello world" localhost:8888</code></pre>
<p>The message will be printed in the terminal window where you run the file as:</p>
<pre><code>[...]
message received: "hello world"</code></pre>
</section>
</article>
</section>
<footer></footer>
<script type="text/javascript" src="/js/article.js"></script>
</body>
</html>