如何处理微服务之间的通信和数据一致性?

news2024/12/28 20:25:22


✨✨祝屏幕前的兄弟姐妹们每天都有好运相伴左右,一定要天天开心哦!✨✨ 
🎈🎈作者主页: 喔的嘛呀🎈🎈

目录

引言

一、微服务通信

1、同步通信:HTTP

1.1.同步通信示例代码:

1.2. 发送HTTP POST请求并获取响应:

2、异步通信

使用消息队列实现异步通信的示例代码:

二、数据一致性

1. 分布式事务

2. 数据同步

3. 幂等性

三、示例

步骤一:创建商品服务和用户服务

商品服务(Product Service)代码示例:

用户服务(User Service)代码示例:

步骤二:引入Spring Cloud分布式事务支持

步骤三:创建订单服务(Order Service)

订单服务(Order Service)代码示例:

注意事项:

总结

目录

引言

一、微服务通信​​​​​​​

1、同步通信:HTTP

1.1.同步通信示例代码:

1.2. 发送HTTP POST请求并获取响应:

2、异步通信

使用消息队列实现异步通信的示例代码:

二、数据一致性

1. 分布式事务

2. 数据同步

3. 幂等性

三、示例

步骤一:创建商品服务和用户服务

商品服务(Product Service)代码示例:

用户服务(User Service)代码示例:

步骤二:引入Spring Cloud分布式事务支持

步骤三:创建订单服务(Order Service)

订单服务(Order Service)代码示例:

注意事项:

总结



引言

在微服务架构中,处理微服务之间的通信和数据一致性是非常重要的。通信需要高效可靠,数据一致性要求保证在分布式环境下的可靠性和正确性。下面我们将详细介绍如何处理微服务之间的通信和数据一致性。

一、微服务通信

在微服务架构中,微服务之间的通信可以采用不同的方式,包括同步和异步通信。常用的通信方式包括HTTP和消息队列等。下面将详细介绍这些通信方式,并提供相应的代码示例。

1、同步通信:HTTP

同步通信是指请求方发送请求后,一直等待直到接收到响应。这种通信方式简单直接,但容易导致调用方和被调用方之间的耦合度高,服务雪崩风险大。

在微服务架构中,同步通信是指客户端发送请求后等待服务端响应的通信方式。常用的同步通信方式包括使用HTTP协议。下面将详细介绍如何使用Java的HttpURLConnection实现同步通信,并附上代码示例。

1.1.同步通信示例代码:

 发送HTTP GET请求并获取响应:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class SyncHttpClient {
    public static void main(String[] args) {
        try {
            // 创建URL对象
            URL url = new URL("http://localhost:8080/api/example");
            // 创建HttpURLConnection对象
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 设置请求方法为GET
            conn.setRequestMethod("GET");
            // 设置连接超时时间为5秒
            conn.setConnectTimeout(5000);
            // 设置读取超时时间为5秒
            conn.setReadTimeout(5000);

            // 发起请求并获取响应码
            int responseCode = conn.getResponseCode();
            System.out.println("Response Code: " + responseCode);

            // 读取响应内容
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String inputLine;
            StringBuilder response = new StringBuilder();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();

            // 打印响应内容
            System.out.println("Response Content: " + response.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,我们使用HttpURLConnection对象创建了一个GET请求,并设置了连接超时时间和读取超时时间。然后我们发起了请求,并获取了响应码和响应内容,最后打印出来。

1.2. 发送HTTP POST请求并获取响应:

import java.io.DataOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class SyncHttpClient {
    public static void main(String[] args) {
        try {
            // 创建URL对象
            URL url = new URL("http://localhost:8080/api/example");
            // 创建HttpURLConnection对象
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 设置请求方法为POST
            conn.setRequestMethod("POST");
            // 设置连接超时时间为5秒
            conn.setConnectTimeout(5000);
            // 设置读取超时时间为5秒
            conn.setReadTimeout(5000);
            // 允许输入输出流
            conn.setDoOutput(true);

            // 发送POST请求
            DataOutputStream out = new DataOutputStream(conn.getOutputStream());
            out.writeBytes("key1=value1&key2=value2");
            out.flush();
            out.close();

            // 获取响应码
            int responseCode = conn.getResponseCode();
            System.out.println("Response Code: " + responseCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

以上就是关于使用Java的HttpURLConnection实现同步通信的示例代码。这些代码可以帮助你理解如何在Java中进行同步通信,并根据需要发送GET或POST请求并获取响应。

2、异步通信

异步通信是指客户端发送请求后不需要等待响应,而是继续执行后续操作,待服务端处理完请求后发送响应。在微服务架构中,常用的异步通信方式包括使用消息队列。

使用消息队列实现异步通信的示例代码:

// 消息生产者发送消息的代码
@Component
public class MessageProducer {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMessage(String message) {
        rabbitTemplate.convertAndSend("my-exchange", "my-routing-key", message);
    }
}

// 消息消费者处理消息的代码
@Component
public class MessageConsumer {
    @RabbitListener(queues = "my-queue")
    public void handleMessage(String message) {
        System.out.println("Received message: " + message);
    }
}

以上是关于微服务通信的示例代码,其中包括了同步通信(HTTP)和异步通信(消息队列)。这些通信方式可以根据具体场景选择使用,以实现不同的功能需求。

二、数据一致性

在分布式系统中,确保数据一致性是至关重要的。下面详细介绍分布式系统中数据一致性的相关问题和解决方案。

1. 分布式事务

分布式事务是指涉及多个数据库或服务的事务操作。在分布式环境中,保证事务的原子性、一致性、隔离性和持久性是具有挑战性的。常用的分布式事务解决方案包括:

  • 2PC(Two-Phase Commit):两阶段提交协议,通过协调器协调所有参与者,确保所有参与者要么全部提交,要么全部回滚。但是2PC存在单点故障和阻塞的问题。
  • TCC(Try-Confirm-Cancel):Try阶段尝试执行操作,Confirm阶段确认执行操作,Cancel阶段取消执行操作。TCC通过业务逻辑实现分布式事务,适用于高并发场景。
  • Saga模式:一种长事务的模式,通过将一个大事务拆分为多个小事务,并通过补偿操作实现事务的最终一致性。

2. 数据同步

数据同步是保持不同数据副本之间数据一致性的过程。常见的数据同步方式包括:

  • 主从复制:主数据库向从数据库定期发送更新数据的操作,从而保持数据一致性。
  • 发布-订阅模式:通过消息队列实现数据的发布和订阅,实现数据的异步传输和处理。

3. 幂等性

幂等性是指对同一操作的多次执行具有相同的效果。在分布式系统中,保证接口的幂等性是确保数据一致性的重要手段。常见的幂等性实现方式包括:

  • 接口设计幂等性:通过接口设计保证同一请求的多次执行不会产生重复的效果。
  • 唯一请求标识:每个请求都携带唯一标识,服务端通过标识判断请求的幂等性。

综上所述,分布式系统中数据一致性是一个复杂而重要的问题,需要综合考虑业务需求和系统架构,选择合适的解决方案来保证数据的一致性。

在分布式系统中,数据一致性是确保不同节点上的数据在时间上保持一致的重要性。在处理分布式系统中的数据一致性时,有几个关键概念和技术需要考虑:

  1. CAP定理:CAP定理指出,一个分布式系统不可能同时满足一致性(Consistency)、可用性(Availability)和分区容忍性(Partition Tolerance)这三个特性,只能满足其中两个。在实际系统设计中需要根据实际需求权衡这三个特性。

  2. ACID和BASE:ACID是传统数据库事务的特性,包括原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。而BASE是基本可用(Basically Available)、软状态(Soft state)和最终一致性(Eventual Consistency)的缩写,是NoSQL数据库的设计理念。

  3. 一致性模型:在分布式系统中,常用的一致性模型包括强一致性、弱一致性和最终一致性。强一致性要求数据写入后立即对所有节点可见,而最终一致性允许在一段时间内出现不一致的情况,但最终会达到一致状态。

  4. 分布式事务:分布式事务是指涉及多个参与者的事务操作。常用的分布式事务解决方案包括基于消息队列的最终一致性方案、TCC(Try-Confirm-Cancel)等。

  5. 数据同步:数据同步是保持分布式系统中数据副本之间一致性的过程。常用的数据同步方式包括主从复制和发布-订阅模式。

  6. 幂等性:幂等性是指对同一操作的多次执行具有相同效果。在分布式系统中,保证接口的幂等性是确保数据一致性的重要手段。

综上所述,数据一致性在分布式系统中是一个复杂而重要的问题,需要根据具体的业务需求和系统架构选择合适的一致性模型和技术方案。

三、示例

电商系统中,确保下单成功时同时扣减商品库存和用户余额是一个常见的场景,可以使用分布式事务来保证数据一致性。下面是一个简单的示例,使用Spring Boot和Spring Cloud的分布式事务管理来实现这一功能。

步骤一:创建商品服务和用户服务

首先,我们需要创建两个微服务,一个是商品服务,负责管理商品库存;另一个是用户服务,负责管理用户余额。这里使用Spring Boot创建两个简单的RESTful服务。

商品服务(Product Service)代码示例:
@RestController
public class ProductController {

    private int productStock = 100; // 初始商品库存为100

    @PostMapping("/product/decreaseStock")
    public boolean decreaseStock(@RequestParam int quantity) {
        if (productStock >= quantity) {
            productStock -= quantity;
            return true;
        } else {
            return false;
        }
    }

    @GetMapping("/product/stock")
    public int getStock() {
        return productStock;
    }
}
用户服务(User Service)代码示例:
@RestController
public class UserController {

    private int userBalance = 1000; // 初始用户余额为1000

    @PostMapping("/user/decreaseBalance")
    public boolean decreaseBalance(@RequestParam int amount) {
        if (userBalance >= amount) {
            userBalance -= amount;
            return true;
        } else {
            return false;
        }
    }

    @GetMapping("/user/balance")
    public int getBalance() {
        return userBalance;
    }
}

步骤二:引入Spring Cloud分布式事务支持

在每个服务的pom.xml文件中添加Spring Cloud的依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

并在各自的配置文件中配置Seata分布式事务的相关信息。

步骤三:创建订单服务(Order Service)

订单服务负责处理下单逻辑,并在下单成功时调用商品服务和用户服务接口来扣减库存和余额。

订单服务(Order Service)代码示例:
@RestController
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @PostMapping("/order")
    public boolean createOrder(@RequestParam int productId, @RequestParam int quantity, @RequestParam int userId, @RequestParam int amount) {
        // 调用商品服务扣减库存
        boolean decreaseStockResult = restTemplate.postForObject("http://product-service/product/decreaseStock?quantity=" + quantity, null, Boolean.class);
        if (!decreaseStockResult) {
            throw new RuntimeException("Decrease stock failed");
        }

        // 调用用户服务扣减余额
        boolean decreaseBalanceResult = restTemplate.postForObject("http://user-service/user/decreaseBalance?amount=" + amount, null, Boolean.class);
        if (!decreaseBalanceResult) {
            // 如果扣减余额失败,需要回滚商品服务扣减的库存
            restTemplate.postForObject("http://product-service/product/increaseStock?quantity=" + quantity, null, Boolean.class);
            throw new RuntimeException("Decrease balance failed");
        }

        // 创建订单成功
        return true;
    }
}

在订单服务中,我们使用RestTemplate来调用商品服务和用户服务的接口。如果任何一个扣减操作失败,就会抛出异常并回滚之前的操作,保证数据的一致性。

注意事项:

  1. 在实际项目中,应考虑分布式事务的性能和并发情况,合理设计事务的范围和边界。
  2. 应注意分布式事务可能存在的问题,如分布式事务协调器单点故障、性能瓶颈等。
  3. 可以考虑使用分布式事务中间件如Seata、TCC框架等来简化分布式事务管理。

总结

通过使用消息队列实现微服务之间的异步通信,以及使用分布式事务保证数据的一致性,我们可以有效地处理微服务架构中的通信和数据一致性问题。这样的架构具有高可靠性、可扩展性和灵活性,适用于大型复杂系统

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1490748.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Q-Align Teaching LMMs for Visual Scoring via Discrete Text-Defined Levels

Q-Align: Teaching LMMs for Visual Scoring via Discrete Text-Defined Levels TL; DR&#xff1a;教会多模态大模型用文本等级评价词&#xff08;如 Good、Bad、Excellent 等&#xff09;来评估视觉质量分。 图像美学质量评估是一个小方向&#xff0c;但是实际业务中很有用&…

Jenkins 将shell脚本启动方式修改为bash

platform"arm x86" if [[ "$platform" ~ "arm" ]] thenecho "arm" fi最近在调试Jenkins实现的一些功能&#xff0c;发现在本地可以运行的脚本内容到了Jenkins里面就没办法运行了&#xff0c;不是提示unexpected operator就是提示[[ : …

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:拖拽控制)

设置组件是否可以响应拖拽事件。 说明&#xff1a; 从API Version 10开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 ArkUI框架对以下组件实现了默认的拖拽能力&#xff0c;支持对数据的拖出或拖入响应&#xff0c;开发者只需要将这些组件…

商家转账到零钱申请时间要多久

商家转账到零钱是什么&#xff1f; 【商家转账到零钱】功能整合了微信支付之前的【企业付款到零钱】【批量转账到零钱】功能&#xff0c;支持批量对外转账&#xff0c;对有批量对用户付款需求的应用场景更友好&#xff0c;操作便捷。如果你的应用场景是单付款场景的话&#xf…

运维打工人,周末兼职送外卖的一天

运维打工人&#xff0c;周末兼职送外卖的一天 在那个不经意的周末&#xff0c;我决定尝试一份新的工作——为美团外卖做兼职配送员。这份工作对于一向规律生活的我来说&#xff0c;既是突破也是挑战。 早晨&#xff0c;空气中带着几分凉意和宁静。准备好出发时&#xff0c;线…

如何做代币分析:以 CRO 币为例

作者&#xff1a;lesleyfootprint.network 编译&#xff1a;Mingfootprint.network 数据源&#xff1a;CRO Token Dashboard &#xff08;仅包括以太坊数据&#xff09; 在加密货币和数字资产领域&#xff0c;代币分析起着至关重要的作用。代币分析指的是深入研究与代币相关…

Unity编辑器功能Inspector快捷自动填充数据

我们有时候可能需要在面板增加一些引用&#xff0c;可能添加脚本后要手动拖动&#xff0c;这样如果有大量的脚本拖动也是不小的工作量 实例 例如&#xff1a;我的脚本需要添加一个Bone的列表&#xff0c;一个个拖动很麻烦。 实现脚本 我们可以用这样的脚本来实现。 public…

鼠标右键没有git bash here,右键添加git bash here并增加图标

突然发现自己鼠标右键没有git bash here&#xff0c;或者安装之后就没有git bash here。后面那种情况多半是没有默认装在C盘。我们装在其他盘的时候就需要自己去配置。git gui目前用不上&#xff0c;这里只讲git bash here。网上一堆教程&#xff0c;说法不同大多不能用要么就很…

Vue router文件中本地路由配置使用i18n【解决tab名称出现undefined,导致i18n没有实现问题】

问题 点击按钮 跳转详情页后 tab名称出现错误&#xff0c;报 undefined ## 需求 点击工单详情按钮&#xff0c;跳转详情页面&#xff08;新页面&#xff09;&#xff0c;新页面tab栏名称 还是为 工单出库&#xff0c;但要求工单出库文字配置为多语言&#xff0c;使用i18n来配置…

SPC 之 I-MR 控制图

概述 1924 年&#xff0c;美国的休哈特博士应用统计数学理论将 3Sigma 原理运用于生产过程中&#xff0c;并发表了 著名的“控制图法”&#xff0c;对产品特性和过程变量进行控制&#xff0c;开启了统计过程控制新时代。 什么是控制图 控制图指示过程何时不受控制&#xff…

中医舌苔笔记

舌诊时按照舌尖-舌中-舌根-舌侧的顺序进行观察。 先看舌体再看舌苔&#xff0c;30秒左右。 如果一次望舌判断不清&#xff0c;可令病人休息3~5分钟后&#xff0c;重新观察一次 舌诊脏腑部位分属图 舌体 胖嫩而边有齿痕为气虚、阳虚。 薄白而润为风寒&#xff1b; 薄白而燥…

RabbitMQ如何实现延迟消息?

RabbitMQ中是可以实现延迟消息的&#xff0c;一般有两种方式&#xff0c;分别是通过死信队列以及通过延迟消息插件来实现。 扩展&#xff1a; 死信队列 当rabbitMQ中的一条正常的消息&#xff0c;因为过了存活时间&#xff08;TTL过期&#xff09;&#xff0c;队列长度超限&a…

【论文精读】Attention Bottlenecks for Multimodal Fusion 视频分类任务

本文并非逐句翻译&#xff0c;添加个人理解与疑惑&#xff0c;如有需要&#xff0c;请自行阅读原文。 Attention Bottlenecks for Multimodal Fusion 多模态融合的注意力瓶颈 会议&#xff1a;NIPS2021 Benchmark&#xff1a;Audioset、Epic Kitchens和VGGSound等 Backbone&…

白酒:原料的预处理技术对白酒品质的影响

在豪迈白酒的酿造过程中&#xff0c;原料的预处理技术对白酒的品质起着至关重要的作用。预处理技术包括原料的选择、清洗、破碎、润料等环节&#xff0c;这些环节的处理方式直接影响着白酒的口感、香气和品质。云仓酒庄在原料的预处理技术方面进行了深入研究和探索&#xff0c;…

图扑数字孪生水电站,水力发电可视化运维

自水轮机的早期发明被用于农业灌溉&#xff0c;到 18 世纪末期的工业革命促使水轮机技术的改良&#xff0c;再到 19 世纪末水利发电的崛起&#xff0c;直至今日&#xff0c;智慧水电站数字孪生技术正处于蓬勃发展之中。通过整合物联网、大数据、云计算等现代信息技术&#xff0…

Python图像处理【21】基于卷积神经网络增强微光图像

基于卷积神经网络增强微光图像 0. 前言1. MBLLEN 网络架构2. 增强微光图像小结系列链接 0. 前言 在本节中&#xff0c;我们将学习如何基于预训练的深度学习模型执行微光/夜间图像增强。由于难以同时处理包括亮度、对比度、伪影和噪声在内的所有因素&#xff0c;因此微光图像增…

vscode设置打开浏览器

安装这个插件 Open Browser Preview

linemap | 这样好看的山峦地图真的可以快速绘制啦~~

上一次介绍了Python绘制svg的优秀可视化库Pygal&#xff0c;今天我们介绍一下一个优秀的R地图可视化绘制包-linemap包&#xff0c;顾名思义&#xff0c;该包是是为了绘制由线组成的地图&#xff0c;其官网如下&#xff1a;https://github.com/rCarto/linemap。该包主要拥有两个…

鸿蒙实战开发:【SIM卡管理】

概述 本示例展示了电话服务中SIM卡相关功能&#xff0c;包含SIM卡的服务提供商、ISO国家码、归属PLMN号信息&#xff0c;以及默认语音卡功能。 样例展示 基础信息 介绍 本示例使用sim相关接口&#xff0c;展示了电话服务中SIM卡相关功能&#xff0c;包含SIM卡的服务提供商、…

Android Studio Iguana | 2023.2.1版本

Android Gradle 插件和 Android Studio 兼容性 Android Studio 构建系统基于 Gradle&#xff0c;并且 Android Gradle 插件 (AGP) 添加了一些特定于构建 Android 应用程序的功能。下表列出了每个版本的 Android Studio 所需的 AGP 版本。 如果特定版本的 Android Studio 不支持…