前景回顧
【mq】從零開始實現 mq-02-如何實現生產者調用消費者?
【mq】從零開始實現 mq-03-引入 broker 中間人
【mq】從零開始實現 mq-06-消費者心跳檢測 heartbeat
【mq】從零開始實現 mq-07-負載均衡 load balance
【mq】從零開始實現 mq-09-消費者拉取消息 pull message
【mq】從零開始實現 mq-10-消費者拉取消息回執 pull message ack
【mq】從零開始實現 mq-11-消費者消息回執添加分組信息 pull message ack groupName
註冊鑑權
我們前面實現了 mq 的基本功能,不過還是存在一個問題,那就是 mq 沒有進行鑑權。
這就會導致如果部署在公網,任何一個機器都可以連接我們的服務,這顯然是不夠安全的。
生產者實現
屬性
生產者啓動時新增 2 個屬性:
/**
* 賬戶標識
* @since 0.1.4
*/
private String appKey;
/**
* 賬戶密碼
* @since 0.1.4
*/
private String appSecret;
註冊邏輯調整
註冊時,添加這兩個屬性到服務端。
public void registerToBroker() {
int successCount = 0;
for(RpcChannelFuture channelFuture : this.channelFutureList) {
ServiceEntry serviceEntry = new ServiceEntry();
serviceEntry.setGroupName(groupName);
serviceEntry.setAddress(channelFuture.getAddress());
serviceEntry.setPort(channelFuture.getPort());
serviceEntry.setWeight(channelFuture.getWeight());
BrokerRegisterReq brokerRegisterReq = new BrokerRegisterReq();
brokerRegisterReq.setServiceEntry(serviceEntry);
brokerRegisterReq.setMethodType(MethodType.P_REGISTER);
brokerRegisterReq.setTraceId(IdHelper.uuid32());
brokerRegisterReq.setAppKey(appKey);
brokerRegisterReq.setAppSecret(appSecret);
log.info("[Register] 開始註冊到 broker:{}", JSON.toJSON(brokerRegisterReq));
final Channel channel = channelFuture.getChannelFuture().channel();
MqCommonResp resp = callServer(channel, brokerRegisterReq, MqCommonResp.class);
log.info("[Register] 完成註冊到 broker:{}", JSON.toJSON(resp));
if(MqCommonRespCode.SUCCESS.getCode().equals(resp.getRespCode())) {
successCount++;
}
}
if(successCount <= 0 && check) {
log.error("校驗 broker 可用性,可連接成功數爲 0");
throw new MqException(MqCommonRespCode.P_REGISTER_TO_BROKER_FAILED);
}
}
消費者
消費者連接到 broker 也是類似的,此處不做贅述。
Broker 的處理
註冊邏輯
以前註冊是直接成功,此處加一個業務判斷。
// 生產者註冊
if(MethodType.P_REGISTER.equals(methodType)) {
BrokerRegisterReq registerReq = JSON.parseObject(json, BrokerRegisterReq.class);
if(!brokerRegisterValidService.producerValid(registerReq)) {
log.error("{} 生產者註冊驗證失敗", JSON.toJSON(registerReq));
throw new MqException(MqBrokerRespCode.P_REGISTER_VALID_FAILED);
}
return registerProducerService.register(registerReq.getServiceEntry(), channel);
}
首先會校驗有效性,這個是一個接口,可自行靈活替換。
其他業務邏輯
其他業務處理時,都需要 registerProducerService.checkValid(channelId);
進行有效性判斷。
// 生產者註銷
if(MethodType.P_UN_REGISTER.equals(methodType)) {
registerProducerService.checkValid(channelId);
BrokerRegisterReq registerReq = JSON.parseObject(json, BrokerRegisterReq.class);
return registerProducerService.unRegister(registerReq.getServiceEntry(), channel);
}
小結
註冊鑑權實現的原理非常簡單,不過可以爲安全性提供最基礎的保障。
希望本文對你有所幫助,如果喜歡,歡迎點贊收藏轉發一波。
我是老馬,期待與你的下次重逢。
開源地址
The message queue in java.(java 簡易版本 mq 實現) https://github.com/houbb/mq