放心,Leaf中已经对这种情况做了优化,不会等到ID消耗完了才去重新申请,会在还没用完之前就去申请下一个范围段。并发量大的问题你可以直接将step调大即可。
问题二这个时候又有人说了,如果Leaf服务挂掉某个节点会不会有影响呢?
首先Leaf服务是集群部署,一般都会注册到注册中心让其他服务发现。挂掉一个没关系,还有其他的N个服务。问题是对ID的获取有问题吗? 会不会出现重复的ID呢?
答案是没问题的,如果Leaf1挂了的话,它的范围是11000,假如它当前正获取到了100这个阶段,然后服务挂了。服务重启后,就会去申请下一个范围段了,不会再使用11000。所以不会有重复ID出现。
Leaf改造支持RPC如果你们的调用量很大,为了追求更高的性能,可以自己扩展一下,将Leaf改造成Rpc协议暴露出去。
首先将Leaf的Spring版本升级到5.1.8.RELEASE,修改父pom.xml即可。
<spring.version>5.1.8.RELEASE</spring.version>然后将Spring Boot的版本升级到2.1.6.RELEASE,修改leaf-server的pom.xml。
<spring-boot-dependencies.version>2.1.6.RELEASE</spring-boot-dependencies.version>还需要在leaf-server的pom中增加nacos相关的依赖,因为我们kitty-cloud是用的nacos。同时还需要依赖dubbo,才可以暴露rpc服务。
<dependency> <groupId>com.cxytiandi</groupId> <artifactId>kitty-spring-cloud-starter-nacos</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.cxytiandi</groupId> <artifactId>kitty-spring-cloud-starter-dubbo</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> </dependency>在resource下创建bootstrap.properties文件,增加nacos相关的配置信息。
spring.application.name=LeafSnowflake dubbo.scan.base-packages=com.sankuai.inf.leaf.server.controller dubbo.protocol.name=dubbo dubbo.protocol.port=20086 dubbo.registry.address=spring-cloud://localhost spring.cloud.nacos.discovery.server-addr=47.105.66.210:8848 spring.cloud.nacos.config.server-addr=${spring.cloud.nacos.discovery.server-addr}Leaf默认暴露的Rest服务是LeafController中,现在的需求是既要暴露Rest又要暴露RPC服务,所以我们抽出两个接口。一个是Segment模式,一个是Snowflake模式。
Segment模式调用客户端
/** * 分布式ID服务客户端-Segment模式 * * @作者 尹吉欢 * @个人微信 jihuan900 * @微信公众号 猿天地 * @GitHub https://github.com/yinjihuan * @作者介绍 * @时间 2020-04-06 16:20 */ @FeignClient("${kitty.id.segment.name:LeafSegment}") public interface DistributedIdLeafSegmentRemoteService { @RequestMapping(value = "/api/segment/get/{key}") String getSegmentId(@PathVariable("key") String key); }Snowflake模式调用客户端
/** * 分布式ID服务客户端-Snowflake模式 * * @作者 尹吉欢 * @个人微信 jihuan900 * @微信公众号 猿天地 * @GitHub https://github.com/yinjihuan * @作者介绍 * @时间 2020-04-06 16:20 */ @FeignClient("${kitty.id.snowflake.name:LeafSnowflake}") public interface DistributedIdLeafSnowflakeRemoteService { @RequestMapping(value = "/api/snowflake/get/{key}") String getSnowflakeId(@PathVariable("key") String key); }使用方可以根据使用场景来决定用RPC还是Http进行调用,如果用RPC就@Reference注入Client,如果要用Http就用@Autowired注入Client。
最后改造LeafController同时暴露两种协议即可。
@Service(version = "1.0.0", group = "default") @RestController public class LeafController implements DistributedIdLeafSnowflakeRemoteService, DistributedIdLeafSegmentRemoteService { private Logger logger = LoggerFactory.getLogger(LeafController.class); @Autowired private SegmentService segmentService; @Autowired private SnowflakeService snowflakeService; @Override public String getSegmentId(@PathVariable("key") String key) { return get(key, segmentService.getId(key)); } @Override public String getSnowflakeId(@PathVariable("key") String key) { return get(key, snowflakeService.getId(key)); } private String get(@PathVariable("key") String key, Result id) { Result result; if (key == null || key.isEmpty()) { throw new NoKeyException(); } result = id; if (result.getStatus().equals(Status.EXCEPTION)) { throw new LeafServerException(result.toString()); } return String.valueOf(result.getId()); } }扩展后的源码参考:https://github.com/yinjihuan/Leaf/tree/rpc_support
感兴趣的Star下呗:https://github.com/yinjihuan/kitty
关于作者:尹吉欢,简单的技术爱好者,《Spring Cloud微服务-全栈技术与案例解析》, 《Spring Cloud微服务 入门 实战与进阶》作者, 公众号 猿天地 发起人。个人微信 jihuan900,欢迎勾搭。