”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 微服务系统中服务之间的通信方式

微服务系统中服务之间的通信方式

发布于2024-08-21
浏览:284

1. 同步通讯

同步通信涉及实时交互,其中一个服务向另一个服务发送请求并暂停其操作,直到收到响应。 REST API 和 gRPC 是用于促进此类通信的常用协议。

Ways of communication between services in a Microservice system

1.1 REST API

RESTful API(表述性状态传输)是微服务系统中服务相互通信最常用的方法之一。 REST 利用 HTTP/HTTPS 和 JSON 或 XML 格式进行数据交换。

通常,服务通过直接调用另一个服务的 API 来相互交互。

请求和响应示例:

GET /users/12345 HTTP/1.1
Host: api.userservice.com
Accept: application/json
Authorization: Bearer your-access-token

{
  "userId": "12345",
  "name": "Michel J",
  "email": "[email protected]",
  "address": "Mountain View, Santa Clara, California"
}

源代码示例

import org.springframework.web.client.RestTemplate;
import org.springframework.http.ResponseEntity;

public class OrderService {

    private final RestTemplate restTemplate = new RestTemplate();
    private final String userServiceUrl = "https://api.userservice.com/users/";

    public User getUserById(String userId) {
        String url = userServiceUrl   userId;
        ResponseEntity response = restTemplate.getForEntity(url, User.class);
        return response.getBody();
    }
}

优点:

易于部署并与各种语言和工具集成。

能够轻松使用测试和监控工具。

缺点:

由于其同步特性,对于高速要求可能效率不高。

在处理网络错误或断开连接时可能会遇到困难。

1.2 通用RPC

gRPC,全称Google Remote procedure Call,是一个高性能、开源的通用RPC框架。它利用 HTTP/2 进行高效的数据传输,并且通常依赖于协议缓冲区(一种语言中立、平台中立、可扩展的机制,用于序列化结构化数据)来定义发送和接收的数据的结构。

示例,协议缓冲区的定义

syntax = "proto3";

package userservice;

// Define message User
message User {
    string userId = 1;
    string name = 2;
    string email = 3;
    string address = 4;
}

// Define service UserService
service UserService {
    rpc GetUserById (UserIdRequest) returns (User);
}

// Define message UserIdRequest
message UserIdRequest {
    string userId = 1;
}

对于用户管理服务,您应该实现一个遵循 .proto 文件中提供的服务定义的 gRPC 服务器。这包括创建必要的服务器端逻辑来处理传入的 gRPC 请求并生成适当的响应。

import io.grpc.stub.StreamObserver;
import userservice.User;
import userservice.UserIdRequest;
import userservice.UserServiceGrpc;

public class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase {

    @Override
    public void getUserById(UserIdRequest request, StreamObserver responseObserver) {
        // Assuming you have a database to retrieve user information.
        User user = User.newBuilder()
                .setUserId(request.getUserId())
                .setName("Michel J")
                .setEmail("[email protected]")
                .setAddress("Mountain View, Santa Clara, California")
                .build();

        responseObserver.onNext(user);
        responseObserver.onCompleted();
    }
}

import io.grpc.Server;
import io.grpc.ServerBuilder;

public class UserServer {
    public static void main(String[] args) throws Exception {
        Server server = ServerBuilder.forPort(9090)
                .addService(new UserServiceImpl())
                .build()
                .start();

        System.out.println("Server started on port 9090");
        server.awaitTermination();
    }
}

优点:

由于使用了 HTTP/2 和 Protocol Buffers,因此具有高性能和带宽效率。

支持多种编程语言,具有良好的扩展性。

缺点:

如果服务不支持 gRPC,则需要转换层。

部署和管理可能更加复杂。

2. 异步通信

异步通信是指一个服务向另一个服务发送请求而不阻塞其自身操作以等待回复的过程。这通常是通过消息队列或发布/订阅系统来实现的。

Ways of communication between services in a Microservice system

1.消息队列

消息队列系统,如 RabbitMQ 和 Apache ActiveMQ,促进服务之间的异步通信。

优点:

提高可扩展性和容错能力:系统可以更好地处理增加的工作负载并且不易出现故障。

减少服务负载:通过解耦请求发送和接收,主要服务可以专注于处理任务,而不会被不断的请求淹没。

缺点:

可能需要额外的工作来管理和维护:基于队列的系统可能更复杂,并且需要更多的资源来运行。

处理排序和确保消息传递的困难:确保以正确的顺序处理请求并且不丢失消息可能是一项技术挑战。

2.2.发布/订阅系统

Pub/Sub(发布/订阅)系统,例如 Apache Kafka 或 Google Pub/Sub,允许服务发布消息和订阅主题。

优点:

支持大规模和高吞吐量的数据流。

减少服务之间的依赖关系。

缺点:

需要更复杂的层来管理和监控主题和消息。

处理消息的排序和可靠性问题可能具有挑战性。”

如果您有兴趣,可以阅读我之前关于 pub/sub 主题的文章。

消息代理中的死信队列第 1 部分

消息代理中的死信队列第 2 部分

消息代理系统内的一致性和可靠性问题

3. 事件驱动的沟通

事件驱动的通信是指服务发出事件并且其他服务根据这些事件做出响应或采取操作。

3.1.同步事件

当服务发出事件并等待其他服务的响应时,就会发生同步事件。

优点:

易于控制和监控事件处理过程。

缺点:

如果响应服务缓慢或遇到错误,可能会导致瓶颈

3.2.异步事件

当服务发出事件并且不需要等待立即响应时,就会发生异步事件。

优点:

减少等待时间并提高可扩展性。

帮助服务更加独立运行并减少相互依赖。

缺点:

需要额外的机制来确保正确及时地处理事件。

难以确保顺序和处理重复事件。

4. 结论

微服务系统中服务间通信方式的选择取决于性能需求、可靠性、系统复杂度等因素。每种方法都有自己的优点和缺点,了解这些方法将帮助您构建更高效、更灵活的微服务系统。仔细考虑您系统的要求,选择最合适的通信方式。

版本声明 本文转载于:https://dev.to/anh_trntun_4732cf3d299/ways-of-communication-between-services-in-a-microservice-system-597p?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 定制Seaborn图表尺寸,完美打印输出
    定制Seaborn图表尺寸,完美打印输出
    在海洋绘图中自定义图形大小用于打印 1。使用seaborn set_theme方法: RC参数允许您使用字典以英寸为单位指定所需的图形大小。利用matplotlib rcparams: = 11.7,8.27 此方法允许直接操纵matplotlib的配置来设置图形大小。 附加说明:探索seabo...
    编程 发布于2025-04-12
  • 如何使用PHP将斑点(图像)正确插入MySQL?
    如何使用PHP将斑点(图像)正确插入MySQL?
    essue VALUES('$this->image_id','file_get_contents($tmp_image)')";This code builds a string in PHP, but the function call ...
    编程 发布于2025-04-12
  • 如何从Google API中检索最新的jQuery库?
    如何从Google API中检索最新的jQuery库?
    从Google APIS 问题中提供的jQuery URL是版本1.2.6。对于检索最新版本,以前有一种使用特定版本编号的替代方法,它是使用以下语法:获取最新版本:未压缩)While these legacy URLs still remain in use, it is recommended ...
    编程 发布于2025-04-12
  • 如何在Java中执行命令提示命令,包括目录更改,包括目录更改?
    如何在Java中执行命令提示命令,包括目录更改,包括目录更改?
    在java 通过Java通过Java运行命令命令可能很具有挑战性。尽管您可能会找到打开命令提示符的代码段,但他们通常缺乏更改目录并执行其他命令的能力。 solution:使用Java使用Java,使用processBuilder。这种方法允许您:启动一个过程,然后将其标准错误重定向到其标准输出。...
    编程 发布于2025-04-12
  • 如何在Java中正确显示“ DD/MM/YYYY HH:MM:SS.SS”格式的当前日期和时间?
    如何在Java中正确显示“ DD/MM/YYYY HH:MM:SS.SS”格式的当前日期和时间?
    如何在“ dd/mm/yyyy hh:mm:mm:ss.ss”格式“ gormat 解决方案: args)抛出异常{ 日历cal = calendar.getInstance(); SimpleDateFormat SDF =新的SimpleDateFormat(“...
    编程 发布于2025-04-12
  • 如何克服PHP的功能重新定义限制?
    如何克服PHP的功能重新定义限制?
    克服PHP的函数重新定义限制 但是,PHP工具腰带中有一个隐藏的宝石:runkit扩展。它使您能够灵活地重新定义函数。 runkit_function_renction_rename() runkit_function_redefine() //重新定义'this'以返回“新和改...
    编程 发布于2025-04-12
  • 如何简化PHP中的JSON解析以获取多维阵列?
    如何简化PHP中的JSON解析以获取多维阵列?
    php 试图在PHP中解析JSON数据的JSON可能具有挑战性,尤其是在处理多维数组时。要简化过程,建议将JSON作为数组而不是对象解析。执行此操作,将JSON_DECODE函数与第二个参数设置为true:[&&&&& && &&&&& json = JSON = JSON_DECODE($ j...
    编程 发布于2025-04-12
  • 如何使用Python有效地以相反顺序读取大型文件?
    如何使用Python有效地以相反顺序读取大型文件?
    在python 中,如果您使用一个大文件,并且需要从最后一行读取其内容,则在第一行到第一行,Python的内置功能可能不合适。这是解决此任务的有效解决方案:反向行读取器生成器 == ord('\ n'): 缓冲区=缓冲区[:-1] ...
    编程 发布于2025-04-12
  • 如何从PHP中的Unicode字符串中有效地产生对URL友好的sl。
    如何从PHP中的Unicode字符串中有效地产生对URL友好的sl。
    为有效的slug生成首先,该函数用指定的分隔符替换所有非字母或数字字符。此步骤可确保slug遵守URL惯例。随后,它采用ICONV函数将文本简化为us-ascii兼容格式,从而允许更广泛的字符集合兼容性。接下来,该函数使用正则表达式删除了不需要的字符,例如特殊字符和空格。此步骤可确保slug仅包含...
    编程 发布于2025-04-12
  • 使用JavaScript和jQuery处理HTML时如何解决未定义元素问题
    使用JavaScript和jQuery处理HTML时如何解决未定义元素问题
    尝试使用javascript(JS)和JQUERES的录制时,请访问html元素时,您可能会遇到sistating的问题,而沮丧的问题是 不明确的。这个令人困惑的错误可能源于代码结构中的常见监督。在提供的代码片段中理解错误,脚本文件(jQuery和您的脚本)位于HTML文档的部分中。结果,JS代码...
    编程 发布于2025-04-12
  • Java开发者如何保护数据库凭证免受反编译?
    Java开发者如何保护数据库凭证免受反编译?
    在java 在单独的配置文件保护数据库凭证的最有效方法中存储凭据是将它们存储在单独的配置文件中。该文件可以在运行时加载,从而使登录数据从编译的二进制文件中远离。使用prevereness class import java.util.prefs.preferences; 公共类示例{ 首选项...
    编程 发布于2025-04-12
  • 标准迭代器范围为何采用半开区间\[begin, end)而非闭区间\[begin, end\]?
    标准迭代器范围为何采用半开区间\[begin, end)而非闭区间\[begin, end\]?
    为什么标准迭代器范围[begin,end)而不是[begin,end]?对空序列的自然处理: 基于链范围的构造: the [begin,end,end)惯例,促进了基于多个嵌套范围的链接,而无需过时,并提升了一个杂货,并提醒了一个浪费的浪费,并提醒了一个浪费的杂物,并促进了基于型号的浪费。代码。在...
    编程 发布于2025-04-12
  • 为什么我在Silverlight Linq查询中获得“无法找到查询模式的实现”错误?
    为什么我在Silverlight Linq查询中获得“无法找到查询模式的实现”错误?
    查询模式实现缺失:解决“无法找到”错误在Silverlight应用程序中,尝试使用LINQ建立LINQ连接以错误而实现的数据库”,无法找到查询模式的实现。”当省略LINQ名称空间或查询类型缺少IEnumerable 实现时,通常会发生此错误。 解决问题来验证该类型的质量是至关重要的。在此特定实例中...
    编程 发布于2025-04-12
  • eval()vs. ast.literal_eval():对于用户输入,哪个Python函数更安全?
    eval()vs. ast.literal_eval():对于用户输入,哪个Python函数更安全?
    称量()和ast.literal_eval()中的Python Security 在使用用户输入时,必须优先确保安全性。强大的Python功能Eval()通常是作为潜在解决方案而出现的,但担心其潜在风险。 This article delves into the differences betwee...
    编程 发布于2025-04-12
  • 如何使用不同数量列的联合数据库表?
    如何使用不同数量列的联合数据库表?
    合并列数不同的表 当尝试合并列数不同的数据库表时,可能会遇到挑战。一种直接的方法是在列数较少的表中,为缺失的列追加空值。 例如,考虑两个表,表 A 和表 B,其中表 A 的列数多于表 B。为了合并这些表,同时处理表 B 中缺失的列,请按照以下步骤操作: 确定表 B 中缺失的列,并将它们添加到表的末...
    编程 发布于2025-04-12

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3