我是vert.x的新手。我正在尝试使用vert.x“NetServer”功能。 http://vertx.io/core_manual_java.html#writing-tcp-servers-and-clients它就像一个魅力。
但是,我还读到“一个Verticle实例严格是单线程的。
如果您创建一个简单的TCP服务器并部署它的单个实例,那么该服务器的所有处理程序总是在同一个事件循环(线程)上执行。“
目前,对于我的实现,我想接收TCP字节流,然后触发另一个组件。但这不应该是Verticle的“start”方法中的阻塞调用。那么,在start方法中编写执行程序是一种好的做法吗?或者vertx会自动处理这种情况。
这是一个片段
public class TCPListener extends Verticle {
public void start(){
NetServer server = vertx.createNetServer();
server.connectHandler(new Handler<NetSocket>() {
public void handle(NetSocket sock) {
container.logger().info("A client has connected");
sock.dataHandler(new Handler<Buffer>() {
public void handle(Buffer buffer) {
container.logger().info("I received " + buffer.length() + " bytes of data");
container.logger().info("I received " + new String(buffer.getBytes()));
//Trigger another component here. SHould be done in a sperate thread.
//The previous call should be returned . No need to wait for component response.
}
});
}
}).listen(1234, "host");
}
}
什么应该是使这个非阻塞调用的机制。
答案 0 :(得分:8)
我认为这不是Vert.x的方法。
更好的方法是正确使用事件总线而不是Executor。让工作人员对总线上的事件做出响应,进行处理,并在总线完成时发出信号。
创建线程违背了使用vert.x的目的。
答案 1 :(得分:1)
最灵活的方法是创建ExecutorService并使用它处理请求。这样可以对工作者的线程模型进行细粒度控制(固定或可变数量的线程,应该在单个线程上连续执行哪些工作等)。
修改后的样本可能如下所示:
public class TCPListener extends Verticle {
private final ExecutorService executor = Executors.newFixedThreadPool(10);
public void start(){
NetServer server = vertx.createNetServer();
server.connectHandler(new Handler<NetSocket>() {
public void handle(final NetSocket sock) { // <-- Note 'final' here
container.logger().info("A client has connected");
sock.dataHandler(new Handler<Buffer>() {
public void handle(final Buffer buffer) { // <-- Note 'final' here
//Trigger another component here. SHould be done in a sperate thread.
//The previous call should be returned . No need to wait for component response.
executor.submit(new Runnable() {
public void run() {
//It's okay to read buffer data here
//and use sock.write() if necessary
container.logger().info("I received " + buffer.length() + " bytes of data");
container.logger().info("I received " + new String(buffer.getBytes()));
}
}
}
});
}
}).listen(1234, "host");
}
}
答案 2 :(得分:0)
正如duffymo提到的创建线程失败了使用vertx的目的。最好的方法是将消息写入eventbus并创建一个新的处理程序来监听来自事件总线的消息。更新了代码以展示此内容。将消息写入&#34; next.topic&#34;主题,并注册了一个处理程序来读取来自&#34; next.topic&#34;话题。
public class TCPListener extends Verticle {
public void start(){
NetServer server = vertx.createNetServer();
server.connectHandler(new Handler<NetSocket>() {
public void handle(NetSocket sock) {
container.logger().info("A client has connected");
sock.dataHandler(new Handler<Buffer>() {
public void handle(Buffer buffer) {
String recvMesg = new String(buffer.getBytes());
container.logger().info("I received " + buffer.length() + " bytes of data");
container.logger().info("I received " + recvMesg);
//Writing received message to event bus
vertx.eventBus().send("next.topic", recvMesg);
}
});
}
}).listen(1234, "host");
//Registering new handler listening to "next.topic" topic on event bus
vertx.eventBus().registerHandler("next.topic", new Handler<Message<String>() {
public void handle(Message<String> mesg) {
container.logger.info("Received message: "+mesg.body());
}
};
}
}