」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 微服務系統中服務之間的通訊方式

微服務系統中服務之間的通訊方式

發佈於2024-08-21
瀏覽:194

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]刪除
最新教學 更多>
  • 如何使用不同數量列的聯合數據庫表?
    如何使用不同數量列的聯合數據庫表?
    合併列數不同的表 當嘗試合併列數不同的數據庫表時,可能會遇到挑戰。一種直接的方法是在列數較少的表中,為缺失的列追加空值。 例如,考慮兩個表,表 A 和表 B,其中表 A 的列數多於表 B。為了合併這些表,同時處理表 B 中缺失的列,請按照以下步驟操作: 確定表 B 中缺失的列,並將它們添加到表的...
    程式設計 發佈於2025-07-20
  • 如何使用Python的請求和假用戶代理繞過網站塊?
    如何使用Python的請求和假用戶代理繞過網站塊?
    如何使用Python的請求模擬瀏覽器行為,以及偽造的用戶代理提供了一個用戶 - 代理標頭一個有效方法是提供有效的用戶式header,以提供有效的用戶 - 設置,該標題可以通過browser和Acterner Systems the equestersystermery和操作系統。通過模仿像Chro...
    程式設計 發佈於2025-07-20
  • 如何從PHP中的Unicode字符串中有效地產生對URL友好的sl。
    如何從PHP中的Unicode字符串中有效地產生對URL友好的sl。
    為有效的slug生成首先,該函數用指定的分隔符替換所有非字母或數字字符。此步驟可確保slug遵守URL慣例。隨後,它採用ICONV函數將文本簡化為us-ascii兼容格式,從而允許更廣泛的字符集合兼容性。 接下來,該函數使用正則表達式刪除了不需要的字符,例如特殊字符和空格。此步驟可確保slug僅包...
    程式設計 發佈於2025-07-20
  • 如何使用node-mysql在單個查詢中執行多個SQL語句?
    如何使用node-mysql在單個查詢中執行多個SQL語句?
    Multi-Statement Query Support in Node-MySQLIn Node.js, the question arises when executing multiple SQL statements in a single query using the node-mys...
    程式設計 發佈於2025-07-20
  • 哪種方法更有效地用於點 - 填點檢測:射線跟踪或matplotlib \的路徑contains_points?
    哪種方法更有效地用於點 - 填點檢測:射線跟踪或matplotlib \的路徑contains_points?
    在Python Matplotlib's path.contains_points FunctionMatplotlib's path.contains_points function employs a path object to represent the polygon.它...
    程式設計 發佈於2025-07-20
  • 如何在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-07-20
  • Java是否允許多種返回類型:仔細研究通用方法?
    Java是否允許多種返回類型:仔細研究通用方法?
    在Java中的多個返回類型:一種誤解類型:在Java編程中揭示,在Java編程中,Peculiar方法簽名可能會出現,可能會出現,使開發人員陷入困境,使開發人員陷入困境。 getResult(string s); ,其中foo是自定義類。該方法聲明似乎擁有兩種返回類型:列表和E。但這確實是如此嗎...
    程式設計 發佈於2025-07-20
  • 表單刷新後如何防止重複提交?
    表單刷新後如何防止重複提交?
    在Web開發中預防重複提交 在表格提交後刷新頁面時,遇到重複提交的問題是常見的。要解決這個問題,請考慮以下方法: 想像一下具有這樣的代碼段,看起來像這樣的代碼段:)){ //數據庫操作... 迴聲“操作完成”; 死(); } ? > ...
    程式設計 發佈於2025-07-20
  • C++中如何將獨占指針作為函數或構造函數參數傳遞?
    C++中如何將獨占指針作為函數或構造函數參數傳遞?
    在構造函數和函數中將唯一的指數管理為參數 unique pointers( unique_ptr [2啟示。通過值: base(std :: simelor_ptr n) :next(std :: move(n)){} 此方法將唯一指針的所有權轉移到函數/對象。指針的內容被移至功能中,在操作...
    程式設計 發佈於2025-07-19
  • PHP未來:適應與創新
    PHP未來:適應與創新
    PHP的未來將通過適應新技術趨勢和引入創新特性來實現:1)適應云計算、容器化和微服務架構,支持Docker和Kubernetes;2)引入JIT編譯器和枚舉類型,提升性能和數據處理效率;3)持續優化性能和推廣最佳實踐。 引言在編程世界中,PHP一直是網頁開發的中流砥柱。作為一個從1994年就開始發展...
    程式設計 發佈於2025-07-19
  • 為什麼使用固定定位時,為什麼具有100%網格板柱的網格超越身體?
    為什麼使用固定定位時,為什麼具有100%網格板柱的網格超越身體?
    網格超過身體,用100%grid-template-columns 為什麼在grid-template-colms中具有100%的顯示器,當位置設置為設置的位置時,grid-template-colly修復了? 問題: 考慮以下CSS和html: class =“ snippet-code”> ...
    程式設計 發佈於2025-07-19
  • Android如何向PHP服務器發送POST數據?
    Android如何向PHP服務器發送POST數據?
    在android apache httpclient(已棄用) httpclient httpclient = new defaulthttpclient(); httppost httppost = new httppost(“ http://www.yoursite.com/script.p...
    程式設計 發佈於2025-07-19
  • 為什麼我會收到MySQL錯誤#1089:錯誤的前綴密鑰?
    為什麼我會收到MySQL錯誤#1089:錯誤的前綴密鑰?
    mySQL錯誤#1089:錯誤的前綴鍵錯誤descript [#1089-不正確的前綴鍵在嘗試在表中創建一個prefix鍵時會出現。前綴鍵旨在索引字符串列的特定前綴長度長度,以便更快地搜索這些前綴。 理解prefix keys `這將在整個Movie_ID列上創建標準主鍵。主密鑰對於唯一識...
    程式設計 發佈於2025-07-19
  • CSS可以根據任何屬性值來定位HTML元素嗎?
    CSS可以根據任何屬性值來定位HTML元素嗎?
    靶向html元素,在CSS 中使用任何屬性值,在CSS中,可以基於特定屬性(如下所示)基於特定屬性的基於特定屬性的emants目標元素: 字體家庭:康斯拉斯(Consolas); } 但是,出現一個常見的問題:元素可以根據任何屬性值而定位嗎?本文探討了此主題。 的目標元素有任何任何屬性值,...
    程式設計 發佈於2025-07-19
  • 左連接為何在右表WHERE子句過濾時像內連接?
    左連接為何在右表WHERE子句過濾時像內連接?
    左JOIN CONUNDRUM:WITCHING小時在數據庫Wizard的領域中變成內在的加入很有趣,當將c.foobar條件放置在上面的Where子句中時,據說左聯接似乎會轉換為內部連接。僅當滿足A.Foo和C.Foobar標準時,才會返回結果。 為什麼要變形?關鍵在於其中的子句。當左聯接的右側...
    程式設計 發佈於2025-07-19

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3