首页 理论教育 Java服务端研发-Ribbon

Java服务端研发-Ribbon

时间:2023-11-22 理论教育 版权反馈
【摘要】:先创建一个服务的消费者,用服务消费者单独调用服务的提供者,完成基础的Ribbon调用;然后为服务提供者再添加一个实例。看一下Ribbon的负载情况。Ribbon获取数据的几种方法由于查看Provider日志,发现Provider已经正确返回了数据,那么可能先怀疑,Consumer是否正确收到了数据。图9-7 Provider服务多实例调用Consumer服务接口,观察Provider服务的两台实例是否都得到了调用。当然Ribbon的负载还包含其他策略,可以进入工程的ribbon-loadbalancer依赖中查看更多的负载策略。

Java服务端研发-Ribbon

先创建一个服务的消费者(类似数据组装层),用服务消费者单独调用服务的提供者(类似核心功能模块),完成基础的Ribbon调用;然后为服务提供者再添加一个实例。看一下Ribbon的负载情况。

(1)添加服务消费者依赖

新建一个Spring Boot工程SpringCloudServiceConsumer,添加如下依赖。

978-7-111-61011-3-Part02-268.jpg

(2)添加Eureka相关配置

由于服务间调用是基于Eureka的服务发现注册机制的,所以服务消费者也要注册到Eureka上,才能获取服务提供者的信息。这里可以参照上一节服务提供者的Eureka配置进行修改。不同的地方就是服务名字和端口号,消费者服务名使用service-consumer,端口号使用18020。打开Eureka可以看到相关注册信息,如图9-5所示。

978-7-111-61011-3-Part02-269.jpg

图9-5 Eureka服务列表

(3)服务提供者提供可调用接口

对服务提供者进行改造,把前面使用过的SpringBootMybatis工程的代码移植[38]过来,从而使SpringCloudServiceProvider[39]工程具备了用户查询接口、日志记录等能力,这样Provider工程就成为了注册到Eureka上的负责用户模块的微服务。

(4)服务消费者调用配置

在SpringCloudServiceConsumer的启动类中,添加如下代码,使调用的RestTemplete实例被Spring管理。

978-7-111-61011-3-Part02-270.jpg

(5)服务消费者逻辑添加

在Consumer工程中,添加Service接口类和它的实现类,在实现类中调用Provider服务的接口,从接口返回的数据中,选取需要的数据,返回给Controller类,然后在Controller类中完成数据的模板化返回[40]。同时需要在Consumer工程中建立一个DomainUser类,用于承接Provider服务的返回数据,这个类的数据结构和Provider中的相同,这里就不再赘述。

978-7-111-61011-3-Part02-271.jpg

978-7-111-61011-3-Part02-272.jpg

添加Controller类逻辑如下:

978-7-111-61011-3-Part02-273.jpg

上面的代码在Service中使用RestTemplete的getForObject方法调用服务提供者的接口,由于服务都已经注册到Eureka上,所以Http链接上可以直接使用服务的名字[41]。在方法中期望返回一个Result类型的数据,所以在请求参数中设置了Result类型,然后根据返回的信息码判断是否成功,如果成功则可以得到DomainUser类型的实例,然后Consumer服务再对数据进行封装返回。

通过用浏览器访问Consumer服务的接口完成调用,但并没有返回期望得到的输出结果,并且Consumer服务报错了。但是排查Provider服务的输出日志[42]发现此服务已经正确返回了数据。那么问题出在哪里?下面从问题排查的角度来逐步分析上面出现的问题,然后尝试去解决这个问题。

(6)Ribbon获取数据的几种方法

由于查看Provider日志,发现Provider已经正确返回了数据,那么可能先怀疑,Consumer是否正确收到了数据。所以对Service中的getUserFromProvider方法进行改造。(www.xing528.com)

978-7-111-61011-3-Part02-274.jpg

通过日志查看,会发现Consumer服务已经成功收到了数据。那么问题可能就出在Json数据到类实例的转化过程。

如果读者仔细阅读了第1章,应该记得Java的泛型模板和C++的不同,Java的泛型会擦除类型。既然RestTemplete提供了根据类型获取返回数据的接口,那么如果不使用模板,而使用确定类型来获取数据呢?

所以,下面创建一个确定类型的类,来承接getForObject方法返回的数据,这个确定类型不使用模板,而是直接包含一个DomainUser对象。

978-7-111-61011-3-Part02-275.jpg

通过Postman访问获取用户接口,可以看到数据的输出。如图9-6所示。

978-7-111-61011-3-Part02-276.jpg

图9-6 获取用户信息

现在数据确实可以返回了,但是这样却破坏了模板化输出的结构,调用方要针对每个提供方返回的数据提供两个类,来承接数据返回,所以还是期望能够使用模板来实现数据传递的简单化和标准化。在Service实现类中添加如下引用,并修改getUserFromProvider方法。

978-7-111-61011-3-Part02-277.jpg

978-7-111-61011-3-Part02-278.jpg

模板类型应该使用exchange方法获取,并且要在参数中设置一个特殊的类型,不能使用普通的类型获取方法。通过这样修改,模板又可以使用了。

(7)多台负载

通过Spring Boot的多环境配置,用另一个端口再启动一个Provider实例[43],如图9-7所示。

978-7-111-61011-3-Part02-279.jpg

图9-7 Provider服务多实例

调用Consumer服务接口,观察Provider服务的两台实例是否都得到了调用。最简单的办法就是观察日志,你会发现两台实例轮流打印日志信息。

(8)修改负载规则

默认的负载规则是轮询的方式,可以在消费者服务的配置类或启动类中添加如下代码修改负载规则:

978-7-111-61011-3-Part02-280.jpg

这段代码把负载规则修改为随机策略。当然Ribbon的负载还包含其他策略,可以进入工程的ribbon-loadbalancer依赖中查看更多的负载策略。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈