ZeroMQ两个PUB-SUB代理

时间:2015-02-13 08:20:43

标签: java proxy zeromq publish-subscribe

我想为我们的分布式系统实现pub-sub基础结构。 网络背后的想法,你可以在图片中看到,我想在java中实现发布者和订阅者。但在JZmq曲线中,尚不支持加密。所以我想在C(++)中实现可用的代理。(目前我只在java中使用它)

这是我的代码

Subscriber.java

import java.nio.charset.Charset;

import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Context;
import org.zeromq.ZMQ.Socket;

public class Subscriber {
    public static void main(String[] args) {
        String address = args[0];
        String topic = args[1];

        Context context = ZMQ.context(1);
        Socket subscriber = context.socket(ZMQ.SUB);
        subscriber.connect(address);
        subscriber.subscribe(topic.getBytes());

        while (!Thread.currentThread().isInterrupted()) {
            String top = subscriber.recvStr(Charset.defaultCharset());
            String contents = subscriber.recvStr(Charset.defaultCharset());

            System.out.println(top + ": " + contents);
        }
        subscriber.close();
        context.term();
    }    
}

Publisher.java

import java.util.Random;

import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Context;
import org.zeromq.ZMQ.Socket;

public class Publisher {
    public static void main(String[] args) {
        String url = args[0];
        String topic = args[1];
        int intervall = Integer.valueOf(args[2]);

        Context context = ZMQ.context(1);
        Socket publisher = context.socket(ZMQ.PUB);

        Random rand = new Random();
        publisher.connect(url);
        while (!Thread.currentThread().isInterrupted()) {
            try {
                Thread.sleep(intervall);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            int value = rand.nextInt(20) * (rand.nextBoolean() ? (-1) : 1);
            publisher.sendMore(topic);
            publisher.send(String.valueOf(value));
            System.out.println("PUB: " + topic + ":" + value);
        }

        publisher.close();
        context.term();
    }
}

PubSubProxy.java

import java.io.PrintStream;

import org.zeromq.ZContext;
import org.zeromq.ZFrame;
import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Context;
import org.zeromq.ZMQ.Socket;
import org.zeromq.ZThread;
import org.zeromq.ZThread.IAttachedRunnable;

public class PubSubProxy {
    static Socket frontend;
    static Socket backend;

    public static void main(String[] args) {
        String addressSubscriber = args[0];
        String modeSubscriber = args[1];
        String addressPublisher = args[2];
        String modePublisher = args[3];

        // Prepare our context and sockets
        // ZContext context = ZMQ.context(1);
        ZContext context = new ZContext();

        // This is where the weather server sits
        frontend = context.createSocket(ZMQ.XSUB);
        if (modeSubscriber.equals("client")) {
            System.out.println("Subscriber connecting to: " + addressSubscriber);
            frontend.connect(addressSubscriber);
        } else if (modeSubscriber.equalsIgnoreCase("server")) {
            System.out.println("Subscriber binding to: " + addressSubscriber);
            frontend.bind(addressSubscriber);
        }
        // This is our public endpoint for subscribers
        backend = context.createSocket(ZMQ.XPUB);

        if (modePublisher.equals("client")) {
            System.out.println("Publisher connecting to: " + addressPublisher);
            backend.connect(addressPublisher);
        } else if (modePublisher.equalsIgnoreCase("server")) {
            System.out.println("Publisher binding to: " + addressPublisher);
            backend.bind(addressPublisher);
        }

        // Subscribe on everything
        // frontend.subscribe("".getBytes());

        // Run the proxy until the user interrupts us
        IAttachedRunnable runnable = new Listener();
        Socket listener = ZThread.fork(context, runnable);
        ZMQ.proxy(frontend, backend, listener);

        frontend.close();
        backend.close();
        context.destroy();
    }

    private static class Listener implements IAttachedRunnable {
        @Override
        public void run(Object[] args, ZContext ctx, Socket pipe) {
            // Print everything that arrives on pipe
            while (true) {
                ZFrame frame = ZFrame.recvFrame(pipe);
                if (frame == null)
                    break; // Interrupted
                System.out.println(frame.toString());
                frame.destroy();
            }
        }
    }
}

正如您所看到的,我已经向代理添加了一个监听器,以查看是否收到了消息。 在发布者端代理(图片中的顶部代理),我收到消息,但在另一个代理上没有。

这是我执行应用程序的方式

#beaglebone #1
#proxy #1
java -Djava.library.path=/usr/local/lib -jar proxy.jar ipc:///tmp/pub server tcp://*:5555 server 
#pub
java -Djava.library.path=/usr/local/lib -jar publisher.jar ipc:///tmp/pub temperature 10000
java -Djava.library.path=/usr/local/lib -jar publisher.jar ipc:///tmp/pub humidity 1000
java -Djava.library.path=/usr/local/lib -jar publisher.jar ipc:///tmp/pub testvar 5000

#beaglebone #2
#proxy #2
java -Djava.library.path=/usr/local/lib -jar proxy.jar tcp://192.168.0.192:5555 client ipc:///tmp/sub server
#sub
java -Djava.library.path=/usr/local/lib -jar subscriber.jar ipc:///tmp/sub temperature
java -Djava.library.path=/usr/local/lib -jar subscriber.jar ipc:///tmp/sub humidity
java -Djava.library.path=/usr/local/lib -jar subscriber.jar ipc:///tmp/sub testvar

pub-sub network

1 个答案:

答案 0 :(得分:0)

您似乎混淆了客户端/服务器模式与pub / sub模式的混淆。

在发布/订阅模式中,发布者通知其订阅者(如果有)。发布者应使用bind(监听订阅),订阅者应使用connect(请求订阅)。

然后你的交流变成: enter image description here

为了做到这一点,你可以:

  • 修改使用publisher.connect(url);
  • 替换publisher.bind(url);的Publisher.java
  • 修改PubSubProxy.java,删除无用的客户端/服务器参数
import java.io.PrintStream;

import org.zeromq.ZContext;
import org.zeromq.ZFrame;
import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Context;
import org.zeromq.ZMQ.Socket;
import org.zeromq.ZThread;
import org.zeromq.ZThread.IAttachedRunnable;

public class PubSubProxy {
    static Socket frontend;
    static Socket backend;

    public static void main(String[] args) {
        String addressSubscriber = args[0];
        String addressPublisher = args[1];

        // Prepare our context and sockets
        ZContext context = new ZContext();

        // This is where the weather server sits
        frontend = context.createSocket(ZMQ.XSUB);
        System.out.println("Subscriber connecting to: " + addressSubscriber);
        frontend.connect(addressSubscriber);

        // This is our public endpoint for subscribers
        backend = context.createSocket(ZMQ.XPUB);
        System.out.println("Publisher binding to: " + addressPublisher);
        backend.bind(addressPublisher);

        // Run the proxy until the user interrupts us
        ZMQ.proxy(frontend, backend, null);

        frontend.close();
        backend.close();
        context.destroy();
    }
} 

然后你应该能够使用以下方法从后端到前端接收数据:

#beaglebone #1
#proxy #1
java -Djava.library.path=/usr/local/lib -jar proxy.jar ipc:///tmp/pub tcp://*:5555 
#pub
java -Djava.library.path=/usr/local/lib -jar publisher.jar ipc:///tmp/pub temperature 10000

#beaglebone #2
#proxy #2
java -Djava.library.path=/usr/local/lib -jar proxy.jar tcp://192.168.0.192:5555 ipc:///tmp/sub
#sub
java -Djava.library.path=/usr/local/lib -jar subscriber.jar ipc:///tmp/sub temperature