首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

深入探讨微服务架构中的同步通信机制

编程知识
2024年08月09日 08:39

微服务架构是一种设计方法,将应用程序划分为一组小型服务,每个服务在独立的进程中运行,通常根据业务能力进行组织。这些服务通过多种通信方式交互,以实现整个应用的功能。今天我们着重介绍同步通信,关于异步通信和消息队列(MQ)等内容将在后续讲解。

这里所指的通信,是指我们在客户端内部进行的服务间通信,而非通过调用外部的Web服务进行访问。好的,让我们开始。

负载均衡

服务端负载均衡

在深入探讨客户端负载均衡之前,我们首先应该对服务端负载均衡有一个更加深入的了解,例如nginx组件。现在让我们来仔细看一下:

image

nginx通常用来对我们服务器内部进行负载转发请求,而客户端则是在各个服务内部进行负载分担。

客户端负载均衡

在Spring Cloud中,例如使用Ribbon时,客户端会维护一个服务器地址列表,在发送请求之前通过负载均衡算法选择一个服务器进行访问。这种方式被称为客户端负载均衡,因为它在客户端内部就完成了负载均衡算法的分配工作。

image

同步通信

一般情况下,我们在进行HTTP请求时常会借助各种工具类。我相信大家之前可能经常自行封装httputils等类,或者使用其他官方提供的工具。比如,今天我们来讲解一下RestTemplate工具类。它其实就是一个用来发送HTTP请求的工具,只不过它在此基础上多做了一些额外的工作。接下来我们先看一下它的基本用法。

RestTemplate

RestTemplate 是由 Spring 框架提供的一个功能强大的类,专门用于进行同步客户端的 HTTP 访问。它的设计旨在简化使用 HTTP 客户端进行 REST 调用的复杂流程,并提供了丰富的方法和功能来处理各种 HTTP 请求和响应。

创建 RestTemplate 实例

首先,你需要创建一个 RestTemplate 的实例。这可以通过直接实例化或使用Spring的自动装配来完成。

import org.springframework.web.client.RestTemplate;

RestTemplate restTemplate = new RestTemplate();

发送请求

使用 RestTemplate 发送一个GET请求并获取响应体。

String url = "http://example.com/api/resource";
String result = restTemplate.getForObject(url, String.class);
System.out.println(result);

发送一个POST请求,通常包含请求体。

String url = "http://example.com/api/resource";
Map<String, Object> requestMap = new HashMap<>();
requestMap.put("key1", "value1");
requestMap.put("key2", "value2");

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestMap, headers);
String response = restTemplate.postForObject(url, entity, String.class);
System.out.println(response);

看到这里,你可能会想到,这与微服务间的通信有什么关系呢?难道不只是简单的 HTTP 调用吗?让我们继续深入探讨。

LoadBalanced注解

微服务架构中通常会涉及到注册中心。今天我们专注讨论微服务间的通信,而不深入讲解注册中心,例如 Nacos 是如何管理所有微服务的注册以及如何使一个服务节点发现其他服务节点的。假设我们已经获得了其他服务节点的 IP 地址,你可能会想直接将上述示例中的域名替换为 IP 地址,但是在面对保证高可用的多节点微服务时,直接在代码中写死 IP 地址将会带来灾难性的后果。所有的 IP 地址应当由一个统一组件进行管理和选择。

因此,Ribbon应运而生。一般情况下,如果在项目的pom文件中集成了Nacos依赖,通常会默认包含Ribbon组件,因此不需要单独配置pom文件来引入Ribbon依赖。

基本用法

如前所述,一种方法是直接实例化对象,另一种则是通过Spring容器进行管理和注入。

@Configuration
public class RestConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

这样一来,当需要使用时,就可以轻松地进行服务调用操作。

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value = "/findOrderByUserId/{id}")
    public R findOrderByUserId(@PathVariable("id") Integer id) {
        String url = "http://mall-order/order/findOrderByUserId/"+id;
        R result = restTemplate.getForObject(url,R.class);
        return result;
    }
}

注意,mall-order可不是我们说的网站域名,而是我们配置在nacos等注册中心的服务名。

添加了LoadBalanced注解后,RestTemplate会自动注入所需的依赖项,具体的实现可以通过查看源代码来了解。

源码分析

关于Spring的自动配置,我之前在讲解Spring时提到过很多次,这里就不再详细展开了。我们可以看到它实现了SmartInitializingSingleton接口,因此,想要使用负载均衡功能,必须等到所有的bean都加载完毕才能进行。

image

好的,我们可以看到,在这里他向RestTemplate类添加了一个拦截器。接下来,我们可以探究一下这个拦截器具体做了什么。我选择不逐步展示整个过程是因为这并不必要。首先,这样做记不住,其次,就像处理业务一样,我们只关注最终走到了哪一个数据表。我们只需记住他一定会经过的那个十字路口即可,这样可以减轻大脑的负担。

    public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
            final ClientHttpRequestExecution execution) throws IOException {
        final URI originalUri = request.getURI();
        String serviceName = originalUri.getHost();
        Assert.state(serviceName != null,
                "Request URI does not contain a valid hostname: " + originalUri);
        return this.loadBalancer.execute(serviceName,
                this.requestFactory.createRequest(request, body, execution));
    }

其实,看到这一点,不用猜也能明白。一旦获取了serviceName,也就是我们之前定义的微服务名,它会在execute方法中被替换为真正的IP地址,然后最终调用HTTP请求完成整个过程。让我们来仔细看一下源代码吧。

    public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint)
            throws IOException {
        ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
        Server server = getServer(loadBalancer, hint);
        if (server == null) {
            throw new IllegalStateException("No instances available for " + serviceId);
        }
        RibbonServer ribbonServer = new RibbonServer(serviceId, server,
                isSecure(server, serviceId),
                serverIntrospector(serviceId).getMetadata(server));

        return execute(serviceId, ribbonServer, request);
    }

所有的负载均衡规则都实现在getServer方法中,我们不再深入追踪了。在这一步,我们已经找到了要调用的微服务。如果你还有疑问,我们可以看一下Server类的具体实现,就能明白了。

image

最终就交给HTTP调用即可。然而,仅仅这样还不够。难道你会愿意在每个服务中编写这种无关紧要的服务调用代码吗?这会非常繁琐,不仅增加了业务逻辑的复杂性,还让人感到不便。幸运的是,有了Spring Cloud OpenFeign,这一切变得轻松许多。OpenFeign的出现正是为了解决这种服务间通信的问题,它将这些繁琐的细节封装起来。

然而,要注意,这种封装并不影响通信的实质。下次我们将详细讨论Spring Cloud OpenFeign与Dubbo调用组件的区别与使用方法。

总结

今天我们专注于微服务之间的网络通信。可以清楚地看到,框架的最终目标是使程序员能够更专注于业务逻辑,而不是被迫写各种无关紧要的代码。总结一下,尽管我们使用了框架和各种抽象,但最终仍然是通过HTTP来进行调用。不同的是,在实际调用之前,我们引入了一个拦截器来实现微服务的负载均衡。这个拦截器中实现了各种均衡算法,最终确定真实的IP地址和端口,以便进行访问并获取所需的数据。


我是努力的小雨,一名 Java 服务端码农,潜心研究着 AI 技术的奥秘。我热爱技术交流与分享,对开源社区充满热情。同时也是一位掘金优秀作者、腾讯云内容共创官、阿里云专家博主、华为云云享专家。

💡 我将不吝分享我在技术道路上的个人探索与经验,希望能为你的学习与成长带来一些启发与帮助。

🌟 欢迎关注努力的小雨!🌟

🚀 目前,我的探索重点在于 AI Ag

From:https://www.cnblogs.com/guoxiaoyu/p/18345043
本文地址: http://shuzixingkong.net/article/930
0评论
提交 加载更多评论
其他文章 记一次 .NET某环境监测系统 崩溃分析
一:背景 1. 讲故事 前些天有位朋友找到我,说他们的程序崩溃了,也自己分析了下初步结果,让我帮忙再确认下,既然让我确认,那就开始dump分析之旅吧。 二:WinDbg 分析 1. 为什么会崩溃 windbg 有一个强大之处就是带有一个自动化的分析命令 !analyze -v 可以帮助我们快速的分析
记一次 .NET某环境监测系统 崩溃分析 记一次 .NET某环境监测系统 崩溃分析 记一次 .NET某环境监测系统 崩溃分析
快速基于 ClickHouse + Grafana 搭建可观测性解决方案 - 分布式链路追踪篇(ClickHouse 官方博客)
引言 在 ClickHouse,我们认为可观测性仅仅是另一个实时分析问题。作为一款高性能的实时分析数据库,ClickHouse 被用于多种场景,包括时间序列数据的实时分析。其应用场景的多样性推动了大量分析函数的发展,这些函数有助于查询大多数数据类型。这些查询特性和高压缩率使得越来越多的用户开始利用
快速基于 ClickHouse + Grafana 搭建可观测性解决方案 - 分布式链路追踪篇(ClickHouse 官方博客) 快速基于 ClickHouse + Grafana 搭建可观测性解决方案 - 分布式链路追踪篇(ClickHouse 官方博客) 快速基于 ClickHouse + Grafana 搭建可观测性解决方案 - 分布式链路追踪篇(ClickHouse 官方博客)
《最新出炉》系列小成篇-Python+Playwright自动化测试-67 - 模拟手机浏览器兼容性测试
1.简介 在日常工作中,我们会遇到需要使用不同的硬件设备测试兼容性的问题,尤其是现在手机型号基本上是每个厂家每年发布一款新机型,而且手机的屏幕大小分辨率五花八门的,我们基本不可能全部机型都用真机测试一遍,playwright提供了模仿机型的功能,我们可以使用playwright来模拟设备。使用 Pl
《最新出炉》系列小成篇-Python+Playwright自动化测试-67 - 模拟手机浏览器兼容性测试 《最新出炉》系列小成篇-Python+Playwright自动化测试-67 - 模拟手机浏览器兼容性测试 《最新出炉》系列小成篇-Python+Playwright自动化测试-67 - 模拟手机浏览器兼容性测试
适合新手进行接口与自动化测试练习的推荐网站!!!
对于新手来说,接口与自动化测试练习网站是提升技能的重要资源。以下是一些适合新手进行接口与自动化测试练习的推荐网站: 1、httpbin.org httpbin.org是一个在线提供HTTP服务的网站,它提供了丰富的HTTP接口,用于测试HTTP请求和响应的各种信息,如cookie、IP、header
适合新手进行接口与自动化测试练习的推荐网站!!! 适合新手进行接口与自动化测试练习的推荐网站!!! 适合新手进行接口与自动化测试练习的推荐网站!!!
【VMware vCenter】一次性说清楚 vCenter Server 的 CLI 部署方式。
VMware vCenter Server 是 VMware vSphere 解决方案的核心组件,用于管理多个 ESXi 主机并实现更多高级功能特性(如 HA、DRS 以及 FT 等),相信大家已经非常熟悉了。对于 vCenter Server 的安装和部署,可能大部分人会选择使用 GUI 方式部署
【VMware vCenter】一次性说清楚 vCenter Server 的 CLI 部署方式。 【VMware vCenter】一次性说清楚 vCenter Server 的 CLI 部署方式。 【VMware vCenter】一次性说清楚 vCenter Server 的 CLI 部署方式。
软件测试基础理论
软件测试基础理论 测试理论 ⭐️测试的八大原则 所有的测试都应该追溯到用户的需求 测试应当尽早介入,将“尽早和不断的测试”写入座右铭! 在实际当中,开发进行的同时测试可以去编写测试用例文档 开发是按模块开发:每个模块开发好了之后就可以进行测试了 测试的工作应该由专门的测试人员完成 避免自己测试自己写
软件测试基础理论 软件测试基础理论 软件测试基础理论
.NET 8 + Blazor 多租户、模块化、DDD框架、开箱即用
前言 基于 .NET 8 的开源项目,主要使用 WebAPI + Blazor 支持多租户和模块化设计,DDD构建。可以帮助我们轻松地搭建起一个功能完善的Web应用程序。除了帮助你快速构建应用程序之外,项目也可以当做学习资料。我们可以从中了解到多租户、CQRS、DDD架构、云部署、Docker容器化
.NET 8 + Blazor 多租户、模块化、DDD框架、开箱即用 .NET 8 + Blazor 多租户、模块化、DDD框架、开箱即用 .NET 8 + Blazor 多租户、模块化、DDD框架、开箱即用
IntelliJ IDEA 2024.2 发布:Spring Data JPA即时查询、自动补全cron表达式
今早看到,IntelliJ IDEA 2024.2 发布的邮件提示,看了一眼这个版本更新的新特性真的太适合我了!也许这些能力对关注DD的小伙伴也有帮助,所以搞篇博客介绍和推荐一下。下面就来一起看看这个版本中推出的几个强大新特性。 Spring Data JPA 的即时查询 在2024.2 Ultim
IntelliJ IDEA 2024.2 发布:Spring Data JPA即时查询、自动补全cron表达式 IntelliJ IDEA 2024.2 发布:Spring Data JPA即时查询、自动补全cron表达式 IntelliJ IDEA 2024.2 发布:Spring Data JPA即时查询、自动补全cron表达式