feat(sj_1.3.0-beta1): 设置客户端client为-1时,支持随机端口号

This commit is contained in:
srzou 2024-12-05 14:39:14 +08:00
parent ed4161d9d9
commit ac1e679409
2 changed files with 117 additions and 2 deletions

View File

@ -15,17 +15,19 @@ import com.aizuda.snailjob.common.core.grpc.auto.Metadata;
import com.aizuda.snailjob.common.core.util.NetUtil;
import com.aizuda.snailjob.common.log.SnailJobLog;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.protobuf.Any;
import com.google.protobuf.UnsafeByteOperations;
import io.grpc.ManagedChannel;
import io.grpc.MethodDescriptor;
import io.grpc.protobuf.ProtoUtils;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author: opensnail
@ -57,6 +59,11 @@ public final class GrpcChannel {
*/
private static final String SNAIL_JOB_CLIENT_HOST = "snail-job.host";
private static final Integer MIN_PORT = 15000;
private static final Integer MAX_PORT = 50000;
private static final ReentrantLock PORT_LOCK = new ReentrantLock();
private static final Integer RANDOM_CLIENT_PORT = -1;
private static final String HOST_ID = IdUtil.getSnowflake().nextIdStr();
private static final int PORT;
private static final String HOST;
@ -130,12 +137,62 @@ public final class GrpcChannel {
// 获取客户端指定的端口
if (Objects.isNull(port)) {
port = Optional.ofNullable(serverProperties.getPort()).orElse(PORT);
snailJobProperties.setPort(port);
SnailJobLog.LOCAL.info("snail job client port :{}", port);
} else if (port.equals(RANDOM_CLIENT_PORT)) {
// 使用随机算法获取端口
PORT_LOCK.lock();
try {
// 双重检查避免重复获取端口
if (snailJobProperties.getPort().equals(RANDOM_CLIENT_PORT)) {
port = getAvailablePort();
snailJobProperties.setPort(port);
SnailJobLog.LOCAL.info("snail job client port :{}", port);
} else {
port = snailJobProperties.getPort();
}
} finally {
PORT_LOCK.unlock();
}
}
return port;
}
/**
* 获取随机可用的端口
*
* @return 可用端口号
*/
private static Integer getAvailablePort() {
int port;
do {
port = MIN_PORT + (int) (Math.random()*(MAX_PORT - MIN_PORT));
}while (!isPortAvailable(port));
return port;
}
/**
* 检查端口是否可以使用
*
* @param port 端口号
* @return 是否可用
*/
private static boolean isPortAvailable(int port) {
try (ServerSocket serverSocket = new ServerSocket()) {
// 设置端口重用
serverSocket.setReuseAddress(true);
// 绑定端口
serverSocket.bind(new InetSocketAddress(port));
return true;
} catch (IOException e) {
return false;
}
}
public static ListenableFuture<GrpcResult> sendOfUnary(String path, String body, final long reqId) {
if (channel == null) {
return null;

View File

@ -17,9 +17,13 @@ import io.netty.handler.codec.http.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author opensnail
@ -51,6 +55,11 @@ public class NettyChannel {
*/
private static final String SNAIL_JOB_CLIENT_HOST = "snail-job.host";
private static final Integer MIN_PORT = 15000;
private static final Integer MAX_PORT = 50000;
private static final ReentrantLock PORT_LOCK = new ReentrantLock();
private static final Integer RANDOM_CLIENT_PORT = -1;
private static final String HOST_ID = IdUtil.getSnowflake().nextIdStr();
private static final int PORT;
private static final String HOST;
@ -124,11 +133,60 @@ public class NettyChannel {
// 获取客户端指定的端口
if (Objects.isNull(port)) {
port = Optional.ofNullable(serverProperties.getPort()).orElse(PORT);
snailJobProperties.setPort(port);
SnailJobLog.LOCAL.info("snail job client port :{}", port);
} else if (port.equals(RANDOM_CLIENT_PORT)) {
// 使用随机算法获取端口
PORT_LOCK.lock();
try {
// 双重检查避免重复获取端口
if (snailJobProperties.getPort().equals(RANDOM_CLIENT_PORT)) {
port = getAvailablePort();
snailJobProperties.setPort(port);
SnailJobLog.LOCAL.info("snail job client port :{}", port);
} else {
port = snailJobProperties.getPort();
}
} finally {
PORT_LOCK.unlock();
}
}
return port;
}
/**
* 获取随机可用的端口
*
* @return 可用端口号
*/
private static Integer getAvailablePort() {
int port;
do {
port = MIN_PORT + (int) (Math.random() * (MAX_PORT - MIN_PORT));
} while (!isPortAvailable(port));
return port;
}
/**
* 检查端口是否可以使用
*
* @param port 端口号
* @return 是否可用
*/
private static boolean isPortAvailable(int port) {
try (ServerSocket serverSocket = new ServerSocket()) {
// 设置端口重用
serverSocket.setReuseAddress(true);
// 绑定端口
serverSocket.bind(new InetSocketAddress(port));
return true;
} catch (IOException e) {
return false;
}
}
public static void setChannel(Channel channel) {
NettyChannel.CHANNEL = channel;