介绍

一个散布式微服务RPC结构 | 英文阐明文档 | SpringBoot整合RPC

  • 根据SocketNetty异步非堵塞通信的处理方案;
  • 支撑散布式超时重试机制、幂等前史成果筛选战略、异步缓存完成高效通信;
  • 完成选用Jedis/Lettuce两种根据雪花算法的id生成器;
  • 支撑JDK内置SPI机制,完成接口与完成解耦;
  • 注册中心高可用性,供给集群注册中心,一切注册节点宕机后仍能经过缓存为用户持续供给服务;
  • 供给个性化服务,推出个性化服务name、服务group,适合在测验、实验和正式环境的服务,以及为后期版别的兼容、保护和升级供给更好的服务;
  • 供给集群注册中心宕机重启服务;
  • 供给服务无限制横向扩展;
  • 供给服务的两种负载均衡战略,如随机和轮询负载;
  • 供给恳求超时重试,且确保事务履行的幂等性,超时重试能降低线程池使命的推迟,线程池确保了高并发场景下线程数创立数量的安稳,却因而带来推迟问题,处理该问题能够启用重试恳求,且重试到达阈值将放弃恳求,认为该服务暂时不可用,造成事务损耗,请慎用;
  • 供给自定义注解扩展服务,运用署理扩展,能无侵入式扩展个性化服务;
  • 供给可扩展的序列化服务,目前供给KryoJackson两种序列化办法;
  • 供给日志结构Logback
  • 供给Netty可扩展的通信协议,通信协议头运用与Class相同的16位魔数0xCAFEBABE、包辨识id,用来辨识恳求包和呼应包、res长度,用来防止粘包,以及最终的res,内部参加检验码和仅有识别id,让服务器能高效地一起处理多个不同恳求包或重发恳求包,以及包校验;
  • 支撑秒级时钟回拨服务端采纳主动屏蔽客户端恳求战略、分级以上时钟回拨服务端采纳主动下线战略

架构图

  • 重试机制架构图

基于Netty高性能RPC框架(分布式缓存、幂等性、雪花算法)

  • 服务发现与注册架构图

基于Netty高性能RPC框架(分布式缓存、幂等性、雪花算法)

1. 服务供给

  • 负载均衡战略
  • 序列化战略
  • 主动发现和注销服务
  • 注册中心
  • 单机与集群

2. 安全战略

  • 心跳机制
  • 信息摘要
  • 超时重试机制
  • 幂等性
  • 雪花算法

3. 规划形式

  • 单例形式
  • 动态署理
  • 静态工厂
  • 建造者
  • 战略形式
  • Future(观察者)

亮点

1. 信息摘要算法的运用

对于信息摘要算法的运用,其实并不难,在数据包中添加 String 类型的成员变量 checkCode 用来防伪的就能够完成。

  • 原理

发送端把原信息用HASH函数加密成摘要,然后把数字摘要和原信息一起发送到接收端,接收端也用HASH函数把原消息加密为摘要,看两个摘要是否相同,若相同,则表明信息的完好.不然不完好。

  • 完成

客户端在宣布 恳求包,服务端会在该恳求包在恳求履行的成果的内容转成字节码后,运用 MD5 单向加密成为 仅有的信息摘要(128 比特,16 字节)存储到呼应包对应的成员变量 checkCode 中,所以客户端拿到呼应包后,最有运用价值的地方(恳求要履行的成果被改动),那么 checkCode 将不能确保共同性,这便是信息摘要的原理运用。

安全性再增强

考虑到这只是针对客户需求的成果回来共同性,并不能确保恳求包之间存在相同的恳求内容,所以引进了恳求 id

每个包都会生成仅有的 requestId,宣布恳求包后,该包只能由该恳求宣布的客户端所承受,就算两处有一点被对方歹意改动了,客户端都会报错并丢掉收到的呼应包,不会拆包后去回来给用户。

假如不是单单改动了回来成果,而是将成果跟信息摘要都修正了,对方很难确保修正的内容加密后与修正后的信息摘要共同,因为要确保共同的数据传输协议和数据编解码。

2. 心跳机制

心跳机制的 RPC 上运用的很广泛,本项目对心跳机制的完成很简略,并且应对办法是服务端强制断开衔接,当然有些 RPC 结构完成了服务端去主动测验重连。

  • 原理

对于心跳机制的运用,其实是运用了 Netty 结构中的一个 handler 处理器,经过该 处理器,去守时发送心跳包,让服务端知道该客户端坚持活性状况。

  • 完成

运用了 Netty 结构中的 IdleStateEvent 事情监听器,重写userEventTriggered() 办法,在服务端监听读操作,读取客户端的 写操作,在客户端监听写操作,监听本身是否还在活动,即有没有向服务端发送恳求。

假如客户端没有主动断开与服务端的衔接,而持续坚持衔接着,那么客户端的写操作超时后,也便是客户端的监听器监听到客户端没有的规守时刻内做出写操作事情,那么这时客户端该处理器主动发送心跳包给服务端,确保客户端让服务端确保自己坚持着活性。

3. SPI 机制

资源目录META-INF/services下新建接口全限定名作为文件名,内容为完成类全限定名,支撑JDK内置SPI

实质经过反射来无参结构创立实例,假如结构函数涉及到经过参数来完成注入成员,那么可将接口转为抽象类,抽象类露出set办法来让子类重写,然后间接完成注入。

该机制将注册中心逻辑层处理服务发现和注册的接口时完成分离到装备文件META-INF/services,然后更好地去支撑其他插件,如ZookeeperEureka的扩展。

运用到的装备文件:

  • cn.fyupeng.discovery.ServiceDiscovery
cn.fyupeng.discovery.NacosServiceDiscovery
  • cn.fyupeng.provider.ServiceProvider
cn.fyupeng.provider.DefaultServiceProvider
  • cn.fyupeng.registry.ServiceRegistry
cn.fyupeng.registry.NacosServiceRegistry

4. IO 异步非堵塞

IO 异步非堵塞 能够让客户端在恳求数据时处于堵塞状况,并且能够在恳求数据回来时刻段里去处理自己感兴趣的事情。

  • 原理

运用 java8 出世的 CompletableFuture 并发工具类,能够异步处理数据,并在将来需求时获取。

  • 完成

数据在服务端与客户端之间的通道 channel 中传输,客户端向通道宣布恳求包,需求等候服务端回来,这时可运用 CompletableFuture 作为回来成果,只需让客户端读取到数据后,将成果经过 complete()办法将值放进去后,在将来时经过get()办法获取成果。

5. RNF 协议

/**
     * 自定义目标头 协议 16 字节
     * 4 字节 魔数
     * 4 字节 协议包类型
     * 4 字节 序列化类型
     * 4 字节 数据长度
     *
     *       The transmission protocol is as follows :
     * +---------------+---------------+-----------------+-------------+
     * | Magic Number  | Package Type  | Serializer Type | Data Length |
     * | 4 bytes       | 4 bytes       | 4 bytes         | 4 bytes     |
     * +---------------+---------------+-----------------+-------------+
     * |                           Data Bytes                          |
     * |                       Length: ${Data Length}                  |
     * +---------------+---------------+-----------------+-------------+
     */

快速开端

1.依靠

1.1 直接引进

首要引进两个jar包文件rpc-core-1.0.0.jarrpc-core-1.0.0-jar-with-dependencies.jar

jar包中包括字节码文件和java源码,引进后会主动把classsources同时引进,源码可作为参考

基于Netty高性能RPC框架(分布式缓存、幂等性、雪花算法)

1.2 maven引进

引进以下maven,会同时引进rpc-common与默许运用的注册中心nacos-client相关依靠

<dependency>
    <groupId>cn.fyupeng</groupId>
    <artifactId>rpc-core</artifactId>
    <version>2.0.4</version>
</dependency>

最新版别2.1.0还处于测验阶段,引进雪花算法、散布式缓存处理2.0.0版别超时仅单机可用而散布式失效问题。

<dependency>
  <groupId>cn.fyupeng</groupId
  <artifactId>rpc-core</artifactId>
  <version>2.1.0</version>
</dependency>

阿里库房10月份开端处于系统升级,有些版别还没同步过去,引荐另一个maven官方库房:

<mirror>
  <id>repo1maven</id>
  <mirrorOf>*</mirrorOf>
  <name>maven公共库房</name>
  <url>https://repo1.maven.org/maven2</url>
</mirror>

2. 发动 Nacos

-m:形式standalone:单机

命令运用:

startup -m standalone

留意:开源RPC 默许运用 nacos 指定的本地端口号 8848

官方文档:nacos.io/zh-cn/docs/…

优势:

选用Nacos作为注册中心,是因为有较高的可用性,可完成服务长时刻牢靠

  • 注册中心服务列表在本地保存一份
  • 宕机节点在主动重启康复期间,服务仍旧可用

Nacos 发动效果:

基于Netty高性能RPC框架(分布式缓存、幂等性、雪花算法)

3. 供给接口

public interface HelloService {
    String sayHello(String message);
}

4. 发动服务

  • 实在服务
@Service
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String message) {
        return "hello, here is service!";
    }
}
  • 服务发动器
@ServiceScan
public class MyServer {
    public static void main(String[] args) {
        try {
            NettyServer nettyServer = new NettyServer("127.0.0.1", 5000, SerializerCode.KRYO.getCode());
            nettyServer.start();
        } catch (RpcException e) {
            e.printStackTrace();
        }
    }
}

留意:添加注解cn.fyupeng.Servicecn.fyupeng.ServiceScan才可被主动发现服务扫描并注册到 nacos

5. 发动客户端

初始化客户端时衔接服务端有两种办法:

  • 直连
  • 运用负载均衡
public class MyClient {
    public static void main(String[] args) {
        RoundRobinLoadBalancer roundRobinLoadBalancer = new RoundRobinLoadBalancer();
        NettyClient nettyClient = new NettyClient(roundRobinLoadBalancer, CommonSerializer.KRYO_SERIALIZER);
        RpcClientProxy rpcClientProxy = new RpcClientProxy(nettyClient);
        HelloService helloService = rpcClientProxy.getProxy(HelloService.class);
        String result = helloService.sayHello("hello");
        System.out.println(result);
    }
}

5. 额外装备

5.1 装备文件

  • 项目办法发动

在 resources 中参加 resource.properties

主机名运用localhost127.0.0.1指定

cn.fyupeng.nacos.register-addr=localhost:8848
  • Jar办法发动

,兼容springboot的外部发动装备文件注入,需求在Jar包同目录下新建config文件夹,在config中与springboot相同注入装备文件,只不过springboot注入的装备文件默许束缚名为application.properties,而rpc-netty-framework默许束缚名为resource.properties

5.2 日志装备

resources 中参加 logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <!--%date{HH:mm:ss.SSS} %c -->
      <pattern>%date{HH:mm:ss.SSS} [%level] %c [%t] - %m%n</pattern>
    </encoder>
  </appender>
  <root level="info">
    <appender-ref ref="console"/>
  </root>
</configuration>

除此之外,结构还供给了 Socket 办法的 Rpc 服务

6. 场景运用

  • 支撑 springBoot 集成

为了支撑springBoot集成logback日志,继承rpc-netty-framework运用同一套日志,扔掉nacos-client内置的slf4j-apicommons-loging原有Jar包,因为该结构会导致在整合springboot时,呈现重复的日志绑定和日志打印办法的参数兼容问题,运用jcl-over-slf4j-api可处理该问题;

springboot1.02.0版别中,不运用它默许版别的spring-boot-starter-log4j,引荐运用1.3.8.RELEASE; springboot简略装备如下

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <exclusions>
            <!-- 扫除 springboot 默许的 logback 日志结构 -->
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
            <!-- 扫除 springboot 默许的 commons-logging 完成(版别低,呈现办法找不到问题) -->
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jcl</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!-- 与 logback 整合(经过 @Slf4j 注解即可运用) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.10</version>
    </dependency>
    <!--引进log4j日志依靠,目的是运用 jcl-over-slf4j 来重写 commons logging 的完成-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j</artifactId>
    <version>1.3.8.RELEASE</version>
    </dependency>
</dependencies>

7. 高可用集群

cn.fyupeng.nacos.cluster.use=true
cn.fyupeng.nacos.cluster.load-balancer=random
cn.fyupeng.nacos.cluster.nodes=192.168.10.1:8847,192.168.10.1:8848,192.168.10.1:8849
  • 运用办法及留意要点

默许状况下,cn.fyupeng.nacos.cluster.use服从约定优于装备设定,且默许值为false,表明默许不翻开集群;

cn.fyupeng.nacos.cluster.load-balancercn.fyupeng.nacos.cluster.nodes运用前有必要先翻开集群形式

  • 集群节点负载战略
    • random:随机战略
    • round:轮询战略

集群节点理论上答应无限扩展,可运用分隔符[;,|]扩展装备

  • 集群节点容错切换
    • 节点宕机:遇到节点宕机将从头从节点装备列表中选举新的正常节点,不然无限重试

8. 超时重试机制

默许不运用重试机制,为了确保服务的正确性,因为无法确保幂等性。

原因是客户端无法勘探是客户端网络传输进程呈现问题,或许是服务端正确接收后回来途中网络传输呈现问题,因为假如是前者那么重试后能确保幂等性,假如为后者,或许将导致屡次同个事务的履行,这对客户端来说成果对错共同的。

超时重试处理睬导致呈现幂等性问题,因此在服务器中运用HashSet添加恳求id来做超时处理

  • 超时重试:cn.fyupeng.anotion.Reference注解供给重试次数、超时时刻和异步时刻三个装备参数,其中:
    • 重试次数:服务端未能在超时时刻内 呼应,答应触发超时的次数
    • 超时时刻:即客户端最长答应等候 服务端时长,超时即触发重试机制
    • 异步时刻:即等候服务端异步呼应的时刻,且只能在超时重试机制运用,非超时重试状况下默许运用堵塞等候办法

示例:

private static RandomLoadBalancer randomLoadBalancer = new RandomLoadBalancer();
    private static NettyClient nettyClient = new NettyClient(randomLoadBalancer, CommonSerializer.KRYO_SERIALIZER);
    private static RpcClientProxy rpcClientProxy = new RpcClientProxy(nettyClient);
    @Reference(retries = 2, timeout = 3000, asyncTime = 5000)
    private static HelloWorldService service = rpcClientProxy.getProxy(HelloWorldService.class, Client.class);

重试的完成也不难,选用署理 + for + 参数来完成即可。

中心代码完成:

for (int i = 0; i <= retries; i++) {
    long startTime = System.currentTimeMillis();
    CompletableFuture<RpcResponse> completableFuture = (CompletableFuture<RpcResponse>) rpcClient.sendRequest(rpcRequest);
    try {
        rpcResponse = completableFuture.get(asyncTime, TimeUnit.MILLISECONDS);
    } catch (TimeoutException e) {
        // 忽视 超时引发的反常,自行处理,防止程序中止
        timeoutRes.incrementAndGet();
        if (timeout >= asyncTime) {
            log.warn("asyncTime [ {} ] should be greater than timeout [ {} ]", asyncTime, timeout);
        }
        continue;
    }
    long endTime = System.currentTimeMillis();
    long handleTime = endTime - startTime;
    if (handleTime >= timeout) {
        // 超时重试
        log.warn("invoke service timeout and retry to invoke");
    } else {
        // 没有超时不用再重试
        // 进一步校验包
        if (RpcMessageChecker.check(rpcRequest, rpcResponse)) {
            res.incrementAndGet();
            return rpcResponse.getData();
        }
    }
}
  • 幂等性

重试机制服务端要确保重试包的一次履行准则,即要完成幂等性。

完成思路:凭借散布式缓存对首次恳求包进行异步缓存恳求id,散布式缓存选型Redis,客户端选型Jedis与Lettuce,给定一个key失效时刻满意重试机制,减少再次清理缓存的过程。

幂等性效果在失效时刻,也影响到超时机制重试次数以及高并发场景,有雪花算法的优势,不一起间上不会生成重复id,所以能够大胆将失效时刻设置大些,这取决于你能够承当多少内存而转而去考虑内存瓶颈的问题。

9. 雪花算法

/**
     * 自定义 散布式仅有号 id
     *  1 位 符号位
     * 41 位 时刻戳
     * 10 位 作业机器 id
     * 12 位 并发序列号
     *
     *       The distribute unique id is as follows :
     * +---------------++---------------+---------------+-----------------+
     * |     Sign      |     epoch     |    workerId   |     sequence     |
     * |    1 bits     |    41 bits    |    10 bits   |      12 bits      |
     * +---------------++---------------+---------------+-----------------+
     */
  • 介绍

雪花算法:主要由时刻戳、机器码、序列码这三者组成,各个部分有代表的含义。

标志位

表明符号位,固定值为0,表明正数。

时刻戳

时刻戳代表运转时长,它由41比特组成,最高可运用69年,由当时系统时刻戳与服务发动当天清晨时刻戳的差值表明。

机器码

机器码代表散布式节点,它由10比特组成,最高可表明1024个机器码,默许选用当时服务主机号hashCode、高低位异或和散布式缓存算法生成,机器码生成反常时由SecureRandom运用随机种子、AtomicLongCAS锁生成,当机器码数量最大时将抛出反常WorkerIdCantApplyException

序列号

序列号代码并发量,在同一毫秒内产生效果,即毫秒并发时作为一部分仅有值,它由12比特组成,最高可表明4096个序列号。

  • 运用场景

(1)多服务节点负载完成事务持久化主键仅有

(2)毫秒内恳求并发数最高可到达4095,可适当改动序列号满意不同场景

(3)满意根本有序的仅有号id,有利于高效索引查询和保护

(4)id号前6位附加当时时刻年月日日志查询,可作为日志记载

而在RPC中主要选用雪花算法完成了恳求包的仅有识别号,因为UUID生成仅有性和时刻持续性比雪花算法更好,但它id值对错递加序列,在索引建立和保护时价值更高。

雪花算法生成的id根本有序递加,可作为索引值,并且保护成本低,价值是强依靠机器时钟,为了尽或许发挥它的优势和减少缺乏,对最近的时刻内保存了时刻戳与序列号,回拨即获取当时序列号,有则自增,无则堵塞康复到时钟回拨前的时刻戳,回拨时刻过大抛反常中止,并且服务器重启时小概率或许呈现回拨会然后导致id值重复的问题。

cn.fyupeng.redis.server-addr=127.0.0.1:6379
cn.fyupeng.redis.server-auth=true
cn.fyupeng.redis.server-pwd=123456

除此以外,超时重试机制,在散布式场景下,第二次重试会经过负载均衡战略负载到其他服务节点,运用雪花算法弥补了散布式场景下的无法处理幂等性的问题。

超时重试选用Jedis/Lettuce两种完成缓存的办法,可分别在服务端、客户端装备相应的缓存衔接客户端办法:

cn.fyupeng.redis.server-way=lettuce
cn.fyupeng.redis.client-way=jedis
cn.fyupeng.redis.server-async=true

怎么选择JRedisHelperLRedisHelper呢?

JRedisHelper

  • 线程安全
  • synchronizedlock的悲观锁机制
  • 不供给线程池
  • 衔接数为1
  • 同步操作
  • 供给根据主机号缓存和获取机器id
  • 供给根据恳求id缓存和获取恳求成果

LRedisHelper

  • 线程安全
  • 供给线程池
  • 衔接数安稳且由线程池供给
  • 异步/同步操作
  • 供给根据主机号缓存和获取机器id
  • 供给根据恳求id缓存和获取恳求成果

特别提示

高并发恳求不会呈现恳求号重复的状况,当时最高毫秒级并发4096,而超时机制、LRedisHelper线程池对衔接的超时控制等装备参数还不成熟,具体运用场景可自行下载源码修正参数。

10. 反常处理

  • ServiceNotFoundException

抛出反常ServiceNotFoundException

堆栈信息:service instances size is zero, can't provide service! please start server first!

正常状况下,一般的过错从报错中能够引导处理。

处理实在服务不存在的状况,导致负载均衡中运用的战略呈现反常的状况,修正后会强制抛出ServiceNotFoundException,或许大部分状况是服务未发动。

当然,引荐实在服务应该在服务发动器的内层包中,同层或许会不起效果。

除非运用注解注明包名@ServiceScan("com.fyupeng")

其他状况下,如呈现服务端无反响,并且服务现已成功注册到注册中心,那么你就得查看下服务端与客户端中接口命名的包名是否共同,如不共同,也是无法被主动发现服务从注册中心发现的,这样最常见的报错也是service instances size is zero

  • ReceiveResponseException

抛出反常data in package is modified Exception

信息摘要算法的完成,运用的是String类型的equals办法,所以客户端在编写Service接口时,假如回来类型不是八大根本类型 + String 类型,也便是杂乱目标类型,那么要重写toString办法。

不运用Object默许的toString办法,因为它默许打印信息为16位的内存地址,在做校验中,发送的包和恳求获取的包是需求从头实例化的,说白了便是深克隆,有必要 重写Object原有toString办法。

为了避免该状况产生,主张一切PoJoVO类有必要重写toString办法,其实便是一切实在事务办法回来类型的实体,有必要重写toString办法。

如回来体有嵌套杂乱目标,一切杂乱目标均要重写toString只需满意不同目标但内容相同的toString办法打印信息共同,数据完好性检测才不会误报。

  • RegisterFailedException

抛出反常Failed to register service Exception

原因是注册中心没有发动或许注册中心地址端口指定不明,或许因为防火墙问题,导致Nacos地点服务器的端口访问失利。

运用该结构时,需留意以下两点:

(1) 支撑注册本地地址,如 localhost或127.0.0.1,则注册地址会解析成公网地址;

(2) 支撑注册内网地址和外网地址,则地址为对应内网地址或外网地址,不会将其解析;

  • NotSuchMethodException 抛出反常java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log

呈现该反常的原因依靠包依靠了jcl-over-slf4jjar包,与springboot-starter-log4j中供给的jcl-over-slf4j重复了,主张手动删除rpc-core-1.0.0-jar-with-dependenceies.jarorg.apache.commons

  • DecoderException

抛出反常:com.esotericsoftware.kryo.KryoException: Class cannot be created (missing no-arg constructor): java.lang.StackTraceElement

主要是因为Kryo序列化和反序列化是经过无参结构反射创立的,所以运用到Pojo类,首要有必要对其创立无参结构函数,不然将抛出该反常,并且无法正常履行。

  • InvocationTargetException

抛出反常:Serialization trace:stackTrace (java.lang.reflect.InvocationTargetException)

主要也是反射调用失利,主要原因还是反射履行目标函数失利,缺少相关函数,或许是结构函数或许其他办法参数问题。

  • AnnotationMissingException

抛出反常:cn.fyupeng.exception.AnnotationMissingException

由打印信息中可知,追踪AbstractRpcServer类信息打印

cn.fyupeng.net.AbstractRpcServer [main] - mainClassName: jdk.internal.reflect.DirectMethodHandleAccessor

假如mainClassName不为@ServiceScan注解符号地点类名,则需求到包cn.fyupeng.util.ReflectUtil下修正或重写getStackTrace办法,将没有过滤的包名加进过滤列表即可,这或许与JDK的版别有关。

  • OutOfMemoryError

抛出反常java.lang.OutOfMemoryError: Requested array size exceeds VM limit

根本不或许会抛出该过错,因为考虑到并发恳求,或许导致,假如恳求包分包,会呈现许多问题,所以每次恳求只发送一个恳求包,如在运用场景需求发送大数据,比如发表文章等等,需求手动去重写运用的序列化类的serialize办法

例如:KryoSerializer能够重写serialize办法中写缓存的巨细,默许为4096,超出该巨细会很容易报数组越界反常问题。

/**
 * bufferSize: 缓存巨细
 */
Output output = new Output(byteArrayOutputStream,100000))
  • RetryTimeoutExcepton

抛出反常cn.fyupeng.exception.AnnotationMissingException

在启用重试机制后,客户端超越重试次数仍未能成功调用服务,即可认为服务不可用,并抛出超时重试反常。

抛出该反常后,将中止该线程,其线程还未履行的使命将停止,默许不会敞开重试机制,则不会抛出该反常。

  • InvalidSystemClockException

抛出反常cn.fyupeng.idworker.exception.InvalidSystemClockException

雪花算法生成中是有很小概率呈现时钟回拨,时刻回拨需求处理id值重复的问题,故而有或许抛出InvalidSystemClockException中止反常,逻辑不可处理反常。

  • WorkerIdCantApplyException

抛出反常cn.fyupeng.idworker.exception.WorkerIdCantApplyException

雪花算法生成中,凭借IdWorker生成器生成散布式仅有id时,是凭借了机器码,当机器码数量生成到达最大值将不可再请求,这时将抛出中止反常WorkerIdCantApplyException

11. 版别追踪

1.0版别

  • [ #1.0.1 ]:处理实在散布式场景下呈现的注册服务找不到的逻辑问题;

  • [ #1.0.2 ]:解耦注册中心的地址绑定,可到发动器地点工程项目的资源下装备resource.properties文件;

  • [ #1.0.4.RELEASE ]:修正Jar办法部署项目后注册到注册中心的服务未能被发现的问题,解耦Jar包发动装备文件的注入,束缚名相同会覆盖项目原有装备信息;

  • [ #1.0.5 ]:将心跳机制打印装备默许级别为trace,默许日志级别为info,需求敞开到logback.xml启用。

  • [ #1.0.6 ]:默许恳求包巨细为4096字节,扩容为100000字节,满意日常的100000字的数据包,不引荐发送大数据包,如有需求看反常OutOfMemoryError阐明。

  • [ #1.0.10 ]: 修正负载均衡呈现select失利问题,供给装备中心高可用集群节点注入装备、负载均衡装备、容错主动切换

2.0版别

  • [ #2.0.0 ]:优化1.0版别,2.0版别问世超时重试机制,运用到幂等性来处理事务丢失问题,进步事务牢靠性。

  • [ #2.0.1 ]:版别保护

  • [ #2.0.2 ]:修正集群装备中心宕机重试和负载问题

  • [ #2.0.3 ]:供给个性化服务版别号,支撑各种场景,如测验和正式场景,让服务具有更好的兼容性,支撑版别保护和升级。

  • [ #2.0.4 ]:支撑SPI机制,接口与完成解耦。

  • [ #2.1.0 ]:引进雪花算法与散布式缓存,2.0.0版别仅支撑单机幂等性,修正散布式场景失效问题,选用轮询负载+超时机制,能高效处理服务超时问题。

  • [ #2.1.1 ]:更改装备信息cn.fyupeng.client-asynccn.fyupeng.server-async

12. 开发阐明

有二次开发能力的,可直接对源码修正,最终在工程目录下运用命令mvn clean package,可将中心包和依靠包打包到rpc-netty-framework\rpc-core\target目录下,本项目为开源项目,如认为对本项目开发者采纳,请在开源后最终追加原创作者GitHub链接 github.com/fyupeng ,感谢配合!