SpringBoot 不单独部署注册中心,如何实现注册中心功能?

科技   2024-11-19 07:25   浙江  
👇推荐大家关注一个公众号👇
点击上方 "编程技术圈"关注, 星标或置顶一起成长
后台回复“大礼包”有惊喜礼包!

日英文

What is adhere to? Is day, and one day, you tell yourself, insist again one day.

什么是坚持?就是一天,又一天,你告诉自己,再坚持一天。

每日掏心话

不要沉迷过去,不要害怕未来,过去。得失也好,成败也罢,无论快乐,还是痛苦,都过去了,你只能回忆,而无法回去。

责编:乐乐 | 来源Java知音

链接:juejin.cn/post/7385905203646742566

编程技术圈(ID:study_tech)第 3038 期推文


往日回顾:阿里二面:使用 try-catch 捕获异常会影响性能吗?很多人都答错!

     

      正文     

大家好,我是小乐

需求描述

一天,领导找到我,巴拉巴拉一顿沟通,需求很清晰,我就不细说了(因为跟本文关系不大),总结下就是

有两个服务:任务分发中心、任务执行器

分发中心负责任务拆分,然后将拆分后的任务下发给执行器,执行器执行任务

任务分发中心和任务执行器都要支持水平扩节点

我说:技术实现没什么难点,引入注册中心就行

但领导紧接着就说:考虑到客户硬件资源的局限性以及部署的复杂性,不能单独部署注册中心

当时我就懵了,心里想的是

既要马儿跑,又要马儿不吃草,咋不让我上天?

工作要紧.jpg

我接着说道:任务分发中心兼职注册中心,任务执行器能够自动注册到分发中心?

领导:对,你总结的言简意赅,就是要实现这样的效果

领导又补充道:你可以简单点实现,不用像 Nacos 那样复杂,服务支持水平扩展,能够监控任务执行器状态就行

相信大家都明白需求了,总结成一句话

拿着卖白菜的钱,要干卖白粉的事!

需求实现

主流的注册中心,像ZookeeperNacosetcd、Consul 以及 Eureka,都需要单独部署;如果能单独部署,那实现就简单了,可现在要求是不能单独部署,但又要有注册中心的基本功能

宝宝心里苦.jpg

说白了,就是要自实现一个简易版的注册中心,虽说是简易版,但基本功能还是要有吧

  1. 服务发现
    注册中心存储和管理所有可用服务的地址信息,其他服务可以通过查询注册中心发现所需的服务

  2. 服务注册
    服务提供者可以将自己的地址信息注册到注册中心,以便其他服务发现和调用

  3. 健康检查
    注册中心定期对注册的服务进行健康检查,以确保服务的可用性
    某个服务出现故障或不可用,注册中心能够将其从可用服务列表中移除,防止其他服务调用失败

  4. 支持水平拓展
    注册中心肯定要支持水平拓展来保障其高可用
    注册中心节点之间要能正常通信,节点之间的可用服务列表能够及时同步,并且要保证一致

这些基本功能实现起来简不简单?也许你们觉的简单,可我觉的并不简单
但事已至此,已无退路,只能硬着头皮上了

分发中心集成 Eureka Server

几个主流的注册中心,我对 Eureka 比较熟悉,感觉其实现还算比较简单,参考它来实现注册中心应该可行。一头扎进去看源码,一天下来收效甚微,发现并非想象中的那么简单,正当我准备放弃时,脑中闪过一个念头

任务分发中心可不可以集成 Eureka Server?

Eureka Server 是注册中心,这个我们都知道,但我们忽略了一个点,它还是一个普通 Web 服务,只是我们平时不用它来处理业务请求,仅仅是把它当做一个注册中心。从定位来讲,Eureka Server 确实只应该做注册中心该做的事,不应该关联到业务,尤其是服务多时,Eureka Server 维护压力大,更不应该关联业务
但有时候也需要特殊情况特殊处理,比如我目前的需求,注册中心维护的服务就一个 任务执行器,任务执行器的节点也不会很多,顶天 10 个,也就是 Eureka Servr 维护服务的压力会很小,同时业务处理也很简单:任务拆分,然后分发,这么分析下来,任务分发中心集成 Eureka Server 是可行的,说干就干!

干就完了.png

Eureka server 搭建不要太简单,你们肯定都会

gitee.com/youzhibing/…[1]

搭建过程就不演示了,偷懒的小伙伴可以直接用我提供的代码

此时的代码结构如下(未包含业务代码)

代码结构.png

搭建完成后启动服务,Eureka 监控如下

eureka搭建完成.png

至此,Eureka 集成完成

你们发现没,前面的 Eureka 搭建跟我们平时的 Eureka 搭建是不是没区别?

肯定没区别呀,我就是按平时的搭建流程来的,具体区别还要往下看

分发中心集成 Eureka Client

为了更好的体现 任务分发中心 集成 Eureka Client,我们简化业务实现

任务执行器 就提供一个接口给 任务分发中心 调用

任务执行器接口_exec.png

任务分发中心 也提供一个接口给其他服务(例如 调度中心)调用

分发中心接口.png

重点来了,任务分发中心如何将拆分后的任务分发到任务执行器?

细化来讲,分 3 点
1.任务分发中心能不能拿到任务执行器服务列表
2.能拿到的话,如何拿
3.拿到之后如何负载均衡的下发任务

第 1 点毋庸置疑,肯定能拿到,任务分发中心作为 Eureka Server,存储了任务执行器的服务实例列表

第 2 、3点,我们可以将 任务分发中心 又当做 Eureka Client 试试,试试有不要钱

1.引入依赖

Eureka Server 包含了Eureka Client ,不需要额外引入Eureka Client

但需要引入 open-feign

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.开启 Eureka Client 和 open-feign
@SpringBootApplication
@EnableEurekaServer
@EnableEurekaClient
@EnableFeignClients
public class TaskDispatcherApplication {

    public static void main(String[] args) {
        SpringApplication.run(TaskDispatcherApplication.classargs);
    }
}
3.实现 TaskExecutorService,完成对 任务执行器 负载均衡调用
@FeignClient("TASK-EXECUTOR")
public interface TaskExecutorService {

    @GetMapping("task/exec")
    String exec(@RequestParam("taskId") Long taskId);
}
@GetMapping("dispatch")
public String dispatch(Long jobId) {
 LOGGER.info("收到作业[jobId={}]执行请求", jobId);
 LOGGER.info("作业[jobId={}]拆分任务中...", jobId);
 List<Long> taskIds = Arrays.asList(123L666L888L999L);
 LOGGER.info("作业[jobId={}]拆分完成,得到作业列表[{}]", jobId, taskIds);
 for (Long taskId : taskIds) {
  String execResult = taskExecutorService.exec(taskId);
  LOGGER.info("任务[{}]执行结果:{}", taskId, execResult);
 }
 return "success";
}

启动 task-dispatchertask-executor ,然后调用接口

http://192.168.2.10:8080/dispatcher/job/dispatch?jobId=689

你会发现 500 了

500.png

看下日志,关键信息如下

Load balancer does not contain an instance for the service TASK-EXECUTOR

负载均衡器不包含 TASK-EXECUTOR 服务实例,这是因为我们有个配置关闭了

fetch-registry-false.png

导致 Eureka Client 未拉取其他服务,那么 Load balancer 自然就获取不到 TASK-EXECUTOR 实例了
我们将其开启(设置成 true),然后启动task-dispatchertask-executor,然后调用接口

http://192.168.2.10:8080/dispatcher/job/dispatch?jobId=689

结果 success,日志输出如下

1.  task-dispatcher
2024-06-30 10:51:51.653|INFO|http-nio-8080-exec-3|25|com.qsl.task.web.JobController          :收到作业[jobId=689]执行请求
2024-06-30 10:51:51.653|INFO|http-nio-8080-exec-3|26|com.qsl.task.web.JobController          :作业[jobId=689]拆分任务中...
2024-06-30 10:51:51.653|INFO|http-nio-8080-exec-3|28|com.qsl.task.web.JobController          :作业[jobId=689]拆分完成,得到作业列表[[123, 666, 888, 999]]
2024-06-30 10:51:51.657|INFO|http-nio-8080-exec-3|31|com.qsl.task.web.JobController          :任务[123]执行结果:success
2024-06-30 10:51:51.660|INFO|http-nio-8080-exec-3|31|com.qsl.task.web.JobController          :任务[666]执行结果:success
2024-06-30 10:51:51.663|INFO|http-nio-8080-exec-3|31|com.qsl.task.web.JobController          :任务[888]执行结果:success
2024-06-30 10:51:51.665|INFO|http-nio-8080-exec-3|31|com.qsl.task.web.JobController          :任务[999]执行结果:success
2.  task-executor
2024-06-30 10:51:51.656|INFO|http-nio-8081-exec-6|17|com.qsl.task.web.TaskController         :收到任务[taskId=123]执行请求
2024-06-30 10:51:51.656|INFO|http-nio-8081-exec-6|18|com.qsl.task.web.TaskController         :任务[taskId=123]执行中...
2024-06-30 10:51:51.656|INFO|http-nio-8081-exec-6|19|com.qsl.task.web.TaskController         :任务[taskId=123]执行完成
2024-06-30 10:51:51.659|INFO|http-nio-8081-exec-9|17|com.qsl.task.web.TaskController         :收到任务[taskId=666]执行请求
2024-06-30 10:51:51.659|INFO|http-nio-8081-exec-9|18|com.qsl.task.web.TaskController         :任务[taskId=666]执行中...
2024-06-30 10:51:51.659|INFO|http-nio-8081-exec-9|19|com.qsl.task.web.TaskController         :任务[taskId=666]执行完成
2024-06-30 10:51:51.662|INFO|http-nio-8081-exec-8|17|com.qsl.task.web.TaskController         :收到任务[taskId=888]执行请求
2024-06-30 10:51:51.662|INFO|http-nio-8081-exec-8|18|com.qsl.task.web.TaskController         :任务[taskId=888]执行中...
2024-06-30 10:51:51.662|INFO|http-nio-8081-exec-8|19|com.qsl.task.web.TaskController         :任务[taskId=888]执行完成
2024-06-30 10:51:51.664|INFO|http-nio-8081-exec-7|17|com.qsl.task.web.TaskController         :收到任务[taskId=999]执行请求
2024-06-30 10:51:51.664|INFO|http-nio-8081-exec-7|18|com.qsl.task.web.TaskController         :任务[taskId=999]执行中...
2024-06-30 10:51:51.664|INFO|http-nio-8081-exec-7|19|com.qsl.task.web.TaskController         :任务[taskId=999]执行完成

目前 task-executor 是单实例,我们再启动一个实例,来看看负载均衡效果

负载均衡.png

至此,需求是不是实现了

总结

  1. 注册中心推荐单独部署,不要掺杂业务代码
  2. Eureka Server 也可以做 Eureka Client,虽说不推荐,但有时候能止渴
  3. 要敢于尝试,不试怎么知道不行?
Reference
[1]

gitee.com/youzhibing/…: https://gitee.com/youzhibing/qsl-project/tree/master/integrate-eureka


你还有什么想要补充的吗?

上周,又劝退十几个了。。。

ChatGPT 4o 国内直接用 !!!

最后给大家推荐一个ChatGPT 4.0国内网站,是我们团队一直在使用的,我们对接是OpenAI官网的账号,给大家打造了一个一模一样ChatGPT,很多粉丝朋友现在也都通过我拿这种号,价格不贵,关键还有售后。

一句话说明:用官方一半价格的钱,一句话说明:用跟官方 ChatGPT4.0 一模一样功能,无需魔法,无视封号,不必担心次数不够。

最大优势:可实现会话隔离!突破限制:官方限制每个账号三小时可使用40次4.0本网站可实现次数上限之后,手动切换下一个未使用的账号【相当于一个4.0帐号,同享受一百个账号轮换使用权限】


为了跟上AI时代我干了一件事儿,我创建了一个知识星球社群:ChartGPT与副业。想带着大家一起探索ChatGPT和新的AI时代

有很多小伙伴搞不定ChatGPT账号,于是我们决定,凡是这三天之内加入ChatPGT的小伙伴,我们直接送一个正常可用的永久ChatGPT独立账户。

不光是增长速度最快,我们的星球品质也绝对经得起考验,短短一个月时间,我们的课程团队发布了8个专栏、18个副业项目

简单说下这个星球能给大家提供什么:


1、不断分享如何使用ChatGPT来完成各种任务,让你更高效地使用ChatGPT,以及副业思考、变现思路、创业案例、落地案例分享。

2、分享ChatGPT的使用方法、最新资讯、商业价值。

3、探讨未来关于ChatGPT的机遇,共同成长。

4、帮助大家解决ChatGPT遇到的问题。

5、提供一整年的售后服务,一起搞副业

星球福利:

1、加入星球4天后,就送ChatGPT独立账号。

2、邀请你加入ChatGPT会员交流群。

3、赠送一份完整的ChatGPT手册和66个ChatGPT副业赚钱手册。

其它福利还在筹划中... 不过,我给你大家保证,加入星球后,收获的价值会远远大于今天加入的门票费用 !

本星球第一期原价399,目前属于试运营,早鸟价149,每超过50人涨价10元,星球马上要来一波大的涨价,如果你还在犹豫,可能最后就要以更高价格加入了。。

早就是优势。建议大家尽早以便宜的价格加入!


PS:欢迎在留言区留下你的观点,一起讨论提高。如果今天的文章让你有新的启发,欢迎转发分享给更多人。

版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢!

欢迎加入后端架构师交流群,在后台回复“学习”即可。


最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。在这里,我为大家准备了一份2021年最新最全BAT等大厂Java面试经验总结。

别找了,想获取史上最简单的Java大厂面试题学习资料

扫下方二维码回复面试就好了

猜你还想看

阿里、腾讯、百度、华为、京东最新面试题汇集

看看人家那权限管理系统,那叫一个优雅(附源码)!

牛逼啊!接私活必备的 400 多个开源项目!赶快收藏吧(附源码合集)!

用雪花 id 和 uuid 做 MySQL 主键,被领导怼了

项目从 MySQL 切换 PostgreSQL,踩了太多的坑!!!

,你在看吗?

编程技术圈
(本号原名:程序员小乐) 这里有Java、架构、Python、技术、算法、职场、感悟、面经、资源等,一线大厂干货,10万 + 程序员都在看,做一个有趣的帮助程序员成长的架构师公众号,每天早上07点24,第一时间与你相约。
 最新文章