一、背景
近期做一个小的基础组件,主要作用是异步消息通知、缓存维护、以及耗时任务处理。
当中消息通知和耗时任务处理要用到开源的RabbitMQ作为消息中心server。
可是有一点比較恶心,我这个组件是要执行在现有的系统中,即要给现有的系统升级,将我这个组件用进去,并且,除了除数据库server之外,全部server都是windows server 2003 enterprise edition sp2 64bit的。你没看错,就是这么古老的机器。。。
二、面临的问题
之前在windows server 2008和centOS上安装RabbitMQ都很顺利。没有遇到不论什么阻碍,这次在windows server 2003上面安装就遇到了问题:
1、首先安装ErLang的时候,没有出现不论什么问题,我装的是OTP
17.3 Windows 64-bit,地址是:http://www.erlang.org/download.html
2、安装RabbitMQ 最新版3.3.5的时候出问题了。即无法定位程序输入点inet_pton于动态链接库WS2_32.dll上。例如以下图:
报出了一个和网络地址转换相关的错误。。。这让我想不到。
三、寻找答案的过程和思考
于是開始上网找,中文网页压根没人在windows server 2003上面安装过RabbitMQ,在非常多qq群问了也无果。
于是開始搜索英文网页。找到这么一个网址:http://comments.gmane.org/gmane.comp.networking.rabbitmq.general/16499
这两人的对话给我非常多关键性信息。最关键的莫过于:
From the information you provided it is likely that this is caused by the Erlang distributed networking not working on windows 2003 64bit. This platform is sufficiently rare that no-one else has reported this problem for Erlang, but I see there was a similar report in Wireshark caused by a library ordering problem: https://bugs.wireshark.org/bugzilla/show_bug.cgi? id=5160#c16 If you can find the shortest set of steps that provokes the error then that should be enough to give the Erlang developers a handle on the problem. I would expect these commands to cause a failure - can you confirm? Make sure the Erlang bin directory is in your PATH: werl -sname testnode <at> %COMPUTERNAME% werl -sname foo -remsh testnode <at> %COMPUTERNAME% If you need a working RabbitMQ broker in the meantime then consider installing the 32bit version of Erlang. I not expect it to suffer from the same problem.
看来应该就是Erlang的问题了,RabbitMQ号称仅仅要ErLang可以跑的系统,它也可以非常好滴工作^_^ !
ErLang的开发人员预计也知道这个问题了,这么几年下来到如今最新版17.3了还没有改动。预计他们也不会打算要修复这个Bug了。连微软都停止支持windows server 2003了。
于是我又一次下载了一个R16B03 Windows
32-bit Binary
吧之前安装的RabbitMQ和Erlang所有卸载掉,然后又一次安装ErLang和RabbitMQ,这次在安装RabbitMQ的时候又遇到问题了:
这下让我有点头痛了,难道我仅仅剩下最后一条能够尝试的路了?就是 在这个windows server 2003上面又一次编译Erlang源代码么。。。
我静下来想了想,突然认为这个错误报的是无法注冊RabbitMQ 服务。。。 我晕,下次应该好好观察一下报的错误,这个明显就是RabbitMQ注冊服务的问题嘛。
。
。应该是和ErLang无关的。
。。
可能是卸载RabbitMQ并没有卸载干净服务和注冊表。
于是我直接把我的系统还原到之前干净的镜像,又一次安装。OK。!!
四、解决方法
1、安装ErLang 32-bit。下载地址是:http://www.erlang.org/download_release/22,我安装的是16B03 32bit。
2、新建系统环境变量ERLANG_HOME。值为C:\Program Files (x86)\erl5.10.4,即仅仅要可以找到bin/werl.exe就可以。
3、安装RabbitMQ 3.3.5。下载地址是:https://www.rabbitmq.com/install-windows.html
4、添加rabbitmqctl.bat的路径(C:\Program Files (x86)\RabbitMQ Server\rabbitmq_server-3.3.5\sbin)到PATH系统环境变量。
非常easy,这就安装完毕了,接下来新建用户(最好将默认的guest用户删掉)。新建虚拟机vHost,设置用户对该虚拟机的权限:
好了。以下附上一个C#的測试程序:
send.cs
namespace RabbitMQ.SendReceive { class Program { static void Main(string[] args) { //ConnectionFactory factory = new ConnectionFactory() { HostName = "192.168.1.103" }; ConnectionFactory factory = new ConnectionFactory(); factory.Uri = "amqp://jiyiqin:[email protected]:5672/cProxy"; using (IConnection conn = factory.CreateConnection()) { using (IModel channel = conn.CreateModel()) { channel.QueueDeclare("hello", false, false, false, null); string mesg = "hello RabbitMQ"; byte[] body = Encoding.UTF8.GetBytes(mesg); channel.BasicPublish("", "hello", null, body); Console.WriteLine(" [x] Sent {0}", mesg); } } } } }
receive.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using RabbitMQ.Client; using RabbitMQ.Client.Events; namespace RabbitMQ.SendReceive { class Program { static void Main(string[] args) { //ConnectionFactory factory = new ConnectionFactory() { HostName = "192.168.1.103" }; ConnectionFactory factory = new ConnectionFactory(); factory.Uri = "amqp://jiyiqin:[email protected]:5672/cProxy"; using (IConnection conn = factory.CreateConnection()) { using (IModel channel = conn.CreateModel()) { channel.QueueDeclare("hello", false, false, false, null); QueueingBasicConsumer consumer = new QueueingBasicConsumer(channel); channel.BasicConsume("hello", true, consumer); Console.WriteLine(" [*]Waiting for message..."); while (true) { var queueItem = (BasicDeliverEventArgs)consumer.Queue.Dequeue(); byte[] body = queueItem.Body; string mesg = Encoding.UTF8.GetString(body); Console.WriteLine(" [x] Received {0}", mesg); } } } } } }
当然了,64bit的硬件上面跑32bit的程序。肯定无法发挥硬件效果。可能性能也不是很高。可是幸好我们这个古老的系统对并发量等要求太小。哈哈
结束。