feat:Websocket服务拆到单独服务,主后台保持单工通信

This commit is contained in:
zpaeng
2025-09-02 23:10:29 +08:00
parent c337195b16
commit 78a65c6afe
35 changed files with 1504 additions and 329 deletions

View File

@@ -0,0 +1,84 @@
package com.openisle.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.Map;
import java.util.stream.Collectors;
@Component
@Slf4j
public class ShardingStrategy {
// 固定为16以匹配RabbitMQConfig中的十六进制分片逻辑
private static final int QUEUE_COUNT = 16;
// 分片分布统计
private final Map<Integer, AtomicLong> shardCounts = new ConcurrentHashMap<>();
/**
* 根据用户名获取分片信息(基于哈希值首字符)
*/
public ShardInfo getShardInfo(String username) {
if (username == null || username.isEmpty()) {
// 空用户名默认分到第0个分片
return getShardInfoByIndex(0);
}
// 计算用户名的哈希值并转为十六进制字符串
String hash = Integer.toHexString(Math.abs(username.hashCode()));
// 取哈希值的第一个字符 (0-9, a-f)
char firstChar = hash.charAt(0);
// 十六进制字符映射到队列
int shard = getShardFromHexChar(firstChar);
recordShardUsage(shard);
log.debug("Username '{}' -> hash '{}' -> firstChar '{}' -> shard {}",
username, hash, firstChar, shard);
return getShardInfoByIndex(shard);
}
/**
* 将十六进制字符映射到分片索引
*/
private int getShardFromHexChar(char hexChar) {
int charValue;
if (hexChar >= '0' && hexChar <= '9') {
charValue = hexChar - '0'; // 0-9
} else if (hexChar >= 'a' && hexChar <= 'f') {
charValue = hexChar - 'a' + 10; // 10-15
} else {
// 异常情况默认为0
charValue = 0;
}
// 映射到队列数量范围内
return charValue % QUEUE_COUNT;
}
/**
* 根据分片索引获取分片信息
*/
private ShardInfo getShardInfoByIndex(int shard) {
String shardKey = Integer.toHexString(shard);
return new ShardInfo(
shard,
"notifications-queue-" + shardKey,
"notifications.shard." + shardKey
);
}
/**
* 记录分片使用统计
*/
private void recordShardUsage(int shard) {
shardCounts.computeIfAbsent(shard, k -> new AtomicLong(0)).incrementAndGet();
}
}