com.godmao.mqbroker.Broker Maven / Gradle / Ivy
package com.godmao.mqbroker;
import com.godmao.mqbroker.message.MultipleMessage;
import com.godmao.mqbroker.message.SingleMessage;
import com.godmao.netty.channel.ChannelService;
import com.godmao.netty.server.AbstractServer;
import io.netty.channel.*;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.Future;
import io.netty.util.internal.ObjectUtil;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class Broker extends AbstractServer {
private final String name;
public static void main(String[] args) {
Map arguments = new HashMap<>();
for (String arg : args) {
String[] parts = arg.split("=");
if (parts.length == 2) {
String name = parts[0].startsWith("--") ? parts[0].substring(2) : parts[0];
arguments.put(name, parts[1]);
}
}
String portKey = "broker.port";
String nameKey = "broker.name";
final int port = Integer.parseInt(arguments.getOrDefault(portKey, System.getProperty(portKey, "10001")));
final String name = arguments.getOrDefault(nameKey, System.getProperty(nameKey, "broker"));
//
Broker broker = new Broker(port, name);
broker.start();
}
public Broker(int port, String name) {
super(port);
ObjectUtil.checkNonEmpty(name, "Broker name is Empty!");
this.name = name;
// this.deadLetterQueue = new DeadLetterQueue(1000);
log.info("[port]: {}", port);
log.info("[name]: {}", name);
setChannelInitializer(new BrokerInitializer(this));
setChannelService(new ChannelService(name + port + "-channels"));
setParentGroup(Epoll.isAvailable() ?
new EpollEventLoopGroup(1, new DefaultThreadFactory(name + port + "-parent")) :
new NioEventLoopGroup(1, new DefaultThreadFactory(name + port + "-parent")));
setChildGroup(Epoll.isAvailable() ?
new EpollEventLoopGroup(new DefaultThreadFactory(name + port + "-child")) :
new NioEventLoopGroup(new DefaultThreadFactory(name + port + "-child")));
}
/**
* 获取broker的名称
*/
public String getName() {
return name;
}
/**
* 获取主题和对应的订阅数量
*/
public Map getTopicCount() {
final Map topicCount = new HashMap<>();
for (final Channel channel : getChannelService()) {
if (!channel.isActive()) {
continue;
}
final Boolean authorization = channel.attr(Static.AUTHORIZATION).get();
if (null == authorization || !authorization) {
continue;
}
final Set topics = channel.attr(Static.TOPIC).get();
for (final String topic : topics) {
Integer count = topicCount.getOrDefault(topic, 0);
topicCount.put(topic, ++count);
}
}
return topicCount;
}
@Override
public void onOpen(ChannelHandlerContext ctx) {
final Channel channel = ctx.channel();
channel.attr(Static.AUTHORIZATION).set(false);
channel.attr(Static.TOPIC).set(new LinkedHashSet<>());
//
channel.eventLoop().schedule(() -> {
if (!channel.isActive()) {
return;
}
if (!channel.attr(Static.AUTHORIZATION).get()) {
channel.close();
log.info("[连接失败]-[{}-{}]: {} {}", ctx.channel().attr(ChannelService.CHANNELID).get(), ctx.channel().id().asShortText(), ctx.channel().attr(ChannelService.CHANNELADDRESS).get(), "未绑定");
}
}, 30, TimeUnit.SECONDS);
}
@Override
public void onClose(ChannelHandlerContext ctx) {
log.warn("[连接断开]-[{}-{}]: {}", ctx.channel().attr(ChannelService.CHANNELID).get(), ctx.channel().id().asShortText(), ctx.channel().attr(ChannelService.CHANNELADDRESS).get());
}
@Override
public void onError(ChannelHandlerContext ctx, Throwable throwable) {
log.error("[连接异常]-[{}]:", ctx.channel().attr(ChannelService.CHANNELID).get() + "-" + ctx.channel().id().asShortText(), throwable);
}
@Override
public void onMessage(ChannelHandlerContext ctx, Object message) {
log.warn("[未知消息]-[{}-{}]: {}", ctx.channel().attr(ChannelService.CHANNELID).get(), ctx.channel().id().asShortText(), message);
}
public Future> send(final MultipleMessage.Response message, final Channel channel, final int retryCount, final int delay) {
return send0(message, channel, channel.newPromise(), retryCount, delay);
}
public Future> send(final SingleMessage.Response message, final Channel channel, final int retryCount, final int delay) {
return send0(message, channel, channel.newPromise(), retryCount, delay);
}
/**
* 发送消息
*
* @param message 消息
* @param channel 发送消息的会话
* @param promise 会话的约定
* @param retryCount 发送失败重试次数
* @param delay 重试延时发送间隔 /s
* @return {@link ChannelFuture}
*/
private Future> send0(final Object message, final Channel channel, final ChannelPromise promise, final int retryCount, final int delay) {
channel.writeAndFlush(message).addListener((ChannelFutureListener) future -> {
if (future.isSuccess()) {
promise.trySuccess();
return;
}
if (retryCount < 1 || !future.channel().isActive()) {
promise.tryFailure(future.cause());
return;
}
channel.eventLoop().schedule(() -> send0(message, channel, promise, retryCount - 1, delay * 2), delay, TimeUnit.SECONDS);
});
return promise;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy