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


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

目录

引言

一、微服务通信

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框架等来简化分布式事务管理。

总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第四十九回 吴学究双掌连环计 宋公明三打祝家庄-Python与HTTP服务交互

吴用请戴宗从梁山请来铁面孔目裴宣、圣手书生萧让、通臂猿侯健、玉臂匠金大坚来帮忙。又告诫扈家庄的扈成&#xff0c;打起来不要去帮祝家庄。 孙立把旗号改成“登州兵马提辖孙立”&#xff0c;来祝家庄找峦廷玉&#xff0c;被热情接待。 第三天&#xff0c;宋江派小李广花荣…

Vue 路由功能

安装路由 npm install vue-router4创建路由器并导出 //导入vue-router import { createRouter, createWebHistory } from vue-router //导入组件 import LoginVue from /views/Login.vue import LayoutVue from /views/Layout.vue//定义路由关系 const routes [{ path: /log…

安卓玩机工具推荐----ADB状态读写分区 备份分区 恢复分区 查看分区号 工具操作解析

在以往玩机过程中。很多机型备份分区 备份固件需要借助adb手动指令或者第三方手机软件或者特定的一些工具来操作。有些朋友需要查看当前机型分区名称和对应的分区号。此类操作我前面的博文专门说过对应的adb指令。但有些界面化的工具比较方便简单。 相关分区同类博文&#xff…

WPF中如何设置自定义控件(二)

前一篇文章中简要讲解了圆角按钮、圆形按钮的使用,以及在windows.resource和app.resource中设置圆角或圆形按钮的样式。 这篇主要讲解Polygon(多边形)、Ellipse(椭圆)、Path(路径)这三个内容。 Polygon 我们先看一下的源码: namespace System.Windows.Shapes { pu…

性能问题分析排查思路之机器(3)

本文是性能问题分析排查思路的展开内容之一&#xff0c;第2篇&#xff0c;主要分为日志1期&#xff0c;机器4期、环境2期共7篇系列文章&#xff0c;本期是第三篇&#xff0c;讲机器&#xff08;硬件&#xff09;的网络方面的排查方法和最佳实践。 主要内容如图所示&#xff1a…

【短时交通流量预测】基于单层BP神经网络

课题名称&#xff1a;基于单层BP神经网络的短时交通流量预测 版本时间&#xff1a;2023-04-27 代码获取方式&#xff1a;QQ&#xff1a;491052175 或者 私聊博主获取 模型简介&#xff1a; 城市交通路网中交通路段上某时刻的交通流量与本路段前几个时段的交通流量有关&…

【计算机学习】-- 电脑的组装和外设

系列文章目录 文章目录 系列文章目录前言一、电脑的组装1.CPU2.主板3.显卡4.硬盘5.内存6.散热器7.电源8.机箱 二、电脑外设选用1.显示器2.鼠标3.键盘4.音响 总结 前言 一、电脑的组装 1.CPU 返回目录 认识CPU CPU&#xff0c;即中央处理器&#xff0c;负责电脑资源的调度安…

器件选型【电容,电阻篇】

电阻篇&#xff1a; 一句话先做总结&#xff1a;电阻的选型主要考虑额定电压和过流能力&#xff08;基于封装大小&#xff09; 电阻封装规格越大功率越大。但其功率也与温度有关&#xff0c;如果温度超过 70℃&#xff0c;其额定功率是会下降的。并且&#xff0c;R01005 和 R0…

#QT(串口助手-实现)

1.IDE&#xff1a;QTCreator 2.实验 3.记录 &#xff08;1&#xff09;在widget.h中加入必要文件&#xff0c;并且定义一个类指针 &#xff08;2&#xff09;如果有类的成员不知道怎么写&#xff0c;可以通过以下途径搜索 &#xff08;2&#xff09;设置串口数据 void Widget…

AI大全-通往AGI之路

背景 自从AI大模型出来之后&#xff0c;就有很多做资源整理的社区&#xff0c;整理学习资料&#xff0c;整理各种AI工具大全&#xff0c;我也整理过一段时间的最新AI的资讯&#xff0c;也曾尝试去弄一个AI的入口类的东西。但是最近看到一个在飞书上的分享&#xff0c;我觉得他…

IDEA自带 .http 请求工具文档

基础语法 请求格式 基础格式 Method Request-URI HTTP-Version Header-field: Header-valueRequest-Body其中&#xff0c;GET 请求可以省略 Method 不写&#xff1b;HTTP-Version 可以省略不写&#xff0c;默认使用 1.1 版本。 示例&#xff1a; GET https://www.baidu.co…

【Python】成功解决TypeError: list indices must be integers or slices, not float

【Python】成功解决TypeError: list indices must be integers or slices, not float &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&…

GIS之深度学习05:VisualStudio安装教程

在安装CUDA前&#xff0c;建议先安装VisualStudio&#xff0c;以防报错 VisualStudio安装步骤简单&#xff0c;但时间较长。。。。。。 正文开始&#xff1a; VisualStudio官网&#xff1a;Visual Studio: IDE and Code Editor for Software Developers and Teams 点击右上角…

【Docker】若依后端项目搭建

一 搭建局域网 1 # 搭建net-ry局域网&#xff0c;用于部署若依项目docker network create net-ry --subnet172.68.0.0/16 --gateway172.68.0.1 # 注意1&#xff1a;关闭宿主机的防火墙&#xff0c;否者容器内部的MySQL、redis等服务&#xff0c;外部访问不了&#xff1b;开放…

Stream流(Java)

目录 一、介绍 二、Stream流的使用步骤 三、Stream流常见的中间方法 四、Stream流常见的终结方法 一、介绍 Stream也叫Stream流&#xff0c;是JDK8开始新增的一套API&#xff0c;可以用于操作集合或者数组的数据。 优势&#xff1a;Stream流大量的结合了Lambda的语法风格来…

【PHP】PHP实现与硬件串口交互,向硬件设备发送指令数据(下)

目录 一、前言 二、 效果图 三、安装PHP扩展 四、添加模拟串口 五、PHP发送数据给硬件 PHP代码 前端代码 一、前言 上篇文章写到PHP怎么与硬件串口交互之实时接收硬件发送的数据&#xff0c;这里同样是以天平为例&#xff0c;介绍怎么向硬件设备发送数据&#xff0c; 需…

MySQL高可用性攻略:快速搭建MySQL主从复制集群 !

MySQL高可用性攻略&#xff1a;快速搭建MySQL主从复制集群 &#xff01; MySQL基础知识&#xff1a;介绍MySQL数据库的基本概念和常用命令&#xff0c;如何创建数据库、表、用户和权限管理等。 MySQL安装教程&#xff1a;Centos7 安装MySQL5.7.29详细安装手册 MySQL数据类型&…

【仿真基本功】【PyTorch】从头安装PyTorch(GPU版本)【2024/03/03更新】

【仿真基本功】【PyTorch】从头安装PyTorch&#xff08;GPU版本&#xff09;【2024/03/03更新】 安装步骤1. 安装Anaconda2. 查看显卡对CUDA版本的支持3. 查看PyTorch的安装需求4. 安装PyTorcha) 配置新环境b) 进入新环境c) 按照CUDA版本要求&#xff0c;必须小于等于显卡支持的…

初学arp欺骗

首先准备一台靶机这里用虚拟机的win10 已知网关与ip地址&#xff08;怕误伤&#xff09; 现在返回kali从头开始 首先探测自己的网关 然后扫内网存活的ip 发现有3台 用nmap扫一下是哪几台 成功发现我们虚拟机的ip 现在虚拟机可以正常访问网络 接下来直接开梭 ip网关 返回虚拟机…

# 自然语言处理: 第十三章P-tuing系列之P-tuning V1

项目地址: P-Tuning 论文地址: [2103.10385] GPT Understands, Too (arxiv.org) 理论基础 正如果上一节介绍LoRA(自然语言处理: 第十二章LoRA解读_lora自然英语处理-CSDN博客)一样,本次介绍的在21年由清华团推提出来的 P-Tuning V1系列也属于PEFT(参数高效微调系列)里的一种&…