JetLinks 物联网平台源码解读
设备接入逻辑
组件模块里面有两个要重点关注的子模块
- 第一个是网关模块
网关的主要功能是对网络组件产生的消息进行管理并支持发布到总线以支持订阅,对网络组件产生的连接进行认证,对网络组件连接产生的会话进行管理,还有对这些操作进行监控。由于网关的消息处理依赖网络组件,所以网关关于消息处理这部分内容的实现都放到了网络组件里面实现,这里对网关行为进行抽象。但是,一些相关处理,例如监控、发布订阅这里有具体的实现。 - 第二个是网络组件模块
网络组件一般是对一些第三方的网络组件包进行二次封装、提供平台的统一收发消息接口。同时,这里会对每一种类型的网络组件提供一个网关的实现。
MqttServerDeviceGateway
这个mqtt服务器网关里面组合了几个重要类
- MqttServer 是连接、会话、消息产生的源头。
- DeviceRegistry 保存在数据库设备在发布后会注册到这里,所以这个类主要是作用获取发布后的设备,并进行操作。
- DecodedClientMessageHandler 把转换后的平台消息发布到总线。DeviceMessageConnector是它的实现类。
- DeviceGatewayHelper 这个类里面描述了设备消息对会话有怎样的影响
- DeviceSessionManager 设备会话管理,DeviceSessionManager.compute是经常用来判断是否session该更新还是该创建
public Mono<DeviceSession> compute(@Nonnull String deviceId, Mono<DeviceSession> creator, Function<DeviceSession, Mono<DeviceSession>> updater) {
DeviceSessionRef ref = (DeviceSessionRef)this.localSessions.compute(deviceId, (_id, old) -> {
if (old == null) {
return creator == null ? null : new DeviceSessionRef(_id, this, creator);
} else if (updater == null) {
return old;
} else {
old.update((s) -> {
return s.flatMap(updater);
});
return old;
}
});
return ref == null ? Mono.empty() : ref.ref();
}
BrokerEventBus
所在包:org.jetlinks.core.event
JetLinks的消息总线,对topic和消息体进行发布和订阅,但是直接发给设备的topic是不经过消息总线的。
平台向设备发消息
DefaultDeviceOperator
所在包:org.jetlinks.core.defaults
设备操作器,向设备发送消息是可通过此类获取消息发送器,设备信息等。
public class DefaultDeviceOperator implements DeviceOperator, StorageConfigurable {
private static final Logger log = LoggerFactory.getLogger(DefaultDeviceOperator.class);
public static final DeviceStateChecker DEFAULT_STATE_CHECKER = (device) -> {
return checkState0((DefaultDeviceOperator)device);
};
private static final ConfigKey<Long> lastMetadataTimeKey = ConfigKey.of("lst_metadata_time");
static final List<String> productIdAndVersionKey;
private static final AtomicReferenceFieldUpdater<DefaultDeviceOperator, DeviceMetadata> METADATA_UPDATER;
private static final AtomicLongFieldUpdater<DefaultDeviceOperator> METADATA_TIME_UPDATER;
private final String id;
private final DeviceOperationBroker handler;
private final DeviceRegistry registry;
private final DeviceMessageSender messageSender; // 消息发送器,使用的实现是 DefaultDeviceMessageSender
private final Mono<ConfigStorage> storageMono;
private final Mono<ProtocolSupport> protocolSupportMono;
private final Mono<DeviceMetadata> metadataMono;
private final DeviceStateChecker stateChecker;
private final Mono<DeviceProductOperator> parent;
private volatile long lastMetadataTime;
private volatile DeviceMetadata metadataCache;
private ThingRpcSupportChain rpcChain;
private static final List<String> stateCacheKeys;
//...省略
}
DefaultDeviceMessageSender
发消息会用到DeviceOperationBroker,使用的实现是EventBusDeviceOperationBroker
public class DefaultDeviceMessageSender implements DeviceMessageSender {
private static final Logger log = LoggerFactory.getLogger(DefaultDeviceMessageSender.class);
private final DeviceOperationBroker handler; // 实际发送消息是用的这个类,使用的实现是EventBusDeviceOperationBroker
private final DeviceOperator operator;
private final DeviceRegistry registry;
private static final long DEFAULT_TIMEOUT;
private long defaultTimeout;
private final DeviceMessageSenderInterceptor globalInterceptor;
//...省略
}
public <R extends DeviceMessage> Flux<R> send(Publisher<? extends DeviceMessage> message, Function<Object, R> replyMapping) {
return Mono.zip(this.operator.getConnectionServerId().switchIfEmpty(this.refreshAndGetConnectionServerId()).defaultIfEmpty(""), this.operator.getProtocol().flatMap(ProtocolSupport::getSenderInterceptor).defaultIfEmpty(DeviceMessageSenderInterceptor.DO_NOTING), this.operator.getSelfConfig(DeviceConfigKey.parentGatewayId).defaultIfEmpty("")).flatMapMany((serverAndInterceptor) -> {
DeviceMessageSenderInterceptor interceptor = ((DeviceMessageSenderInterceptor)serverAndInterceptor.getT2()).andThen(this.globalInterceptor);
String server = (String)serverAndInterceptor.getT1();
String parentGatewayId = (String)serverAndInterceptor.getT3();
return StringUtils.isEmpty(server) && StringUtils.hasText(parentGatewayId) ? Flux.from(message).flatMap((msg) -> {
return interceptor.preSend(this.operator, msg);
}).flatMap((msg) -> {
return (Flux)this.sendToParentDevice(parentGatewayId, msg).as((flux) -> {
return interceptor.afterSent(this.operator, msg, interceptor.doSend(this.operator, msg, flux));
});
}).map((r) -> {
return r;
}) : Flux.from(message).flatMap((msg) -> {
return interceptor.preSend(this.operator, msg);
}).concatMap((msg) -> {
return (Flux)Flux.defer(() -> {
DeviceMessageTracer.trace(msg, "send.before");
if (StringUtils.isEmpty(server)) {
return interceptor.afterSent(this.operator, msg, Flux.error(new DeviceOperationException(ErrorCode.CLIENT_OFFLINE)));
} else {
boolean forget = (Boolean)msg.getHeader(Headers.sendAndForget).orElse(false);
Flux<R> replyStream = forget ? Flux.empty() : ((Flux)this.handler.handleReply(msg.getDeviceId(), msg.getMessageId(), Duration.ofMillis((Long)msg.getHeader(Headers.timeout).orElse(this.defaultTimeout))).map(replyMapping).onErrorResume(DeviceOperationException.class, (error) -> {
return error.getCode() == ErrorCode.CLIENT_OFFLINE ? this.operator.checkState().then(Mono.error(error)) : Mono.error(error);
}).onErrorMap(TimeoutException.class, (timeout) -> {
return new DeviceOperationException(ErrorCode.TIME_OUT, timeout);
}).as((flux) -> {
return this.logReply(msg, flux);
})).cache();
// 发送消息的逻辑在这里
return this.handler.send(server, Mono.just(msg)).defaultIfEmpty(-1).flatMapMany((len) -> {
if (len == 0) {
return this.operator.checkState().flatMapMany((state) -> {
if (1 != state) {
return interceptor.afterSent(this.operator, msg, Flux.error(new DeviceOperationException(ErrorCode.CLIENT_OFFLINE)));
} else if (StringUtils.hasText(parentGatewayId)) {
log.debug("Device [{}] Cached Server [{}] Not Available,Dispatch To Parent [{}]", new Object[]{this.operator.getDeviceId(), server, parentGatewayId});
return interceptor.afterSent(this.operator, msg, this.sendToParentDevice(parentGatewayId, msg)).map((r) -> {
return r;
});
} else {
log.warn("Device [{}] Cached Server [{}] Not Available", this.operator.getDeviceId(), server);
return interceptor.afterSent(this.operator, msg, Flux.error(new DeviceOperationException(ErrorCode.SERVER_NOT_AVAILABLE)));
}
});
} else if (len == -1) {
return interceptor.afterSent(this.operator, msg, Flux.error(new DeviceOperationException(ErrorCode.CLIENT_OFFLINE)));
} else {
log.debug("send device[{}] message complete", this.operator.getDeviceId());
return interceptor.afterSent(this.operator, msg, replyStream);
}
}).doOnNext((r) -> {
DeviceMessageTracer.trace(r, "send.reply");
});
}
}).as((flux) -> {
return interceptor.doSend(this.operator, msg, flux.cast(DeviceMessage.class)).map((_resp) -> {
return _resp;
});
});
});
});
}
EventBusDeviceOperationBroker
- send:发送消息给设备会先发一条 /_sys/msg-broker/ 消息到消息总线,再由消息总线统一发送消息给设备。
- handleSendToDeviceMessage: 系统启动的时候会订阅 /_sys/msg-broker/ 消息
public Mono<Integer> send(String deviceGatewayServerId, Publisher<? extends Message> message) {
return this.eventBus.publish("/_sys/msg-broker/" + deviceGatewayServerId, messageCodec, Flux.from(message).doOnNext((msg) -> {
msg.addHeader(Headers.sendFrom, this.serverId);
})).map(Long::intValue);
}
public Flux<Message> handleSendToDeviceMessage(String serverId) {
Subscription subscription = Subscription.of("device-message-broker", new String[]{"/_sys/msg-broker/" + serverId}, new Subscription.Feature[]{Feature.local, Feature.broker});
return this.eventBus.subscribe(subscription, messageCodec).doOnNext((message) -> {
if (message instanceof RepayableDeviceMessage && !(Boolean)message.getHeader(Headers.sendAndForget).orElse(false)) {
boolean isSameServer = (Boolean)message.getHeader(Headers.sendFrom).map((sendFrom) -> {
return sendFrom.equals(serverId);
}).orElse(false);
if (!isSameServer) {
this.awaits.put(this.getAwaitReplyKey((RepayableDeviceMessage)message), (RepayableDeviceMessage)message);
}
}
});
}
DefaultSendToDeviceMessageHandler
启动的时候会订阅 /_sys/msg-broker/ 消息,并注册消费者发送消息给设备
public class DefaultSendToDeviceMessageHandler {
private static final Logger log = LoggerFactory.getLogger(DefaultSendToDeviceMessageHandler.class);
private final String serverId;
private final DeviceSessionManager sessionManager;
private final MessageHandler handler; // 使用的实现是 EventBusDeviceOperationBroker
private final DeviceRegistry registry;
private final DecodedClientMessageHandler decodedClientMessageHandler;
public void startup() {
// 启动的时候会调用这里的逻辑
// this.handler.handleSendToDeviceMessage 是向EventBus里面增加一个订阅/_sys/msg-broker/的订阅
// 然后注册订阅者,订阅者会调用handleDeviceMessage()方法,该方法获取DeviceSession后发送消息
this.handler.handleSendToDeviceMessage(this.serverId).subscribe((message) -> {
try {
if (message instanceof DeviceMessage) {
this.handleDeviceMessage((DeviceMessage)message);
}
} catch (Throwable var3) {
log.error("handle send to device message error {}", message, var3);
}
});
this.handler.handleGetDeviceState(this.serverId, (deviceId) -> {
return Flux.from(deviceId).map((id) -> {
return new DeviceStateInfo(id, (byte)(this.sessionManager.sessionIsAlive(id) ? 1 : -1));
});
});
}
protected void handleDeviceMessage(DeviceMessage message) {
String deviceId = message.getDeviceId();
DeviceSession session = this.sessionManager.getSession(deviceId);
if (session != null) {
this.doSend(message, session);
}
// ...省略
}
真正的设备消息发送逻辑
//TODO
DeviceSession deviceSession;
MqttConnectionSession mqttConnectionSession; // DeviceSession 的实现
MqttEndpoint mqttEndpoint;
MqttConnection mqttConnection;
VertxMqttConnection vertxMqttConnection; // MqttConnection 的实现
使用webscoket订阅平台消息
//TODO
DefaultMessagingManager defaultMessagingManager; // 保存所有平台的订阅信息
WebSocketMessagingHandler webSocketMessagingHandler; // 向DefaultMessagingManager注册消费者,获取所有消息并推送给websocket客户端