diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 9981530d30efc717f134ceaf4ac34439cc7818c2..0000000000000000000000000000000000000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# RAS-分布式注册中心 - -#### Description -RAS-分布式注册中心:对服务进行注册和发现,提供服务端和客户端运行机制和通信 - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/admin/pom.xml b/admin/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..e2db2a98829a795d7e44978654d6986b296d0c64 --- /dev/null +++ b/admin/pom.xml @@ -0,0 +1,19 @@ + + + + ras-parent + cn.icanci.loopstack.ras + 1.0-SNAPSHOT + + 4.0.0 + + ras-admin + + + 8 + 8 + + + \ No newline at end of file diff --git a/client/pom.xml b/client/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..94241e2eaebbc395184798f0313ca5d28374062e --- /dev/null +++ b/client/pom.xml @@ -0,0 +1,78 @@ + + + + ras-parent + cn.icanci.loopstack.ras + 1.0-SNAPSHOT + + 4.0.0 + + ras-client + + + 8 + 8 + + + + + cn.icanci.loopstack.ras + ras-common + ${parent.version} + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-autoconfigure + + + org.aspectj + aspectjweaver + + + org.springframework.boot + spring-boot-configuration-processor + compile + true + + + org.apache.commons + commons-lang3 + + + org.apache.commons + commons-collections4 + + + com.google.guava + guava + + + io.netty + netty-all + + + cn.icanci.loopstack + lsi-api + + + cn.icanci.loopstack + lsi-common + + + cn.icanci.loopstack + lsi-utils + + + \ No newline at end of file diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/RasClientAutoConfig.java b/client/src/main/java/cn/icanci/loopstack/ras/client/RasClientAutoConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..e017fa77403f240e0c70b0cdc63fece0017d2fc5 --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/RasClientAutoConfig.java @@ -0,0 +1,19 @@ +package cn.icanci.loopstack.ras.client; + +import cn.icanci.loopstack.ras.client.properties.RasProperties; + +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/06 22:27 + */ +@Configuration +@ComponentScan({ "cn.icanci.loopstack.ras.client" }) +@EnableConfigurationProperties(RasProperties.class) +@AutoConfigureBefore +public class RasClientAutoConfig { +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/aop/RpcCallAop.java b/client/src/main/java/cn/icanci/loopstack/ras/client/aop/RpcCallAop.java new file mode 100644 index 0000000000000000000000000000000000000000..6e39d12b03e4a895a01fe25b41ce44962e8da34a --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/aop/RpcCallAop.java @@ -0,0 +1,33 @@ +package cn.icanci.loopstack.ras.client.aop; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.stereotype.Component; + +/** + * AOP拦截 + * + * @author icanci + * @since 1.0 Created in 2023/01/16 19:56 + */ +@Aspect +@Component +public class RpcCallAop { + + @Pointcut("execution(public * cn.icanci.loopstack.ras.client.facade.RpcCallFacade.call(..))") + private void callAop() { + + } + + @Around("callAop()") + public Object doBefore(ProceedingJoinPoint pjp) throws Throwable { + Object[] args = pjp.getArgs(); + long startTime = System.currentTimeMillis(); + Object returnVal = pjp.proceed(); + long endTime = System.currentTimeMillis(); + // 只记录执行时间即可 + return returnVal; + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/exception/RpcCallException.java b/client/src/main/java/cn/icanci/loopstack/ras/client/exception/RpcCallException.java new file mode 100644 index 0000000000000000000000000000000000000000..1f914a5068c4cdf904736da2ac009b80bea6545b --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/exception/RpcCallException.java @@ -0,0 +1,29 @@ +package cn.icanci.loopstack.ras.client.exception; + +/** + * RPC调用异常 + * + * @author icanci + * @since 1.0 Created in 2023/01/19 19:53 + */ +public class RpcCallException extends RuntimeException { + public RpcCallException() { + super(); + } + + public RpcCallException(String message) { + super(message); + } + + public RpcCallException(String message, Throwable cause) { + super(message, cause); + } + + public RpcCallException(Throwable cause) { + super(cause); + } + + protected RpcCallException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/exception/ServiceNotFoundException.java b/client/src/main/java/cn/icanci/loopstack/ras/client/exception/ServiceNotFoundException.java new file mode 100644 index 0000000000000000000000000000000000000000..32d051018dfe54ab7a1101b3eaee890454534cc9 --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/exception/ServiceNotFoundException.java @@ -0,0 +1,29 @@ +package cn.icanci.loopstack.ras.client.exception; + +/** + * 服务不存异常 + * + * @author icanci + * @since 1.0 Created in 2023/01/19 20:15 + */ +public class ServiceNotFoundException extends RuntimeException { + public ServiceNotFoundException() { + super(); + } + + public ServiceNotFoundException(String message) { + super(message); + } + + public ServiceNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public ServiceNotFoundException(Throwable cause) { + super(cause); + } + + protected ServiceNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/facade/RpcCallFacade.java b/client/src/main/java/cn/icanci/loopstack/ras/client/facade/RpcCallFacade.java new file mode 100644 index 0000000000000000000000000000000000000000..77bc2d68c09b53d7427a8540182be85e77de0a93 --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/facade/RpcCallFacade.java @@ -0,0 +1,148 @@ +package cn.icanci.loopstack.ras.client.facade; + +import cn.hutool.http.Method; +import cn.icanci.loopstack.api.client.Client; +import cn.icanci.loopstack.api.client.http.HttpClientImpl; +import cn.icanci.loopstack.ras.client.exception.RpcCallException; +import cn.icanci.loopstack.ras.client.holder.RasRepositoryHolder; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import javax.annotation.Resource; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import com.google.common.collect.Maps; + +/** + * 请求说明 + * - relativePath: 指的是暴露服务的路径,比如服务地址 => http://127.0.0.1:8080/ddk/condig/query + * 其暴露的服务相对路径为 => /ddk/condig/query + * + * @author icanci + * @since 1.0 Created in 2023/01/19 19:26 + */ +@Service +public class RpcCallFacade { + + private static final Map DEFAULT_HEADERS = Maps.newHashMap(); + + private static final Method DEFAULT_METHOD = Method.POST; + + private static final int DEFAULT_READ_TIMEOUT = 3; + + private static final int DEFAULT_RETRY = 0; + + /** + * RPC 请求客户端 + */ + private static final Client CLIENT = HttpClientImpl.getInstance(); + + @Resource + private RasRepositoryHolder rasRepositoryHolder; + + /** + * Get请求调用 + * + * @param appId appId + * @param relativePath 请求相对路径 + * @param request 请求 + * @param headers 请求头 + * @param readTimeOut 请求超时时间(单位 秒) + * @param retry 重试次数 + * @param clazz 请求返回类型 + * @param 请求返回泛型 + * @return 返回请求返回数据 + */ + public T getCall(String appId, String relativePath, Object request, Map headers, int readTimeOut, int retry, Class clazz) { + return call(appId, relativePath, request, headers, Method.GET, readTimeOut, retry, clazz); + } + + /** + * post请求调用 + * + * @param appId appId + * @param relativePath 请求相对路径 + * @param request 请求 + * @param headers 请求头 + * @param readTimeOut 请求超时时间(单位 秒) + * @param retry 重试次数 + * @param clazz 请求返回类型 + * @param 请求返回泛型 + * @return 返回请求返回数据 + */ + public T postCall(String appId, String relativePath, Object request, Map headers, int readTimeOut, int retry, Class clazz) { + return call(appId, relativePath, request, headers, Method.POST, readTimeOut, retry, clazz); + } + + /** + * 默认get请求调用 + * + * @param appId appId + * @param relativePath 请求相对路径 + * @param request 请求 + * @param clazz 请求返回类型 + * @param 请求返回泛型 + * @return 返回请求返回数据 + */ + public T defaultGetCall(String appId, String relativePath, Object request, Class clazz) { + return call(appId, relativePath, request, DEFAULT_HEADERS, Method.GET, DEFAULT_READ_TIMEOUT, DEFAULT_RETRY, clazz); + } + + /** + * 默认post请求调用 + * + * @param appId appId + * @param relativePath 请求相对路径 + * @param request 请求 + * @param clazz 请求返回类型 + * @param 请求返回泛型 + * @return 返回请求返回数据 + */ + public T defaultPostCall(String appId, String relativePath, Object request, Class clazz) { + return call(appId, relativePath, request, DEFAULT_HEADERS, Method.POST, DEFAULT_READ_TIMEOUT, DEFAULT_RETRY, clazz); + } + + /** + * 请求调用 + * + * @param appId appId + * @param relativePath 请求相对路径 + * @param request 请求 + * @param headers 请求头 + * @param method 请求方法 + * @param readTimeOut 请求超时时间(单位 秒) + * @param retry 重试次数 + * @param clazz 请求返回类型 + * @param 请求返回泛型 + * @return 返回请求返回数据 + */ + public T call(String appId, String relativePath, Object request, Map headers, Method method, int readTimeOut, int retry, Class clazz) { + // 构建请求参数 + Client.RpcRequest rpcRequest = new Client.RpcRequest(resolvingRequestUrl(appId, relativePath), request, headers == null ? DEFAULT_HEADERS : headers, method, readTimeOut, + TimeUnit.SECONDS, retry); + + // 调用 + return CLIENT.call(rpcRequest, clazz); + } + + /** + * 从仓储中获取此次执行的请求数据 + * + * @param appId appId + * @param relativePath 请求相对路径 + * @return 返回需要执行的请求地址 + */ + private String resolvingRequestUrl(String appId, String relativePath) { + if (StringUtils.isBlank(relativePath)) { + throw new RpcCallException("The relativePath is null! Please check your config!"); + } + + String prefixUrl = rasRepositoryHolder.routingRequestAddress(appId); + + return prefixUrl + relativePath; + } + +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/holder/ApplicationHolder.java b/client/src/main/java/cn/icanci/loopstack/ras/client/holder/ApplicationHolder.java new file mode 100644 index 0000000000000000000000000000000000000000..4f7d5da0aecb7022fb5b98d3a90a0e6694b7be33 --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/holder/ApplicationHolder.java @@ -0,0 +1,14 @@ +package cn.icanci.loopstack.ras.client.holder; + +import cn.icanci.loopstack.ras.common.enums.LoadBalanceTypeEnum; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/19 17:25 + */ +public class ApplicationHolder { + /** + * 负载均衡模式 + */ + private LoadBalanceTypeEnum loadBalanceType; +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/holder/RasRepositoryHolder.java b/client/src/main/java/cn/icanci/loopstack/ras/client/holder/RasRepositoryHolder.java new file mode 100644 index 0000000000000000000000000000000000000000..f8bd91f221efe26010186dd0be20e54115d08155 --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/holder/RasRepositoryHolder.java @@ -0,0 +1,147 @@ +package cn.icanci.loopstack.ras.client.holder; + +import cn.hutool.http.Method; +import cn.hutool.json.JSONUtil; +import cn.icanci.loopstack.api.client.Client; +import cn.icanci.loopstack.api.client.http.HttpClientImpl; +import cn.icanci.loopstack.lsi.common.result.R; +import cn.icanci.loopstack.ras.client.properties.RasProperties; +import cn.icanci.loopstack.ras.client.server.NamedNettyServerHandler; +import cn.icanci.loopstack.ras.client.utils.RandomAddressUtils; +import cn.icanci.loopstack.ras.common.exception.ServerOfflineException; +import cn.icanci.loopstack.ras.common.model.Application; +import cn.icanci.loopstack.ras.common.socket.RasLoadRequestDTO; +import cn.icanci.loopstack.ras.common.socket.RasRefreshDTO; +import cn.icanci.loopstack.ras.common.socket.UriConstant; +import io.netty.util.internal.ThrowableUtil; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Service; + +import com.google.common.collect.Maps; + +/** + * 客户端知晓的服务端信息 + * - + * @author icanci + * @since 1.0 Created in 2023/01/19 17:06 + */ +@Service +public class RasRepositoryHolder implements InitializingBean { + + private static final Logger logger = LoggerFactory.getLogger(RasRepositoryHolder.class); + + @Resource + private RasProperties rasProperties; + + /** + * http://{address}:port+UriConstant.ToClient.LOAD + */ + private static final String LOAD_REQUEST_FORMAT = "http://%s:%s" + UriConstant.ToServer.LOAD; + /** + * 请求地址 + */ + private static final String REQUEST_FORMAT = "http://%s:%s"; + + /** + * 客户端 + */ + private static final Client CLIENT = HttpClientImpl.getInstance(); + + @Override + public void afterPropertiesSet() throws Exception { + // 1.加载数据 + toLoad(); + // 2.注入对象 + NamedNettyServerHandler.setRasRepositoryHolder(this); + } + + /** + * 服务启动加载数据 + */ + private void toLoad() { + RasRefreshDTO rasRefresh = loadConfigs(); + refresh(rasRefresh); + } + + /** + * 加载远程数据 + */ + private RasRefreshDTO loadConfigs() { + String serverIps = rasProperties.getServerIps(); + int serverPort = rasProperties.getServerPort(); + int clientPort = rasProperties.getClientPort(); + String appId = rasProperties.getAppId(); + + String[] serverAddress = serverIps.split(","); + + RandomAddressUtils.randomAddress(serverAddress); + + for (String address : serverAddress) { + try { + String reqUrl = String.format(LOAD_REQUEST_FORMAT, address, serverPort); + + RasLoadRequestDTO requestDTO = new RasLoadRequestDTO(appId, address, clientPort); + + Client.RpcRequest rpcRequest = new Client.RpcRequest(reqUrl, requestDTO, Maps.newHashMap(), Method.POST, 3, TimeUnit.SECONDS, 3); + + R call = CLIENT.call(rpcRequest, R.class); + + logger.info("[RasRepositoryHolder][call] Load result:{}", JSONUtil.toJsonStr(call)); + + return JSONUtil.toBean(call.getData().get("response").toString(), RasRefreshDTO.class); + } catch (Exception ex) { + logger.error("[RasRepositoryHolder][call] Ex error message:{}", ThrowableUtil.stackTraceToString(ex)); + } + } + throw new ServerOfflineException("All Server IP are Requested, and All failed!!! Please Check your Config, The Server IPs are: " + serverIps); + } + + /** + * 服务信息缓存刷新 + * + * @param refresh refresh + */ + public void refresh(RasRefreshDTO refresh) { + // 先刷新服务端信息 + refreshServerInfo(refresh.getServerApplication()); + // 再刷新客户端信息 + refreshClientInfo(refresh.getClientApplications()); + } + + /** + * 刷新服务端信息 + * + * @param serverApplication serverApplication + */ + private void refreshServerInfo(Application serverApplication) { + // 这里服务端的信息不可能为,因为数据是从服务端请求而来的 + } + + /** + * 刷新客户端信息 + * + * @param clientApplications clientApplications + */ + private void refreshClientInfo(List clientApplications) { + + } + + /** + * 返回请求执行路由地址 + * + * @param appId 应用id + * @return 返回请求地址 ip+port + */ + public String routingRequestAddress(String appId) { + // REQUEST_FORMAT + return null; + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/package-info.java b/client/src/main/java/cn/icanci/loopstack/ras/client/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..6c030bec0beddc56e2243806a60370ac678adbde --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/package-info.java @@ -0,0 +1,5 @@ +/** + * @author icanci + * @since 1.0 Created in 2023/01/19 08:48 + */ +package cn.icanci.loopstack.ras.client; \ No newline at end of file diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/properties/RasProperties.java b/client/src/main/java/cn/icanci/loopstack/ras/client/properties/RasProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..434448780fbba914dbd3e01c76efc3797ee3e689 --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/properties/RasProperties.java @@ -0,0 +1,62 @@ +package cn.icanci.loopstack.ras.client.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/06 22:28 + */ +@Component +@ConfigurationProperties(prefix = "ras") +public class RasProperties { + /** + * appId + */ + private String appId; + + /** + * 客户端注册的port + */ + private int clientPort = 11000; + /** + * 服务端ip,以,分隔 + */ + private String serverIps = "127.0.0.1"; + /** + * 服务端port + */ + private int serverPort = 9995; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public int getClientPort() { + return clientPort; + } + + public void setClientPort(int clientPort) { + this.clientPort = clientPort; + } + + public String getServerIps() { + return serverIps; + } + + public void setServerIps(String serverIps) { + this.serverIps = serverIps; + } + + public int getServerPort() { + return serverPort; + } + + public void setServerPort(int serverPort) { + this.serverPort = serverPort; + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/server/NamedNettyServerHandler.java b/client/src/main/java/cn/icanci/loopstack/ras/client/server/NamedNettyServerHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..15d8307d2f0ce6b2e75f443ae155f596f2e83eef --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/server/NamedNettyServerHandler.java @@ -0,0 +1,135 @@ +package cn.icanci.loopstack.ras.client.server; + +import cn.hutool.json.JSONUtil; +import cn.icanci.loopstack.ras.client.holder.RasRepositoryHolder; +import cn.icanci.loopstack.ras.common.socket.RasRefreshDTO; +import cn.icanci.loopstack.ras.common.socket.SocketMessage; +import cn.icanci.loopstack.ras.common.socket.UriConstant; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.*; +import io.netty.handler.timeout.IdleStateEvent; +import io.netty.util.CharsetUtil; +import io.netty.util.internal.ThrowableUtil; + +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/06 22:49 + */ +@SuppressWarnings("all") +public class NamedNettyServerHandler extends SimpleChannelInboundHandler { + + private static final Logger logger = LoggerFactory.getLogger(NamedNettyServerHandler.class); + + private static RasRepositoryHolder rasRepositoryHolder; + + private static final int CORE_SIZE = Runtime.getRuntime().availableProcessors(); + + private static final ThreadPoolExecutor POOL = new ThreadPoolExecutor(CORE_SIZE, // + CORE_SIZE << 1, // + 60L, // + TimeUnit.SECONDS, // + new LinkedBlockingQueue<>(2000), // + runnable -> new Thread(runnable, "RasServerThread Pool-" + runnable.hashCode()), // + (r, executor) -> { + throw new RuntimeException("RasServerThread Pool is EXHAUSTED!"); + });; + + public NamedNettyServerHandler() { + } + + public static void setRasRepositoryHolder(RasRepositoryHolder rasRepositoryHolder) { + NamedNettyServerHandler.rasRepositoryHolder = rasRepositoryHolder; + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception { + String requestData = msg.content().toString(CharsetUtil.UTF_8); + String uri = msg.uri(); + HttpMethod httpMethod = msg.method(); + boolean keepAlive = HttpUtil.isKeepAlive(msg); + // 对于这种配置数据,会有很频繁的变更 + POOL.execute(() -> { + Object responseObj = process(httpMethod, uri, requestData); + + String responseJson = JSONUtil.toJsonStr(responseObj); + + writeResponse(ctx, keepAlive, responseJson); + }); + } + + /** + * 后置处理 + * + * @param httpMethod httpMethod + * @param uri uri + * @param requestData requestData + * @return Object + */ + private Object process(HttpMethod httpMethod, String uri, String requestData) { + if (HttpMethod.POST != httpMethod) { + return SocketMessage.fail("Only post requests are supported"); + } + if (StringUtils.isBlank(uri)) { + return SocketMessage.fail("Request uri is null"); + } + try { + switch (uri) { + case UriConstant.ToClient.HEARTBEAT: + logger.info("[{}][NamedNettyServerHandler][process] heartbeat", Thread.currentThread().getName()); + return SocketMessage.success(); + case UriConstant.ToClient.REFRESH: + // 在进行刷新的时候,如果是第一次,则是全局进行加载 + // 如果是增量数据,则是部分刷新,针对Client来说,对其来说只是刷新本地的数据,对到来的是什么数据不关心 + // 因此可以使用同一个方法进行处理 + rasRepositoryHolder.refresh(JSONUtil.toBean(requestData, RasRefreshDTO.class)); + logger.info("[{}][NamedNettyServerHandler][process] {} was refreshed!", Thread.currentThread().getName(), requestData); + return SocketMessage.success(); + default: + return SocketMessage.fail("Invalid request, uri-mapping(" + uri + ") not found"); + } + } catch (Throwable e) { + logger.error("[{}][NamedNettyServerHandler][process] ex,error msg:{}", e, Thread.currentThread().getName(), ThrowableUtil.stackTraceToString(e)); + return SocketMessage.fail(ThrowableUtil.stackTraceToString(e)); + } + } + + private void writeResponse(ChannelHandlerContext ctx, boolean keepAlive, String responseJson) { + FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.copiedBuffer(responseJson, CharsetUtil.UTF_8)); + response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=UTF-8"); + response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes()); + if (keepAlive) { + response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); + } + ctx.writeAndFlush(response); + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + logger.error(ThrowableUtil.stackTraceToString(cause)); + ctx.close(); + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof IdleStateEvent) { + ctx.channel().close(); + } else { + super.userEventTriggered(ctx, evt); + } + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/server/NamedServer.java b/client/src/main/java/cn/icanci/loopstack/ras/client/server/NamedServer.java new file mode 100644 index 0000000000000000000000000000000000000000..d42e6d8a0f25acb2664e955a25e89940a86a8866 --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/server/NamedServer.java @@ -0,0 +1,109 @@ +package cn.icanci.loopstack.ras.client.server; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.*; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.timeout.IdleStateHandler; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.LockSupport; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/01 09:55 + */ +@SuppressWarnings("all") +public class NamedServer { + + private static final Logger logger = LoggerFactory.getLogger(NamedServer.class); + + private static RegisterServer registerServer; + + public static void setRegisterService(RegisterServer registerServer) { + NamedServer.registerServer = registerServer; + } + + public static void startClient(String serverIps, int serverPort, int clientPort) { + // 启动时候注册 + startClient0(serverIps, serverPort, clientPort); + // 自动进行注册 + // Tips: 项目启动了,但是没有配置项目信息,此时注册失败,如果不自动注册,则需要进行重启才能注册。因此开启自助注册 + autoRegister(serverIps, serverPort, clientPort); + } + + private static void startClient0(String serverAddress, int serverPort, int clientPort) { + Thread rasThread = new Thread(() -> { + EventLoopGroup bossGroup = new NioEventLoopGroup(); + EventLoopGroup workerGroup = new NioEventLoopGroup(); + + ServerBootstrap bootstrap = new ServerBootstrap(); + + bootstrap.group(bossGroup, workerGroup) // + .channel(NioServerSocketChannel.class) // + .childHandler(new ChannelInitializer() { + @Override + public void initChannel(SocketChannel channel) throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + pipeline.addLast(new IdleStateHandler(0, 0, 30, TimeUnit.SECONDS)); + pipeline.addLast(new HttpServerCodec()); + pipeline.addLast(new HttpObjectAggregator(5 * 1024 * 1024)); + pipeline.addLast(new NamedNettyServerHandler()); + } + }).childOption(ChannelOption.SO_KEEPALIVE, true); + + try { + ChannelFuture future = bootstrap.bind(clientPort).sync(); + + doRegistry(serverAddress, serverPort, clientPort); + + future.channel().closeFuture().sync(); + + } catch (InterruptedException e) { + logger.info("RAS remoting server interruptedException", e); + } catch (Exception e) { + logger.info("RAS remoting server error", e); + } finally { + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + + }); + rasThread.setDaemon(true); + rasThread.start(); + } + + /** + * 将SDK所在服务注册到注册中心 + * + * @param serverAddress 服务端ip地址 + * @param serverPort 服务端端口 + * @param clientPort 客户端端口 + */ + private static void doRegistry(String serverAddress, int serverPort, int clientPort) { + registerServer.register(serverAddress, serverPort, clientPort); + } + + /** + * 自动注册 + * + * @param serverAddress 服务端ip地址 + * @param serverPort 服务端端口 + * @param clientPort 客户端端口 + */ + private static void autoRegister(String serverAddress, int serverPort, int clientPort) { + Thread autoRegisterThread = new Thread(() -> { + // 每120秒刷新注册一次 + LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(120)); + doRegistry(serverAddress, serverPort, clientPort); + }); + autoRegisterThread.setDaemon(true); + autoRegisterThread.start(); + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/server/RegisterServer.java b/client/src/main/java/cn/icanci/loopstack/ras/client/server/RegisterServer.java new file mode 100644 index 0000000000000000000000000000000000000000..875f8fa1423bee689140ab05a7749a61d4aa89fe --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/server/RegisterServer.java @@ -0,0 +1,121 @@ +package cn.icanci.loopstack.ras.client.server; + +import cn.hutool.http.Method; +import cn.hutool.json.JSONUtil; +import cn.icanci.loopstack.api.client.Client; +import cn.icanci.loopstack.api.client.http.HttpClientImpl; +import cn.icanci.loopstack.lsi.common.result.R; +import cn.icanci.loopstack.ras.client.properties.RasProperties; +import cn.icanci.loopstack.ras.client.utils.RandomAddressUtils; +import cn.icanci.loopstack.ras.common.socket.RegisterDTO; +import cn.icanci.loopstack.ras.common.socket.UriConstant; +import cn.icanci.loopstack.utils.IPUtils; + +import java.util.concurrent.*; + +import javax.annotation.Resource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Service; + +import com.google.common.collect.Maps; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/06 22:30 + */ +@Service +@SuppressWarnings("all") +public class RegisterServer implements InitializingBean { + private static final Logger logger = LoggerFactory.getLogger(RegisterServer.class); + /** http实例 */ + private static final Client CLIENT = HttpClientImpl.getInstance(); + @Resource + private RasProperties rasProperties; + + private static final int CORE_SIZE = Runtime.getRuntime().availableProcessors(); + + private static final ThreadPoolExecutor REGISTER_POOL = new ThreadPoolExecutor(CORE_SIZE, // + CORE_SIZE << 1, // + 60L, // + TimeUnit.SECONDS, // + new LinkedBlockingQueue<>(2000), // + runnable -> new Thread(runnable, "RegisterClient Biz Pool-" + runnable.hashCode()), // + (r, executor) -> { + throw new RuntimeException("RegisterClient Biz Pool is EXHAUSTED!"); + }); + + /** 注册请求地址 */ + private static final String REQ_URL_FORMAT = "http://%s:%s%s"; + + /** + * 将SDK所在服务注册到注册中心 + * + * @param serverAddress 服务端ip地址 + * @param serverPort 服务端端口 + * @param clientPort 客户端端口 + */ + public void register(String serverAddress, int serverPort, int clientPort) { + String appId = rasProperties.getAppId(); + String[] addresses = serverAddress.split(","); + // 注册地址打散,防止压力在同一个机器上 + RandomAddressUtils.randomAddress(addresses); + // 执行注册 + for (String address : addresses) { + try { + FutureTask task = new FutureTask<>(new RegisterCallable(address, clientPort, appId, serverPort)); + REGISTER_POOL.execute(task); + R r = task.get(10, TimeUnit.SECONDS); + if (r.isOk()) { + break; + } else { + logger.error("Task Register Exception:{}", r.getMessage()); + } + } catch (ExecutionException | InterruptedException | TimeoutException e) { + logger.warn("Register Exception:{}", e.getMessage()); + } + } + } + + @Override + public void afterPropertiesSet() throws Exception { + + // 注入注册bean + NamedServer.setRegisterService(this); + + // 启动服务器 + NamedServer.startClient(rasProperties.getServerIps(), rasProperties.getServerPort(), rasProperties.getClientPort()); + } + + /** 注册器 */ + private static class RegisterCallable implements Callable { + + private final String address; + private final int clientPort; + private final String appId; + private final int serverPort; + + public RegisterCallable(String address, int clientPort, String appId, int serverPort) { + this.address = address; + this.clientPort = clientPort; + this.appId = appId; + this.serverPort = serverPort; + } + + @Override + public R call() throws Exception { + RegisterDTO registerDTO = new RegisterDTO(IPUtils.getHostIpAddress(), clientPort, appId); + String reqUrl = String.format(REQ_URL_FORMAT, address, serverPort, UriConstant.ToServer.REGISTER); + + Client.RpcRequest rpcRequest = new Client.RpcRequest(reqUrl, registerDTO, Maps.newHashMap(), Method.POST, 3, TimeUnit.SECONDS, 3); + + R call = CLIENT.call(rpcRequest, R.class); + + logger.info("[RegisterCallable][call] Register result:{}", JSONUtil.toJsonStr(call)); + + return call; + } + } +} diff --git a/client/src/main/java/cn/icanci/loopstack/ras/client/utils/RandomAddressUtils.java b/client/src/main/java/cn/icanci/loopstack/ras/client/utils/RandomAddressUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..db0ceb5e3d53cf6b4d3646b86f7d81ecb358ade2 --- /dev/null +++ b/client/src/main/java/cn/icanci/loopstack/ras/client/utils/RandomAddressUtils.java @@ -0,0 +1,28 @@ +package cn.icanci.loopstack.ras.client.utils; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/19 20:51 + */ +public class RandomAddressUtils { + private RandomAddressUtils() { + } + + /** + * randomAddress、 + * + * @param address address + */ + public static void randomAddress(String[] address) { + if (address.length == 1) { + return; + } + int length = address.length; + for (int i = 0; i < length; i++) { + int iRandNum = (int) (Math.random() * length); + String temp = address[iRandNum]; + address[iRandNum] = address[i]; + address[i] = temp; + } + } +} diff --git a/common/pom.xml b/common/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..ae9541403af27023c8d13e003fff6d486de3f2e8 --- /dev/null +++ b/common/pom.xml @@ -0,0 +1,19 @@ + + + + ras-parent + cn.icanci.loopstack.ras + 1.0-SNAPSHOT + + 4.0.0 + + ras-common + + + 8 + 8 + + + \ No newline at end of file diff --git a/common/src/main/java/cn/icanci/loopstack/ras/common/enums/LoadBalanceTypeEnum.java b/common/src/main/java/cn/icanci/loopstack/ras/common/enums/LoadBalanceTypeEnum.java new file mode 100644 index 0000000000000000000000000000000000000000..36e5fd9abc657906158ae41d1d9b44be236e7f6f --- /dev/null +++ b/common/src/main/java/cn/icanci/loopstack/ras/common/enums/LoadBalanceTypeEnum.java @@ -0,0 +1,59 @@ +package cn.icanci.loopstack.ras.common.enums; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/19 17:28 + */ +public enum LoadBalanceTypeEnum { + /** + * 第一个 + */ + FIRST("FIRST", "第一个"), + /** + * 最后一个 + */ + LAST("LAST", "最后一个"), + /** + * 按顺序 + */ + IN_ORDER("IN_ORDER", "按顺序"), + /** + * 随机 + */ + RANDOM("RANDOM", "随机"), + /** + * 一致性哈希 + */ + CONSISTENCY_HASH("CONSISTENCY_HASH", "一致性哈希"), + /** + * 最不经常使用 + */ + LEAST_FREQUENTLY_USED("LEAST_FREQUENTLY_USED", "最不经常使用"), + /** + * 最近最久未使用 + */ + LEAST_RECENTLY_USED("LEAST_RECENTLY_USED", "最近最久未使用"), + /** + * 调用速度最快 + */ + FASTEST_CALL_SPEED("FASTEST_CALL_SPEED", "调用速度最快"), + + // + ; + + LoadBalanceTypeEnum(String code, String desc) { + this.code = code; + this.desc = desc; + } + + private final String code; + private final String desc; + + public String getCode() { + return code; + } + + public String getDesc() { + return desc; + } +} diff --git a/common/src/main/java/cn/icanci/loopstack/ras/common/exception/ServerOfflineException.java b/common/src/main/java/cn/icanci/loopstack/ras/common/exception/ServerOfflineException.java new file mode 100644 index 0000000000000000000000000000000000000000..b3992a062edf2bbc4b7949cc5f4e4c2a9ed102e5 --- /dev/null +++ b/common/src/main/java/cn/icanci/loopstack/ras/common/exception/ServerOfflineException.java @@ -0,0 +1,27 @@ +package cn.icanci.loopstack.ras.common.exception; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/19 18:43 + */ +public class ServerOfflineException extends RuntimeException { + public ServerOfflineException() { + super(); + } + + public ServerOfflineException(String message) { + super(message); + } + + public ServerOfflineException(String message, Throwable cause) { + super(message, cause); + } + + public ServerOfflineException(Throwable cause) { + super(cause); + } + + protected ServerOfflineException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/common/src/main/java/cn/icanci/loopstack/ras/common/model/Application.java b/common/src/main/java/cn/icanci/loopstack/ras/common/model/Application.java new file mode 100644 index 0000000000000000000000000000000000000000..352ab52cff026a733c25f1687ba98fe093f93e74 --- /dev/null +++ b/common/src/main/java/cn/icanci/loopstack/ras/common/model/Application.java @@ -0,0 +1,46 @@ +package cn.icanci.loopstack.ras.common.model; + +import java.util.Set; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/18 22:06 + */ +public class Application { + /** + * AppId + */ + private String appId; + /** + * 负载均衡算法 + */ + private String loadBalanceType; + /** + * 注册的App + */ + private Set instances; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getLoadBalanceType() { + return loadBalanceType; + } + + public void setLoadBalanceType(String loadBalanceType) { + this.loadBalanceType = loadBalanceType; + } + + public Set getInstances() { + return instances; + } + + public void setInstances(Set instances) { + this.instances = instances; + } +} diff --git a/common/src/main/java/cn/icanci/loopstack/ras/common/model/Instance.java b/common/src/main/java/cn/icanci/loopstack/ras/common/model/Instance.java new file mode 100644 index 0000000000000000000000000000000000000000..0332ceae8de3e40c85c3805e2ccc614f9e0065b6 --- /dev/null +++ b/common/src/main/java/cn/icanci/loopstack/ras/common/model/Instance.java @@ -0,0 +1,117 @@ +package cn.icanci.loopstack.ras.common.model; + +import java.util.Date; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/18 22:06 + */ +public class Instance { + /** + * AppId 唯一 + */ + private String appId; + /** + * 客户端/服务端注册地址 + */ + private String address; + /** + * 客户端/服务端注册端口 + */ + private int port; + /** + * 创建时间 + */ + private Date createTime; + /** + * 更新时间 + */ + private Date updateTime; + /** + * 是否删除:状态 1无效,0有效(主动设置) + */ + private int isDelete; + /** + * 是否在线 1不在线,0在线(客户端注册处理) + */ + private int online; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public int getIsDelete() { + return isDelete; + } + + public void setIsDelete(int isDelete) { + this.isDelete = isDelete; + } + + public int getOnline() { + return online; + } + + public void setOnline(int online) { + this.online = online; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Instance instance = (Instance) o; + return port == instance.port && Objects.equals(appId, instance.appId) && Objects.equals(address, instance.address); + } + + @Override + public int hashCode() { + return Objects.hash(appId, address, port); + } + + @Override + public String toString() { + return new StringJoiner(",").add("appId=" + appId).add("address=" + address).add("port=" + port).add("createTime=" + createTime).add("updateTime=" + updateTime) + .add("isDelete=" + isDelete).add("online=" + online).toString(); + } +} diff --git a/common/src/main/java/cn/icanci/loopstack/ras/common/package-info.java b/common/src/main/java/cn/icanci/loopstack/ras/common/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..2c864d7e7e7e4d5a022b000925b4e7ec98e226c7 --- /dev/null +++ b/common/src/main/java/cn/icanci/loopstack/ras/common/package-info.java @@ -0,0 +1,5 @@ +/** + * @author icanci + * @since 1.0 Created in 2023/01/18 22:06 + */ +package cn.icanci.loopstack.ras.common; \ No newline at end of file diff --git a/common/src/main/java/cn/icanci/loopstack/ras/common/socket/RasLoadRequestDTO.java b/common/src/main/java/cn/icanci/loopstack/ras/common/socket/RasLoadRequestDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..3616eda7b5c742ca9943bf48ae29785891cd3093 --- /dev/null +++ b/common/src/main/java/cn/icanci/loopstack/ras/common/socket/RasLoadRequestDTO.java @@ -0,0 +1,55 @@ +package cn.icanci.loopstack.ras.common.socket; + +import java.io.Serializable; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/19 18:40 + */ +public class RasLoadRequestDTO implements Serializable { + /** + * 当前服务id + */ + private String appId; + /** + * 当前服务地址 + */ + private String address; + /** + * 当前服务的服务端口 + */ + private int port; + + public RasLoadRequestDTO() { + } + + public RasLoadRequestDTO(String appId, String address, int port) { + this.appId = appId; + this.address = address; + this.port = port; + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } +} diff --git a/common/src/main/java/cn/icanci/loopstack/ras/common/socket/RasRefreshDTO.java b/common/src/main/java/cn/icanci/loopstack/ras/common/socket/RasRefreshDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..6e27be753648b560ac36037461c1f2bb25857cbd --- /dev/null +++ b/common/src/main/java/cn/icanci/loopstack/ras/common/socket/RasRefreshDTO.java @@ -0,0 +1,37 @@ +package cn.icanci.loopstack.ras.common.socket; + +import cn.icanci.loopstack.ras.common.model.Application; + +import java.io.Serializable; +import java.util.List; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/19 17:10 + */ +public class RasRefreshDTO implements Serializable { + /** + * 服务Application,只会一个Application + */ + private Application serverApplication; + /** + * 客户端Application + */ + private List clientApplications; + + public Application getServerApplication() { + return serverApplication; + } + + public void setServerApplication(Application serverApplication) { + this.serverApplication = serverApplication; + } + + public List getClientApplications() { + return clientApplications; + } + + public void setClientApplications(List clientApplications) { + this.clientApplications = clientApplications; + } +} diff --git a/common/src/main/java/cn/icanci/loopstack/ras/common/socket/RegisterDTO.java b/common/src/main/java/cn/icanci/loopstack/ras/common/socket/RegisterDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..63fbf46df2a3adb52d44941cb8614952a76ed67c --- /dev/null +++ b/common/src/main/java/cn/icanci/loopstack/ras/common/socket/RegisterDTO.java @@ -0,0 +1,58 @@ +package cn.icanci.loopstack.ras.common.socket; + +import java.io.Serializable; + +/** + * @author icanci + * @since 1.0 Created in 2023/01/06 22:42 + */ +public class RegisterDTO implements Serializable { + private static final long serialVersionUID = -2030921699127783725L; + + /** + * SDK 服务ip地址 + */ + private String clientAddress; + /** + * SDK 服务端口地址 + */ + private int clientPort; + /** + * SDK 服务服务ID + */ + private String appId; + + public RegisterDTO() { + } + + public RegisterDTO(String clientAddress, int clientPort, String appId) { + this.clientAddress = clientAddress; + this.clientPort = clientPort; + this.appId = appId; + } + + public String getClientAddress() { + return clientAddress; + } + + public void setClientAddress(String clientAddress) { + this.clientAddress = clientAddress; + } + + public int getClientPort() { + return clientPort; + } + + public void setClientPort(int clientPort) { + this.clientPort = clientPort; + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + +} diff --git a/common/src/main/java/cn/icanci/loopstack/ras/common/socket/SocketMessage.java b/common/src/main/java/cn/icanci/loopstack/ras/common/socket/SocketMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..d507a73b8a56f780bf7ba791ba6aa6da0648878c --- /dev/null +++ b/common/src/main/java/cn/icanci/loopstack/ras/common/socket/SocketMessage.java @@ -0,0 +1,49 @@ +package cn.icanci.loopstack.ras.common.socket; + +/** + * @author icanci + * @since 1.0 Created in 2022/11/20 21:01 + */ +@SuppressWarnings("all") +public class SocketMessage { + private boolean success; + private String errorMessage; + private T content; + + public static SocketMessage fail(String errorMessage) { + SocketMessage message = new SocketMessage(); + message.setSuccess(false); + message.setErrorMessage(errorMessage); + return message; + } + + public static SocketMessage success() { + SocketMessage message = new SocketMessage(); + message.setSuccess(true); + return message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public T getContent() { + return content; + } + + public void setContent(T content) { + this.content = content; + } +} diff --git a/common/src/main/java/cn/icanci/loopstack/ras/common/socket/UriConstant.java b/common/src/main/java/cn/icanci/loopstack/ras/common/socket/UriConstant.java new file mode 100644 index 0000000000000000000000000000000000000000..b8b99005a3dcfd000d0f8fb222eff6d06c8527bd --- /dev/null +++ b/common/src/main/java/cn/icanci/loopstack/ras/common/socket/UriConstant.java @@ -0,0 +1,31 @@ +package cn.icanci.loopstack.ras.common.socket; + +/** + * TODO 发布的处理 + * + * @author icanci + * @since 1.0 Created in 2023/01/06 22:41 + */ +public interface UriConstant { + /** + * ToClient + */ + interface ToClient { + /** 心跳 */ + String HEARTBEAT = "/ras/register/heartbeat"; + /** 刷新 */ + String REFRESH = "/ras/register/refresh"; + } + + /** + * ToServer + */ + interface ToServer { + /** 注册 */ + String REGISTER = "/ras/register/doRegister"; + /** 加载客户端和注册中心的信息 */ + String LOAD = "/ras/register/load"; + /** 刷新服务的状态信息:上线、下线等 */ + String TO_REFRESH_DELETE_STATUS = "/ras/register/refreshDeleteStatus"; + } +} diff --git a/pom.xml b/pom.xml index dba608abec6ece12bdb78f393ec74a90eb24ceae..28b8ac126abd2de2b1f54160baf5cdab8d843485 100644 --- a/pom.xml +++ b/pom.xml @@ -6,11 +6,428 @@ cn.icanci.loopstack.ras ras-parent + pom 1.0-SNAPSHOT + + client + common + admin + server + + + UTF-8 + + 3.8.1 + 3.0.0-M1 + 3.2.1 + 3.2.0 + 1.6.8 + 1.6 + 3.0.0-M1 + + 1.8 + UTF-8 8 8 + + 4.13.2 + + 1.7.30 + 2.12.1 + 2.13.3 + 2.13.3 + 3.3.4 + + 2.2.2.RELEASE + 2.2.2 + + 3.4 + 2.4 + 4.3 + 19.0 + + 2.11.2 + 1.2.70 + + 1.4.2.Final + 5.4.2 + + 4.1.63.Final + + 0.0.0.1-SNAPSHOT + + + + + org.springframework.boot + spring-boot-dependencies + + + org.springframework.boot + spring-boot-starter-logging + + + ${spring.boot.version} + import + pom + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${spring.boot.mybatis.version.version} + + + + org.apache.commons + commons-lang3 + ${commons.lang3.version} + + + commons-io + commons-io + ${commons.io.version} + + + org.apache.commons + commons-collections4 + ${commons.collections4.version} + + + com.google.guava + guava + ${guava.version} + + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + com.alibaba + fastjson + ${fastjson.version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + junit + junit + ${junit.version} + test + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + + org.apache.logging.log4j + log4j-slf4j-impl + ${log4j-slf4j-impl.version} + + + + org.apache.logging.log4j + log4j-api + ${log4j-api.version} + + + + org.apache.logging.log4j + log4j-core + ${log4j-core.version} + + + + com.lmax + disruptor + ${disruptor.version} + + + + org.mapstruct + mapstruct + ${mapstruct.version} + + + + cn.hutool + hutool-all + ${hutool.version} + + + io.netty + netty-all + ${netty-all.version} + + + + cn.icanci.loopstack + lsi-api + ${lsi.version} + + + cn.icanci.loopstack + lsi-common + ${lsi.version} + + + cn.icanci.loopstack + lsi-utils + ${lsi.version} + + + + + + + + org.slf4j + slf4j-api + + + + org.apache.logging.log4j + log4j-slf4j-impl + + + + org.apache.logging.log4j + log4j-api + + + + org.apache.logging.log4j + log4j-core + + + + com.lmax + disruptor + + + org.springframework.boot + spring-boot-starter-log4j2 + + + junit + junit + test + + + com.fasterxml.jackson.core + jackson-core + + + com.alibaba + fastjson + + + com.fasterxml.jackson.core + jackson-annotations + + + com.fasterxml.jackson.core + jackson-databind + + + cn.hutool + hutool-all + + + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + + icanci + icanci@foxmail.com + https://gitee.com/icanci + +8 + + + + + + ${project.artifactId}-${project.version} + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + attach-sources + verify + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven-deploy-plugin.version} + + ${javadoc.opts} + + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.target} + ${maven.compiler.source} + ${project.build.sourceEncoding} + + + + + org.apache.maven.plugins + maven-source-plugin + + + package + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + package + + jar + + + + + + + + + + + disable-javadoc-doclint + + [1.8,) + + + -Xdoclint:none + + + + release + + + + + org.apache.maven.plugins + maven-source-plugin + + + package + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + package + + jar + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + verify + + sign + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + ${nexus-staging-maven-plugin.version} + true + + oss-release + https://s01.oss.sonatype.org/ + true + + + + + + + sonatype-snapshots + https://s01.oss.sonatype.org/content/repositories/snapshots + + + sonatype-release + https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + + + sonatype-snapshots + https://s01.oss.sonatype.org/content/repositories/snapshots + + + sonatype-release + https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ + + \ No newline at end of file diff --git a/server/pom.xml b/server/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..22784812caf7afe5ffda2fd174971087eed658e3 --- /dev/null +++ b/server/pom.xml @@ -0,0 +1,73 @@ + + + + ras-parent + cn.icanci.loopstack.ras + 1.0-SNAPSHOT + + 4.0.0 + + ras-server + + + 8 + 8 + + + + cn.icanci.loopstack.ras + ras-common + ${parent.version} + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-autoconfigure + + + org.springframework.boot + spring-boot-configuration-processor + compile + true + + + org.apache.commons + commons-lang3 + + + org.apache.commons + commons-collections4 + + + com.google.guava + guava + + + io.netty + netty-all + + + cn.icanci.loopstack + lsi-api + + + cn.icanci.loopstack + lsi-common + + + cn.icanci.loopstack + lsi-utils + + + \ No newline at end of file diff --git a/server/src/main/java/cn/icanci/loopstack/ras/server/package-info.java b/server/src/main/java/cn/icanci/loopstack/ras/server/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..87a177b001b3b2fb53a376b68a89b92c2f1bd385 --- /dev/null +++ b/server/src/main/java/cn/icanci/loopstack/ras/server/package-info.java @@ -0,0 +1,5 @@ +/** + * @author icanci + * @since 1.0 Created in 2023/01/19 17:22 + */ +package cn.icanci.loopstack.ras.server; \ No newline at end of file