- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
大家好,我是三友~~ 。 前几天有个大兄弟问了我一个问题,注册中心要集成SpringCloud,想实现SpringCloud的负载均衡,需要实现哪些接口和规范. 既然这个兄弟问到我了,而我又刚好知道,这不得好好写一篇文章来回答这个问题,虽然在后面的聊天中我已经回答过了. 接下来本文就以探究一下Nacos、OpenFeign、Ribbon、loadbalancer等组件协调工作的原理的方式,来讲一讲应该需要是实现哪些接口了. 再多说一句,本文并没有详细地深入剖析各个组件的源码,如果有感兴趣的兄弟可以从微信公众号 三友的java日记 后台菜单栏中的文章分类中查看我之前写的关于Nacos、OpenFeign、Ribbon源码剖析的文章. 先从Nacos讲起. Nacos是什么,官网中有这么一段话 。 这一段话说的直白点就是Nacos是一个注册中心和配置中心! 。 在Nacos中有客户端和服务端的这个概念 。 当需要向Nacos服务端注册或者获取服务实例数据的时候,只需要通过Nacos提供的客户端SDK就可以了,就像下面这样: 引入依赖 。 示例代码 。 当服务注册到Nacos服务端的时候,在服务端内部会有一个集合去存储服务的信息 。 这个集合在注册中心界中有个响亮的名字, 服务注册表 . 用过SpringCloud的小伙伴肯定知道,在项目启动的时候服务能够自动注册到服务注册中心,并不需要手动写上面那段代码,那么服务自动注册是如何实现的呢? SpringCloud本身提供了一套服务自动注册的机制,或者说是约束,其实就是三个接口,只要注册中心实现这些接口,就能够在服务启动时自动注册到注册中心,而这三个接口我称为服务自动注册三板斧. Registration是SpringCloud提供的一个接口,继承了ServiceInstance接口 。 从ServiceInstance的接口定义可以看出,这是一个服务实例数据的封装,比如这个服务的ip是多少,端口号是多少. 所以Registration就是当前服务实例数据封装,封装了当前服务的所在的机器ip和端口号等信息. Nacos既然要整合SpringCloud,自然而然也实现了这个接口 。 这样当前服务需要被注册到注册中心的信息就封装好了. ServiceRegistry也是个接口,泛型就是上面提到的服务实例数据封装的接口 。 这个接口的作用就是把上面封装的当前服务的数据Registration注册通过 register 方法注册到注册中心中. Nacos也实现了这个接口. 并且核心的注册方法的实现代码跟前面的demo几乎一样 。 AutoServiceRegistration是一个标记接口,所以本身没有实际的意义,仅仅代表了自动注册的意思. AutoServiceRegistration有个抽象实现AbstractAutoServiceRegistration 。 AbstractAutoServiceRegistration实现了ApplicationListener,监听了WebServerInitializedEvent事件. WebServerInitializedEvent这个事件是SpringBoot在项目启动时,当诸如tomcat这类Web服务启动之后就会发布,注意,只有在Web环境才会发布这个事件. ServletWebServerInitializedEvent继承自WebServerInitializedEvent. 所以一旦当SpringBoot项目启动,tomcat等web服务器启动成功之后,就会触发AbstractAutoServiceRegistration监听器的执行. 最终就会调用ServiceRegistry注册Registration,实现服务自动注册 。 Nacos自然而然也继承了AbstractAutoServiceRegistration 。 对于Nacos而言,就将当前的服务注册的ip和端口等信息,就注册到了Nacos服务注册中心. 所以整个注册流程就可以用这么一张图概括 。 当然,不仅仅是Nacos是这么实现的,常见的比如Eureka,Zookeeper等注册中心在整合SpringCloud都是实现上面的三板斧. 讲完了SpringCloud环境底下是如何自动注册服务到注册中心的,下面来讲一讲Ribbon. 我们都知道,Ribbon是负载均衡组件,他的作用就是从众多的服务实例中根据一定的算法选择一个服务实例. 但是有个疑问,服务实例的数据都在注册中心,Ribbon是怎么知道的呢??? 答案其实很简单,那就是需要注册中心去主动 适配 Ribbon,只要注册中心去适配了Ribbon,那么Ribbon自然而然就知道服务实例的数据了. Ribbon提供了一个获取服务实例的接口,叫ServerList 。 接口中提供了两个方法,这两个方法在众多的实现中实际是一样的,并没有区别. 当Ribbon通过ServerList获取到服务实例数据之后,会基于这些数据来做负载均衡的. Nacos自然而然也实现了ServerList接口,为Ribbon提供Nacos注册中心中的服务数据. 这样,Ribbon就能获取到了Nacos服务注册中心的数据. 同样地,除了Nacos之外,Eureka、Zookeeper等注册中心也都实现了这个接口. 到这,其实就明白了Ribbon是如何知道注册中心的数据了,需要注册中心来适配. 在这里插个个人的看法,其实我觉得Ribbon在适配SpringCloud时对获取服务实例这块支持封装的不太好. 因为SpringCloud本身就是一套约束、规范,只要遵守这套规范,那么就可以实现各个组件的替换,这就是为什么换个注册中心只需要换个依赖,改个配置文件就行. 而Ribbon本身是一个具体的负载均衡组件,注册中心要想整合SpringCloud,还得需要单独去适配Ribbon,有点违背了SpringCloud约束的意义. 就类似mybatis一样,mybatis依靠jdbc,但是mybatis根本不关心哪个数据库实现的jdbc. 真正好的做法是Ribbon去适配SpringCloud时,用SpringCloud提供的api去获取服务实例,这样不同的注册中心只需要适配这个api,无需单独适配Ribbon了. 而SpringCloud实际上是提供了这么一个获取服务实例的api,DiscoveryClient 。 通过DiscoveryClient就能够获取到服务实例,当然也是需要不同注册中心的适配. 随着Ribbon等组件停止维护之后,SpringCloud官方自己也搞了一个负载均衡组件 loadbalancer ,用来平替Ribbon. 这个组件底层在获取服务实例的时候,就是使用的DiscoveryClient. 所以对于 loadbalancer 这个负载均衡组价来说,注册中心只需要实现DiscoveryClient之后就自然而然适配了 loadbalancer . OpenFeign是一个rpc框架,当我们需要调用远程服务的时候,只需要声明个接口就可以远程调用了,就像下面这样 。 听上去很神奇,其实本质上就是后面会为接口创建一个动态代理对象,解析类上,方法上的注解. 当调用方法的时候,会根据方法上面的参数拼接一个http请求地址,这个地址的格式是这样的 http://服务名/接口路径 . 比如,上面的例子,当调用 saveOrder 方法的时候,按照这种规律拼出的地址就是这样的 http://order/order ,第一个order是服务名,第二个order是PostMapping注解上面的. 但是由于只知道需要调用服务的服务名,不知道服务的ip和端口,还是无法调用远程服务,这咋办呢? 这时就轮到Ribbon登场了,因为Ribbon这个大兄弟知道服务实例的数据. 于是乎,OpenFeign就对Ribbon说,兄弟,你不是可以从注册中心获取到order服务所有服务实例数据么,帮我从这些服务实例数据中找一个给我. 于是Ribbon就会从注册中心获取到的服务实例中根据负载均衡策略选择一个服务实例返回给OpenFeign. OpenFeign拿到了服务实例,此时就获取到了服务所在的ip和端口,接下来就会重新构建请求路径,将路径中的服务名替换成ip和端口,代码如下 。 假设获取到的orde服务所在的ip和端口分别是 192.168.2.100 和 8080 ,最终重构后的路径就是 http://192.168.2.100:8080/order ,之后OpenFeign就可以发送http请求了. 至于前面提到的 loadbalancer ,其实也是一样的,他也会根据负载均衡算法,从DiscoveryClient获取到的服务实例中选择一个服务实例给OpenFeign,后面也会根据服务实例重构url,再发送http请求. 到这,就把Nacos、OpenFeign、Ribbon、loadbalancer等组件协调工作的原理讲完了,其实就是各个组件会预留一些扩展接口,这也是很多开源框架都会干的事,当第三方框架去适配的,只要实现这些接口就可以了. 最后画一张图来总结一下上述组价的工作的原理. 最后再小小地说一句,Nacos、OpenFeign、Ribbon源码剖析的文章,可以从微信公众号 三友的java日记 后台菜单栏中的文章分类中查看. RocketMQ重复消费的7种原因 。 如何去阅读源码,我总结了18条心法 。 如何实现延迟任务,我总结了11种方法 。 如何写出漂亮代码,我总结了45个小技巧 。 三万字盘点Spring/Boot的那些常用扩展点 。 两万字盘点那些被玩烂了的设计模式 。 扫码或者搜索关注公众号 三友的java日记 ,及时干货不错过,公众号致力于通过画图加上通俗易懂的语言讲解技术,让技术更加容易学习,回复 面试 即可获得一套面试真题. Nacos
< dependency >
< groupId >
com.alibaba.nacos
</ groupId >
< artifactId >
nacos-client
</ artifactId >
< version >
1.4.4
</ version >
</ dependency >
Properties properties =
new
Properties();
properties.setProperty(
"serverAddr"
,
"localhost"
);
properties.setProperty(
"namespace"
,
"8848"
);
NamingService naming = NamingFactory.createNamingService(properties);
//服务注册,注册一个order服务,order服务的ip是192.168.2.100,端口8080
naming.registerInstance(
"order"
,
"192.168.2.100"
,
8080
);
//服务发现,获取所有的order服务实例
List<Instance> instanceList = naming.selectInstances(
"order"
,
true
);
如何进行服务自动注册?
服务自动注册三板斧
服务实例数据封装--Registration
服务注册--ServiceRegistry
服务自动注册--AutoServiceRegistration
Ribbon
< dependency >
< groupId >
org.springframework.cloud
</ groupId >
< artifactId >
spring-cloud-starter-loadbalancer
</ artifactId >
< version >
2.2.5.RELEASE
</ version >
</ dependency >
OpenFeign
http://order/order
总结
往期热门文章推荐
最后此篇关于扒一扒Nacos、OpenFeign、Ribbon、loadbalancer组件协调工作的原理的文章就讲到这里了,如果你想了解更多关于扒一扒Nacos、OpenFeign、Ribbon、loadbalancer组件协调工作的原理的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在 openFeign 未出现前,Spring 提供了 RestTemplate 作为远程服务调用的客户端,提供了多种便捷访问远程 Http 服务的方法,能够大大提高客户端的编写效率。由于文章内容会使
在微服务开发中SpringCloud全家桶集成了OpenFeign用于服务调用,SpringCloud的OpenFeign使用SpringMVCContract来解析OpenFeign的接口定义。
我在 Spring Boot 中使用 OpenFeign 客户端而不使用 Ribbon 或 Eureka。我创建了一个自定义错误解码器,它按预期处理响应错误,但连接拒绝错误似乎绕过了我的自定义解码器。
大家好,我是三友~~ 前几天有个大兄弟问了我一个问题,注册中心要集成SpringCloud,想实现SpringCloud的负载均衡,需要实现哪些接口和规范。
我有一个 OpenFeign 客户端,设置如下: @FeignClient(name = "myService", qualifier = "myServiceClient", url = "${my
本篇文章涉及底层设计以及原理,以及问题定位,比较深入,篇幅较长,所以拆分成上下两篇: 上:问题简单描述以及 Spring Cloud RefreshScope 的原理 下:当前 s
我正在使用 swagger-codegen 为我的 Feign Client 生成界面。 但是 swagger-codegen 生成这些方法: Optional getObjectMapper();
我正在使用 spring Cloud openFeign 来从 service#1 向 service#2 发出请求 当我使用restTemplate时,我可以在jaeger跟踪中正确地看到2个请求。
简介 我最近使用了 netflix feign 和 ribbon,这非常有用。 一个例子是: @FeignClient(name = "ldap-proxy") public interface Ld
有什么区别: spring-cloud-starter-openfeign ( https://github.com/spring-cloud/spring-cloud-openfeign ) 和 s
我正在使用 Spring Boot 创建基于休息的服务。一切正常。 现在我添加了以下依赖项 org.springframework.cloud
我正在调用一个 API,它将某些 HttpHeaders 列入黑名单,包括 Content-Length ,它似乎是由 spring-openfeign 下的 HttpClient 预设的。为了正确接
我在 spring 和 openfeign 方面遇到问题,我认为你可以帮助我。 我有一个 pom 文件如下: 4.0.0 xx.yyy component 1.0.
OpenApi documentation说它支持千分尺。集成如何工作?除了这个小文档,我找不到任何东西。 我在 Spring Boot 应用程序中有一个 FeignClient @FeignClie
当我尝试实现 ErrorDecoder 来解码 feign 异常时,我发现 response.body() 中的流已关闭,因此当我尝试读取该流时并转换为字符串,它抛出java.io.IOExcepti
当尝试将 feign-httpclient 与 Spring-cloud-starter-openfeign 一起使用时,我收到 SSL 握手异常,而如果我不使用,相同的代码可以工作feign-htt
我在 eclipse java 中有 pom.xml,用于在 java 中构建简单的 Rest Web 服务,但是该依赖项显示错误,我已经尝试并且添加版本和更新项目在依赖项中仍然存在错误,我该如何修复
语境 我有一个 spring boot (version 2.2.6.RELEASE) web 项目。 从这个 Web 应用程序(我称之为“APP1”)我想使用来自另一个 Web 应用程序的 PATC
我有一个带有以下假客户的项目 @FeignClient(name = "name", url = "${tokenService}") public interface TokenService {
目标:从 Spring Boot 1.x (webMvc) 迁移到版本 2 (webFlux),并将 Spring Cloud Edgware SR2 迁移到 FinchleyM8(等待发布版本)。
我是一名优秀的程序员,十分优秀!