<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Rabbitmq on ZRJ | 学习笔记</title>
        <link>https://blog.zrj.me/tags/rabbitmq/</link>
        <description>Recent content in Rabbitmq on ZRJ | 学习笔记</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-CN</language>
        <lastBuildDate>Wed, 14 Dec 2016 15:50:58 +0800</lastBuildDate><atom:link href="https://blog.zrj.me/tags/rabbitmq/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>离线安装 Python 包 pika</title>
        <link>https://blog.zrj.me/posts/2016-12-14-%E7%A6%BB%E7%BA%BF%E5%AE%89%E8%A3%85-python-%E5%8C%85-pika/</link>
        <pubDate>Wed, 14 Dec 2016 15:50:58 +0800</pubDate>
        
        <guid>https://blog.zrj.me/posts/2016-12-14-%E7%A6%BB%E7%BA%BF%E5%AE%89%E8%A3%85-python-%E5%8C%85-pika/</guid>
        <description>&lt;p&gt;对于 Python 的扩展包，可以使用 pip 的方式进行在线安装，如果需要离线，那么需要先下载安装包（以及其依赖），然后手工安装，例如从 &lt;a class=&#34;link&#34; href=&#34;https://pypi.python.org/pypi/pika&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://pypi.python.org/pypi/pika&lt;/a&gt; 这里，pika-0.10.0.tar.gz (md5) Source 2015-09-02 80KB，然后解压缩，执行 python setup.py install 即可，关于 setup.py，可以参考 &lt;a class=&#34;link&#34; href=&#34;http://blog.csdn.net/lynn&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://blog.csdn.net/lynn&lt;/a&gt;_kong/article/details/17540207 这个文章，说的比较详细了&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;setup函数还有一些参数：&lt;/p&gt;
&lt;p&gt;1、packages 告诉Distutils需要处理那些包（包含__init__.py的文件夹） 2、package_dir 告诉Distutils哪些目录下的文件被映射到哪个源码包。一个例子：package_dir = {&amp;rsquo;&amp;rsquo;: &amp;rsquo;lib&amp;rsquo;}，表示“root package”中的模块都在lib目录中。 3、ext_modules 是一个包含Extension实例的列表，Extension的定义也有一些参数。 4、ext_package 定义extension的相对路径 5、requires 定义依赖哪些模块 6、provides 定义可以为哪些模块提供依赖 7、scripts 指定python源码文件，可以从命令行执行。在安装时指定&amp;ndash;install-script 8、package_data 通常包含与包实现相关的一些数据文件或类似于readme的文件。如果没有提供模板，会被添加到MANIFEST文件中。 9、data_files 指定其他的一些文件（如配置文件）&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;另外，关于使用 Python 收发 RabbitMQ 的消息，可以参考这里 &lt;a class=&#34;link&#34; href=&#34;https://www.rabbitmq.com/tutorials/tutorial-one-python.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://www.rabbitmq.com/tutorials/tutorial-one-python.html&lt;/a&gt; ，但是官方的文档没有提及用户名密码登录验证的参数，参考这里 &lt;a class=&#34;link&#34; href=&#34;https://pika.readthedocs.io/en/latest/modules/parameters.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://pika.readthedocs.io/en/latest/modules/parameters.html&lt;/a&gt; 的文档有补充&lt;/p&gt;
</description>
        </item>
        <item>
        <title>RabbitMQ 消息队列的 Nginx 反向代理</title>
        <link>https://blog.zrj.me/posts/2016-12-14-rabbitmq-%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E7%9A%84-nginx-%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86/</link>
        <pubDate>Wed, 14 Dec 2016 15:18:14 +0800</pubDate>
        
        <guid>https://blog.zrj.me/posts/2016-12-14-rabbitmq-%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E7%9A%84-nginx-%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86/</guid>
        <description>&lt;p&gt;对于 http 协议，大家都知道可以使用 nginx 进行反向代理，那么，对于 RabbitMQ 等有状态的长连接呢？配是能配，但是主要会关心长连接超时的问题。&lt;/p&gt;
&lt;p&gt;先来看看配置是怎么配的&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cat  nginx.conf
#user  nobody;
worker_processes  1;

#error_log  /var/logs/error.log;
#error_log  /var/logs/error.log  notice;
error_log  /var/logs/error.log  info;

pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

stream {
    upstream rabbitmq{
        server xxxxxx:5672;
    }
    server {
        listen 5672;
        proxy_connect_timeout 1s;
        proxy_timeout 3s;
        proxy_pass rabbitmq;

    }  
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;可以看到这里用到一个叫 stream 的东西，这个东西是 nginx 新出用来搞 tcp 代理的， &lt;a class=&#34;link&#34; href=&#34;http://nglua.com/reads/15.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://nglua.com/reads/15.html&lt;/a&gt; 这里有对他的说明和源码分析&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;nginx因为在http服务的优异表现被大众认可，但是它不仅仅是一个http服务器，也是mail代理服务器。现在这个家庭加入了新的成员tcp。其实它在nginx官网的说辞里叫stream，之所以呈现在大家面前是tcp的原因，我猜测是这样的： a：它解决了代理需求，而这需求就是tcp代理，但是它的源码里命名是stream，可以说看不到tcp。 b：确实有第三方模块（ngx_tcp_proxy_module）做了同样的事，这个优秀的模块早好些时间，有兴趣的可以去github上看看。 c：tcp比stream容易上口，这好像有点废话，反正就是这样了。 为什么强调stream呢，stream和http是同级的，http本身有proxy功能，现在stream的核心功能也是proxy。但预料以后stream的功能将更加丰富强大，所以重申nginx有个stream的东西，因为它才具备tcp代理功能。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.zybuluo.com/orangleliu/note/478334&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://www.zybuluo.com/orangleliu/note/478334&lt;/a&gt; 这里也有一些相关的说明&lt;/p&gt;
&lt;p&gt;我们的配置中涉及到 proxy_connect_timeout 和 proxy_timeout 两个超时相关的配置项， &lt;a class=&#34;link&#34; href=&#34;https://my.oschina.net/xsh1208/blog/199674&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://my.oschina.net/xsh1208/blog/199674&lt;/a&gt; 这里提到 proxy_connect_timeout 不能超过 75 秒，不过在 &lt;a class=&#34;link&#34; href=&#34;https://nginx.org/en/docs/stream/ngx&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://nginx.org/en/docs/stream/ngx&lt;/a&gt;_stream_core_module.html#proxy_protocol_timeout 和 &lt;a class=&#34;link&#34; href=&#34;https://nginx.org/en/docs/stream/ngx&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://nginx.org/en/docs/stream/ngx&lt;/a&gt;_stream_proxy_module.html#proxy_connect_timeout 这两个官方的文档中倒是都没有提到&lt;/p&gt;
&lt;p&gt;先写一个 python 的 RabbitMQ 客户端，尝试去读写数据，都能正确连上，但是测试发现一旦闲置超过 1 秒，连接就被断开了，如下：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[x] Received &amp;#39;Hello World!&amp;#39;
 [x] Received &amp;#39;Hello World!&amp;#39;
 [x] Received &amp;#39;Hello World!&amp;#39;
 [x] Received &amp;#39;Hello World!&amp;#39;
 [x] Received &amp;#39;Hello World!&amp;#39;
 [x] Received &amp;#39;Hello World!&amp;#39;
 [x] Received &amp;#39;Hello World!&amp;#39;
Traceback (most recent call last):
  File &amp;#34;mq-receive.py&amp;#34;, line 19, in &amp;lt;module&amp;gt;
    channel.start_consuming()
  File &amp;#34;/usr/lib/python2.6/site-packages/pika-0.10.0-py2.6.egg/pika/adapters/blocking_connection.py&amp;#34;, line 1681, in start_consuming
    self.connection.process_data_events(time_limit=None)
  File &amp;#34;/usr/lib/python2.6/site-packages/pika-0.10.0-py2.6.egg/pika/adapters/blocking_connection.py&amp;#34;, line 647, in process_data_events
    self._flush_output(common_terminator)
  File &amp;#34;/usr/lib/python2.6/site-packages/pika-0.10.0-py2.6.egg/pika/adapters/blocking_connection.py&amp;#34;, line 426, in _flush_output
    raise exceptions.ConnectionClosed()
pika.exceptions.ConnectionClosed
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;于是考虑调整 nginx 的超时配置，简单粗暴的方法当然是配置为从不超时，但是这里有一个问题，就是我们的接入层的超时不应该这么宽松，官方给这些超时配置项的默认值也是到分钟级别的，不过，如果按照这个默认的超时配置值，随之而来的一个问题就是，RabbitMQ 本身是否有心跳呢？如果 RabbitMQ 本身没有心跳，那么在队列不活跃的时候，很可能就被杀掉了&lt;/p&gt;
&lt;p&gt;从 &lt;a class=&#34;link&#34; href=&#34;https://www.rabbitmq.com/heartbeats.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://www.rabbitmq.com/heartbeats.html&lt;/a&gt; 这里可以看到&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Detecting Dead TCP Connections with Heartbeats&lt;/p&gt;
&lt;p&gt;Introduction&lt;/p&gt;
&lt;p&gt;Network can fail in many ways, sometimes pretty subtle (e.g. high ratio packet loss). Disrupted TCP connections take a moderately long time (about 11 minutes with default configuration on Linux, for example) to be detected by the operating system. AMQP 0-9-1 offers a heartbeat feature to ensure that the application layer promptly finds out about disrupted connections (and also completely unresponsive peers). Heartbeats also defend against certain network equipment which may terminate &amp;ldquo;idle&amp;rdquo; TCP connections.&lt;/p&gt;
&lt;p&gt;Heartbeat Timeout Interval&lt;/p&gt;
&lt;p&gt;The heartbeat timeout value defines after what period of time the peer TCP connection should be considered dead by RabbitMQ and client libraries. This value is negotiated between the client and RabbitMQ server at the time of connection. The client must be configured to request heartbeats. In RabbitMQ versions 3.0 and higher, the broker will attempt to negotiate heartbeats by default (although the client can still veto them). The timeout is in seconds, and default value is 60 (580 prior to release 3.5.5).&lt;/p&gt;
&lt;p&gt;Heartbeat frames are sent about every timeout / 2 seconds. After two missed heartbeats, the peer is considered to be unreachable. Different clients manifest this differently but the TCP connection will be closed. When a client detects that RabbitMQ node is unreachable due to a heartbeat, it needs to re-connect.&lt;/p&gt;
&lt;p&gt;Heartbeats can be disabled by setting the timeout interval to 0.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;官方是有给 RabbitMQ 3.0 以上的版本支持心跳的，我们用的也是 3.4.1，可以认为是支持的&lt;/p&gt;
&lt;p&gt;所以接下来就可以把 nginx 的超时配置改为如下：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;stream {
    upstream rabbitmq{
        server xxxx:5672;
    }
    server {
        listen 5672;
        proxy_connect_timeout 600s;
        #proxy_timeout 3s;
        proxy_pass rabbitmq;
    }   
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;然后再次使用模拟的客户端和接收端进行收发，应该就可以保持长期不断开了&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
