博客 SpringCloud集成Eureka并实现负载均衡

SpringCloud集成Eureka并实现负载均衡

   数栈君   发表于 2024-01-09 10:34  460  0

前言
辗转两家公司也算工作了大半年,有幸见识过很多微服务架构,比如Dubbo+Redis的组合;Dubbo+Zookepper的组合;SpringCloud+Eureka的组合;SpringCloud+Nacos的组合…
每一种组合都有属于自己的故事。
笔者认为:流行的不一定是最好的,如果只学习最流行的技术,这对以后的发展是很受限的。作为后端我们还是需要追求一定的广度。在以后的职业生涯中遇到一些特殊业务场景,才能够有更多的方案去灵活应对!当领导让你做技术选型,你直接好几套方案往他面前一摆,这真的很酷炫。
我想从当下最流行的SpringCloud体系谈起,从demo到底层循序渐进地整理出每一套组合,也非常希望能够对你起到一些绵薄的帮助~

故事从Eureka(译文:发现你了)说起…

1.Eureka
你问我Eureka是什么,其实就是一个基于SpringBoot的Java程序。解压Eureka-server的jar包之后,可以清楚看到一个标准的Java目录结构(还有一些存放前端页面的static文件):
http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/bbb6219ac5abaae6ab130d4b3a675e48..png
  
和nacos非常相似,只不过Eureka作为注册中心默认是将实例信息存放在eureka-server内存中,这比较适用于开发环境与测试环境,生产环境中还是建议配置相应的数据库表,做好数据持久化。在启动方式上,二者大体相似,shell脚本,maven模块启动,docker镜像…都可以实现。

2.整合Eureka作为注册中心
给大家提供一个我已经整合好的demo(用户-支付的场景),实现了服务间的注册与发现,并且有数据库表的支持,可以进行简单的调用:https://gitee.com/lazy-sheep-java/cloud-eureka.git
下面采用将Eureka-server作为独立maven模块的方式启动来作为注册中心,其实本质也就是扫描运行Eureka-server的jar包而已,并在此过程中做一些人为配置:

2.1创建maven工程
创建一个父-子结构的maven工程,这个很简单点点点就好

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/1bcc40cb4f7f27b3c1d80c12910060dc..png
  
2.2依赖配置(Eureka-Server)
作为独立的maven模块启动Eureka服务,只需要引入核心依赖,配置一个启动类,并配置相应路径端口即可提供服务:

<!--eureka服务端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
1
2
3
4
5

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/3f5089877326ba9d393b8666634179b5..png
  
server:
port: 10086 # 服务端口
spring:
application:
name: eureka-server # eureka的服务名称
eureka:
client:
service-url: # eureka的地址信息
defaultZone: http://127.0.0.1:10086/eureka
1
2
3
4
5
6
7
8
9
2.3业务配置(Eureka-Client)
在业务模块中,都属于Eureka的客户端,其核心依赖为:

<!--eureka客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
1
2
3
4
5
并在相应的模块中配置服务端的地址
http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/9f54129ad717366c05b12edabd257e01..png
  
直到这里,当启动eureka-server、user-service模块之后,登录http://127.0.0.1:10086就会发现,Eureka-server作为注册中心已经成功注册了user-service服务,就像这样:
http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/222189d605cdd45902db5323fee3b2bd..png
  

2.4服务调用流程
在一个订单服务(A)调用用户服务(B)的模型中,A服务从Eureka-server获取B服务的地址。在A服务中使用RestTemplate通过getForObject()方法发送HTTP请求到B服务的地址,并处理返回的响应将其封装为指定的对象。
http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/af64c84a21b301b109a638e159d90ccd..png
  
这是一个最简单的调用链路。用非官方语言描述该过程,即A拿着B的使用说明书向B发消息并得到了回应,而Eureka正是那本说明书
当然,在生产环境中一个微服务不太可能只会有单实例,更多的是一服务多实例的形式,当被调用方接收到调用请求,会去做负载均衡的处理,从而将请求落到合适实例上。以此来实现高可用、高扩展、高伸缩…

3.集成负载均衡
首先给一个服务多部署几个实例:
http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/ae08643f1027acea86d0e3be582f40c3..png
  
效果就像这样:
http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/3fb185257d772efbf147c752b9f48476..png
  
以前我们拉取的是某个服务的那个实例,现在则是拉取某个服务的实例列表。并在此基础上通过负载均衡将发来的请求指定到其中的某一实例上。
那要怎么实现呢?
只需要在服务调用方添加一个注解即可,最简单的方式就是这样:

@Bean
@LoadBalanced //负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
1
2
3
4
5
其实,在RestTemplate内部继承了一个拦截器(实现请求的转发,也就是负载均衡),而@LoadBalance注解则是帮助开启了该功能
http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/55cb1da08f342da8c7bee789cc777491..png
  
注解本身是没有实现相关功能的(后面分析实现原理):
http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/c39ab02f0dc249948fee3fd343822c1e..png
  
言归正传
现在我们的user服务已经有三个实例,并且已经进入到了负载均衡的列表
http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/f8cd3a9f0d7a46b1a58882101cf52fdd..png
  
我们用aop做一个切面,来把负载均衡分发到服务实例上的信息以日志的形式打印到控制台,以便更直观地看到均衡的效果:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
1
2
3
4
注入Eureka客户端,通过提供的api来查询服务的客户端分发到的实例信息:

@Aspect
@Component
@Slf4j
public class RequestAspect {
@Resource
EurekaClient eurekaClient;

@Before(value = "execution(* com.yu7.user.web.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
String className = joinPoint.getTarget().getClass().getName();
log.debug("调用方法:{} ", className + "." + methodName);
InstanceInfo instanceInfo = eurekaClient.getApplicationInfoManager().getInfo();
log.debug("负载均衡到的实例信息为:{}",instanceInfo.getInstanceId());
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
当调用方再次发起请求,观察控制台的信息,可以直接看到请求被分发到了端口为8084的实例上:
http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/3ae508129d6d304556ca4488b831a5f0..png
  
负载均衡成功实现
————————————————
版权声明:本文为CSDN博主「懒羊羊.java」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_57535055/article/details/134391818

免责申明:

本文系转载,版权归原作者所有,如若侵权请联系我们进行删除!


《数据治理行业实践白皮书》下载地址:https://fs80.cn/4w2atu

《数栈V6.0产品白皮书》下载地址:https://fs80.cn/cw0iw1

想了解或咨询更多有关袋鼠云大数据产品、行业解决方案、客户案例的朋友,浏览袋鼠云官网:https://www.dtstack.com/?src=bbs

同时,欢迎对大数据开源项目有兴趣的同学加入「袋鼠云开源框架钉钉技术群」,交流最新开源技术信息,群号码:30537511,项目地址:https://github.com/DTStack  
0条评论
社区公告
  • 大数据领域最专业的产品&技术交流社区,专注于探讨与分享大数据领域有趣又火热的信息,专业又专注的数据人园地

最新活动更多
微信扫码获取数字化转型资料
钉钉扫码加入技术交流群