Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.godmao.mqserver.AbstractServer Maven / Gradle / Ivy
package com.godmao.mqserver;
import com.godmao.mqserver.handler.TopicSubscribeCancelMessageEncoderHandler;
import com.godmao.mqserver.handler.TopicSubscribeMessageEncoderHandler;
import com.godmao.mqserver.message.*;
import com.godmao.netty.channel.ChannelService;
import com.godmao.netty.client.AbstractClient;
import com.godmao.netty.common.NetUtil;
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.AttributeKey;
import io.netty.util.concurrent.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
public abstract class AbstractServer extends AbstractClient {
public static final AttributeKey AUTHORIZATION = AttributeKey.valueOf("mate-authorization");
public static final AttributeKey TOPIC_VERSION = AttributeKey.valueOf("mate-topic-version");
public static final AttributeKey> TOPIC = AttributeKey.valueOf("mate-topic");
private final String name;
private final AtomicLong counter = new AtomicLong();
private final EventExecutor executor = new DefaultEventExecutor();
public AbstractServer() {
this(NetUtil.LOCAL_IP);
}
public AbstractServer(String name) {
log.info("name: {}", name);
this.name = name;
setChannelInitializer(new ServerInitializer(this));
setChannelService(new ChannelService(name + "-channel-service"));
setGroup(Epoll.isAvailable() ?
new EpollEventLoopGroup(new DefaultThreadFactory(name + "-server")) :
new NioEventLoopGroup(new DefaultThreadFactory(name + "-server")));
}
public String getName() {
return name;
}
@Override
public synchronized void shutdown() {
if (!this.executor.isShutdown()) {
this.executor.shutdownGracefully().addListener(future -> {
if (!future.isSuccess()) {
log.error("Error while shutting down executor", future.cause());
}
});
}
super.shutdown();
}
@Override
public void onOpen(ChannelHandlerContext ctx) {
final Channel channel = ctx.channel();
channel.attr(AUTHORIZATION).set(false);
channel.attr(TOPIC).set(new HashMap<>());
channel.attr(TOPIC_VERSION).set(-1L);
ctx.writeAndFlush(new BindMessage(name, NetUtil.LOCAL_IP));
}
@Override
public synchronized void start() {
//
super.start();
//
scheduledSendHeartbeat();
}
// 定时发送心跳包
private void scheduledSendHeartbeat() {
executor.scheduleWithFixedDelay(() -> {
for (final Channel channel : getChannelService()) {
if (!channel.isActive()) {
continue;
}
if (!channel.isWritable()) {
continue;
}
if (!channel.attr(AUTHORIZATION).get()) {
continue;
}
channel.writeAndFlush(new HeartbeatMessage.Response(channel.attr(TOPIC_VERSION).get()));
}
}, 30, 30, TimeUnit.SECONDS);
}
@Override
public void onMessage(ChannelHandlerContext ctx, Object message) {
log.warn("[未知消息]: {} {} {}", ctx.channel().attr(ChannelService.CHANNELID).get(), ctx.channel().attr(ChannelService.CHANNELADDRESS).get(), message);
}
public Future> send(final SingleMessage.Response message) {
return send(message, 0, 0);
}
public Future> send(final MultipleMessage.Response message) {
return send(message, 0, 0);
}
public Future> send(final SingleMessage.Response message, final int retryCount, final int delay) {
return send(message, new DefaultPromise<>(group.next()), retryCount, delay);
}
public Future> send(final MultipleMessage.Response message, final int retryCount, final int delay) {
return send(message, new DefaultPromise<>(group.next()), retryCount, delay);
}
public Future> send(final SingleMessage.Response message, final Promise> promise, final int retryCount, final int delay) {
// 找到所有 活跃 绑定过 包含主题 的所有服务
final Set matches_ = getChannelService().matches(
channel -> channel.isActive() &&
channel.attr(AUTHORIZATION).get() &&
channel.attr(TOPIC).get().containsKey(message.getTopic())
);
if (matches_.isEmpty()) {
if (retryCount < 1) {
promise.setFailure(new Exception("No matching channels found: " + message.getTopic()));
} else {
super.group.next().schedule(() -> send(message, promise, retryCount - 1, delay * 2), delay, TimeUnit.SECONDS);
}
} else {
// 选择一个channel(轮询策略)
final int flag = Math.abs((int) (counter.incrementAndGet() % (long) matches_.size()));
final Channel channel = (Channel) matches_.toArray()[flag];
send0(message, channel, promise, retryCount, delay);
}
return promise;
}
public Future> send(final MultipleMessage.Response message, final Promise> promise, final int retryCount, final int delay) {
// 找到所有 活跃 绑定过 包含主题 的所有服务
final Set matches_ = getChannelService().matches(
channel -> channel.isActive() &&
channel.attr(AUTHORIZATION).get() &&
channel.attr(TOPIC).get().keySet().containsAll(message.getTopics())
);
if (matches_.isEmpty()) {
if (retryCount < 1) {
promise.setFailure(new Exception("No matching channels found: " + message.getTopics()));
} else {
super.group.next().schedule(() -> send(message, promise, retryCount - 1, delay * 2), delay, TimeUnit.SECONDS);
}
} else {
// 选择一个channel(轮询策略)
final int flag = Math.abs((int) (counter.incrementAndGet() % (long) matches_.size()));
final Channel channel = (Channel) matches_.toArray()[flag];
send0(message, channel, promise, retryCount, delay);
}
return promise;
}
/**
* 发送消息
*
* @param message 消息
* @param channel 发送消息的会话
* @param promise 会话的约定
* @param retryCount 发送失败重试次数
* @param delay 重试延时发送间隔 /s
* @return {@link ChannelFuture}
*/
private Future> send0(final Object message, final Channel channel, final Promise> promise, final int retryCount, final int delay) {
channel.writeAndFlush(message).addListener((ChannelFutureListener) future -> {
if (future.isSuccess()) {
promise.trySuccess(null);
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;
}
/**
* 消息订阅
*/
public void subscribe(TopicSubscribeMessage subscribeMessage) {
getChannelService().writeAndFlush(
TopicSubscribeMessageEncoderHandler.INSTANCE.encode(subscribeMessage),
channel -> channel.isActive() && channel.attr(AUTHORIZATION).get()
);
}
public void subscribe(Set topics) {
subscribe(new TopicSubscribeMessage(topics));
}
/**
* 取消订阅
*/
public void subscribeCancel(TopicSubscribeCancelMessage subscribeCancelMessage) {
getChannelService().writeAndFlush(
TopicSubscribeCancelMessageEncoderHandler.INSTANCE.encode(subscribeCancelMessage),
channel -> channel.isActive() && channel.attr(AUTHORIZATION).get()
);
}
public void subscribeCancel(Set topics) {
subscribeCancel(new TopicSubscribeCancelMessage(topics));
}
public abstract void onMessage(ChannelHandlerContext ctx, final String topic, final byte[] data);
public abstract void onOpen(ChannelHandlerContext ctx, final BindMessage bindMessage);
}