Unable to connect to Apache ActiveMQ with Node.js

2019-06-05 11:02发布

问题:

Background

Trying to connect to my Apache ActiveMQ broker using the AMQP 1.0 protocol via amqp10. I am using the following code (adapted from the original example in the README):

const AMQPClient = require("amqp10").Client;
const Promise = require("bluebird");

//Fix from: https://github.com/noodlefrenzy/node-amqp10/issues/241
const activeMQPolicy = require("amqp10").Policy;
const client = new AMQPClient(activeMQPolicy.ActiveMQ);

const setUp = () => {
    return Promise.all([
        client.createReceiver("amq.topic"),
        client.createSender("amq.topic")
    ]);
};

client.connect("amqp://localhost")
    .then(setUp)
    .spread(function (receiver, sender) {
        receiver.on("errorReceived", function (err) {

            if (err) {
                console.log(`failed with error: ${err}`);
                return;
            }

            receiver.on("message", message => console.log(`Rx message: ${message.body}`));

            return sender.send({ key: "Value" });
        });
    })
    .error( err => console.log("error: ", err));

Error

Execution fails with the following application error:

Workspace/activemq/node_modules/amqp10/lib/frames.js:64 stream.write(buffer, callback); ^

TypeError: Cannot read property 'write' of null at Object.frames.writeFrame (/home/pedro/Workspace/activemq/node_modules/amqp10/lib/frames.js:64:9) at Connection.sendFrame (/home/pedro/Workspace/activemq/node_modules/amqp10/lib/connection.js:329:10) at Connection._sendCloseFrame (/home/pedro/Workspace/activemq/node_modules/amqp10/lib/connection.js:491:8) at Connection._receiveAny (/home/pedro/Workspace/activemq/node_modules/amqp10/lib/connection.js:413:12) at Connection._receiveData (/home/pedro/Workspace/activemq/node_modules/amqp10/lib/connection.js:358:8) at NetTransport. (/home/pedro/Workspace/activemq/node_modules/amqp10/lib/connection.js:516:38) at emitOne (events.js:96:13) at NetTransport.emit (events.js:191:7) at Socket. (/home/pedro/Workspace/activemq/node_modules/amqp10/lib/transport/net_transport.js:26:49) at emitOne (events.js:96:13) at Socket.emit (events.js:191:7) at readableAddChunk (_stream_readable.js:178:18) at Socket.Readable.push (_stream_readable.js:136:10) at TCP.onread (net.js:560:20)

While ActiveMQ rejects the request with the following message:

WARN | Connection attempt from non AMQP v1.0 client. AMQP,0,1,0,0 WARN | Transport Connection to: tcp://127.0.0.1:53188 failed: org.apache.activemq.transport.amqp.AmqpProtocolException: Connection from client using unsupported AMQP attempted

What I tried

I tried to implement the fix described in this issue:

  • https://github.com/noodlefrenzy/node-amqp10/issues/241

But it didn't work either. Also tried specifying the port 5672 in the url, but with no luck.

Question

At this point I am quite sure the application fails the write, because ActiveMQ rejects the request as invalid.

  • Any ideas on how to fix this?

回答1:

Solution

After asking around in the ActiveMQ forums, it does turn out that @Tim was correct. To quote the user Gordon Sim-2:

As of 5.14 (...) ActiveMQ requires a SASL layer, even if you use ANONYMOUS to authenticate. The examples for clients often don't explicitly authenticate in any way (...)

To fix this there are two options.

Option 1 - change code

The first one is to change the code, which is what I was looking for:

To have the amqp10 client use a SASL layer, just specify a saslMechanism override on the connect e.g.

client.connect(uri, {'saslMechanism':'ANONYMOUS'})

This approach was suggested by the creator of yet another AMQP 1.0 Node.js library called rhea and I highly recommend that if you are reading this, to check it.

Option 2 - change broker config files

The second one, as Tim suggested, is to change the broker configuration files. I recommend reading his post if you opt for this approach as it is more complete.



回答2:

The most likely issue is that the client is not using a SASL based authentication request on the connect and is just trying to connect directly. The broker defaults to requiring the client be using SASL in it's opening handshake even if the authentication mechanism is only 'Anonymous' so that the client can be validated against any broker security policy that is in place.

You can disable this check by adding wireFormat.allowNonSaslConnections=true to the broker's AMQP TransportConnector configuration and then see if you can connect. This might be a short term solution to get you going however on a production broker you should not be using that option and should have a valid security policy in place with user / password authentication.

Read about broker configuration here.