精通springcloud:微服务之间的通信,使用Ribbon执行负载均衡
Posted jinggege795
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了精通springcloud:微服务之间的通信,使用Ribbon执行负载均衡相关的知识,希望对你有一定的参考价值。
使用Ribbon执行负载均衡
与Ribbon 有关的主要概念是命名客户端(Client) 。这就是为什么开发人员可以使用客户端的名称而不是带有主机名和端口的完整地址来调用其他服务,并且无须连接到服务发现。在这种情况下,应该在application.yml文件内的Ribbon配置设置中提供地址的列表。
使用Ribbon客户端启用微服务之间的通信
现在来继续这个示例。它由4个独立的微服务组成,其中一些可能会调用其他微服务公开的端点。应用程序源代码可在以下地址处获得。
https://github。com/piomin/ sample-spr ing-cloud-comm.git
在这个示例中,我们将尝试开发一个简单的订单系统,客户可以在该系统中购买产品。如果客户决定确认要购买的所选产品列表,则POST请求将发送到order-service (订单服务)。它由REST控制器内的Order prepare(@RequestBody Order orde()..方法处理。该方法负责订单的准备。首先,它将从order-service 中调用适当的API方法,考虑产品列表中每个产品的价格、客户订购的历史记录及客户在系统中的类别等因素,计算出最终价格:然后,它通过调用account-service (账户服务),验证客户的账户余额是否足够执行订单:最后,它返回计算的价格。如果客户确认操作,则调用PUT/{id}方法。该请求将由REST控制器内的Order accept(@PathVariable Long d...}方法处理。它会更改订单的状态并从客户的账户中提取资金。该系统架构可以分解为各个微服务,如图6.1所示。
静态负载均衡配置
本示例中的order-service (订单服务)必须与该示例中的所有其他微服务进行通信,以执行所需的操作,因此,开发人员需要使用ribon.listOfServers 属性定义3个不同的Ribbon客户端,并且这些客户端需要包含网络地址设置。该示例中的第二个重要事项是在Eureka中禁用默认启用的发现服务。以下是application.yml文件中order. service的所有已定义属性。
server :
port: 8090
account-service:
ribbon :
eureka:
enabled: false
listofservers: localhost:8091
customer-service:
ribbon:
eureka:
enabled: false
listOfServers: localhost:8092
product-service:
ribbon:
eureka:
enabled: false
listOfServers: localhost:8093
开发人员还应该在项目中包含以下依赖项,以便将RestTemplate与Ribbon客户端结合在一起使用。
<dependency>
<groupId>org. springf ramework.cloud</ groupId>
<arti factId>spring-cloud-starter-ribbon/arti factId>
</ dependency>
<dependency>
<groupId>org.springframework.boot/groupId>
<arti factId>spring-boot-starter-web</artifactId>
</ dependency>
然后,开发人员可以通过声明application.yml中配置的名称列表来启用Ribbon客户端。为完成此操作,可以使用@RibbonClients注解main类或任何其他Spring配置类。开发人员还应该注册RestTemplate bean 并使用@LoadBalanced注解它,以启用与SpringCloud组件的交互。
@Spr ingBootApplication
@RibbonClients ({
@RibbonClient (name - " account-service"),
@RibbonClient (name = "customer-service"),
@RibbonClient (name = "product-service")
})
public class OrderApplication {
@LoadBalanced
@Bean
RestTemplate restTemplate() (
return new RestTemplate () :
}
public static void main(String[] args) {
new
SpringApplicationBuilder (OrderApplication.class) .web(true) .run (args);
}
//...
}
调用其他服务
最后,我们可以开始实现OrderController (订单控制程序),它负责提供公开到微服务之外的HTTP方法。它注入了RestTemplate bean以便能够调用其他HTTP端点。开发人员可能会在以下源代码片段中看到使用application.yml中配置的Ribbon客户端名称而不是IP地址或主机名。使用相同的RestTemplate bean,即可与3个不同的微服务进行通信。在这里需要花一点时间来讨论控制程序内部可用的方法。在第一个实现的方法中,可以调用product-service (产品服务)的GET端点,该端点将返回包含所选产品详细信息的列表。然后,可以调用customer-service (客户服务)公开的GET /withAccounts/ {id}方法,它将返回客户详细信息及其账户列表。
现在,开发人员拥有了计算最终订单价格所需的所有信息,并将验证客户在其主账户中是否有足够的资金。PUT方法将调用account-service (账户服务)的端点以从客户账户中提取资金。虽然我们花了很多时间来讨论OrderController 中可用的方法,但我们认为这是必要的,因为相同的示例将用于显示Spring Cloud 组件的主要功能,这些组件提供了微服务之间同步通信的机制。
@RestController
public class OrderController {
@Autowired
OrderRepository repository;
@Autowired
RestTemplate template;
@PostMapping
public Order prepare (ORequestBody Order order) {
int price = 0;
Product[] products =
template . postForobject ("http://product-service/ids",
order . getProductIds(), Product[].class) ;
Customer customer =
template . getForobject ("http://customer-service/withAccounts/{id}",
Customer.class, order. getCustomerId()) ;
for (Product product : products)
price += product.getPrice() ;
final int priceDiscounted一priceDiscount (price, customer) ;
Optional<Account> account = customer .getAccounts() .stream() .filter(a->
(a.getBalance() > priceDiscounted)) .findFirst() ;
if (account. isPresent()) (
order . setAccountId (account.get() .getId()) ;
order. setStatus (OrderStatus .ACCEPTED) ;
order. setPrice (priceDiscounted) ;
} else {
order . setStatus (OrderStatus . REJECTED) ;
}
return repository.add (order) ;
}
@PutMapping("/{id}")
public Order accept (@Pathvarlable Long id) {
final Order order - repository. findById(id);
template . put ("http://account-service/withdraw/ (id}/ {amount}", null,
order。getAccountId(); order.getPrice());
order . setstatus (OrderStatus. DONE) ;
repository. update (order) ;
return order;
}
//...
}
这里比较有趣并值得注意的是,customer. service的GET /withAcounts/fid}方法(由order-service调用)也使用Ribbon客户端与另一个微服务account-service 进行通信。以下是来自CustomerController的片段,它具有上述方法的实现。
@GetMapping ("/wi thAccounts/lid}")
public Customer findByIdWithAccounts (@PathVariable("id") Long id) {
Account[] accounts =
template . getForobject ("http://account-service/ customer/ {customerId}",
Account[] .class, id) ;
Customer c = repository. findById(id);
C . setAccounts (Arrays . stream (accounts) .collect (Collectors.toList()));
return C:
}
要测试该示例,可以按以下步骤操作。首先,使用Maven命令mvn clean install构建整个项目。然后,使用java -jar命令以任意顺序启动所有微服务,而无须任何其他参数。当然,开发人员也可以从集成开发环境中运行该应用程序。在启动时应该为每个微服务准备测试数据。由于没有持久性存储,因而重启后将删除所有对象。开发人员可以通过调用order-service公开的POST方法来测试整个系统。示例请求如下所示。
$ curl -d ' {"productIds": [1,5],"customerId": 1, "status": "NEW"}' -H
"Content-Type: application/json" -x POST http: //localhost:8090
如果尝试发送此请求,开发人员将能够看到Ribbon客户端打印的以下日志。
DynamicServerListLoadBalancer for client customer- service initialized:DynamicServerLis tLoadBalancer: {NFLoadBalancer :name=customer service,current list of Servers= [localhost: 8092] ,Load balancer stats= Zonestats: {unknown= [Zone : unknown; Instance count:1; Active connectionscount: 0;Circuit breaker tripped count: 0; Active connections perserver: 0.0;]} ,Server stats:[ [Server: localhost:8092; Zone : UNKNOWN; Total Requests:0; Successive connection failure:0; Total blackoutseconds:0; Last connection made:Thu Jan 01 01:00:00 CET 1970: Firstconnection made: Thu Jan 01 01:00:00 CET 1970; Active Connections:0;total failure count in last (1000) msecs:0; average resp time:0.0;90 percentile resp time:0.0; 95 percentile resp time:0.0; min resptime:0.0; max resp time:0.0; stddev resp time:0.01]1 ServerList:com. netflix.loadbalancer. ConfigurationBasedserverListe7f1e23f6
需要指出的是,本节描述的方法有一个很大的缺点,这使得它在由若干个微服务组成的系统中并不能很好地工作。如果系统有自动扩展功能的话,该问题会更严重。开发人员可以很容易地发现,所有服务的网络地址都是人工管理的。当然,我们也可以考虑将配置设置从每个胖JAR中的application.yml文件移动到配置服务器。但是,这样做并不能改变管理:大量交互仍然很麻烦的事实。通过客户端负载均衡器和服务发现进行交互的能力,可以轻松解决这样的问题。
总结
因为文章包含的内容实在是太多了,就不给大家做过多的介绍了,需要这份文档来学习的小伙伴,可以转发此文关注小编。
扫码来获取就可以了!
以上是关于精通springcloud:微服务之间的通信,使用Ribbon执行负载均衡的主要内容,如果未能解决你的问题,请参考以下文章
精通springcloud:微服务之间的通信,监控延迟和容错
你是否精通springcloud:使用SpringCloud进行同步通信?
你是否精通springcloud:使用SpringCloud进行同步通信?
精通springcloud:微服务之间的通信,带Hystrix的断路器模式