自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

SpringBoot與Apache Thrift整合,解決不同編程語(yǔ)言的微服務(wù)通信問題

開發(fā) 架構(gòu)
Apache Thrift是一種跨語(yǔ)言的服務(wù)開發(fā)框架,由 Facebook 開發(fā)并捐贈(zèng)給 Apache 基金會(huì)。它允許開發(fā)者使用一種定義接口的方式,生成不同編程語(yǔ)言的代碼,從而實(shí)現(xiàn)不同語(yǔ)言之間的高效通信。

Apache Thrift是一種跨語(yǔ)言的服務(wù)開發(fā)框架,由 Facebook 開發(fā)并捐贈(zèng)給 Apache 基金會(huì)。它允許開發(fā)者使用一種定義接口的方式,生成不同編程語(yǔ)言的代碼,從而實(shí)現(xiàn)不同語(yǔ)言之間的高效通信。

哪些公司使用Apache Thrift?

Facebook:

  • Facebook 是 Apache Thrift 的最初開發(fā)者之一,廣泛用于其內(nèi)部的微服務(wù)通信。
  • 通過 Thrift,F(xiàn)acebook 能夠?qū)崿F(xiàn)不同語(yǔ)言之間的高效通信,并支持大規(guī)模的分布式系統(tǒng)。

Baidu:

  • Baidu 使用 Thrift 來(lái)構(gòu)建其搜索引擎和其他在線服務(wù)。
  • Thrift 的高效性和可擴(kuò)展性滿足了 Baidu 對(duì)高性能的需求。

Yahoo!:

  • Yahoo! 在其多個(gè)項(xiàng)目中使用 Thrift,包括搜索、廣告和其他核心服務(wù)。
  • Thrift 的可靠性和成熟度使其成為 Yahoo! 技術(shù)選擇的一部分。

Twitter:

  • Twitter 使用 Thrift 來(lái)處理大量的實(shí)時(shí)數(shù)據(jù)流和 API 請(qǐng)求。
  • Thrift 的跨語(yǔ)言特性和高效的序列化能力幫助 Twitter 構(gòu)建了高性能的服務(wù)架構(gòu)。

Airbnb:

  • Airbnb 利用 Thrift 實(shí)現(xiàn)其內(nèi)部服務(wù)間的通信,特別是在需要高吞吐量和低延遲的應(yīng)用場(chǎng)景中。
  • Thrift 的靈活性和可擴(kuò)展性使其成為 Airbnb 技術(shù)棧的重要組成部分。

Uber:

  • Uber 在其后端服務(wù)中廣泛使用 Thrift 來(lái)管理微服務(wù)之間的通信。
  • Thrift 的高效性和可靠性確保了 Uber 系統(tǒng)的穩(wěn)定運(yùn)行。

Yelp:

  • Yelp 使用 Thrift 來(lái)管理其評(píng)論、搜索和其他關(guān)鍵服務(wù)之間的通信。
  • Thrift 的高效性和靈活性提升了 Yelp 的整體性能和可靠性。

選擇Apache Thrift的好處

提高開發(fā)效率:

  • 自動(dòng)代碼生成:Thrift 編譯器根據(jù) IDL 文件自動(dòng)生成客戶端和服務(wù)端代碼,減少手動(dòng)編碼的工作量。
  • 一致的數(shù)據(jù)結(jié)構(gòu):通過統(tǒng)一的 IDL 文件定義數(shù)據(jù)結(jié)構(gòu),確保前后端數(shù)據(jù)的一致性。

性能優(yōu)化:

  • 低延遲:由于使用高效的二進(jìn)制協(xié)議和靈活的傳輸層,Thrift 在高性能場(chǎng)景下表現(xiàn)出色。
  • 資源利用率高:較少的 CPU 和內(nèi)存開銷,適合大規(guī)模部署。

跨語(yǔ)言支持:

  • 多語(yǔ)言兼容性:Thrift 支持多種編程語(yǔ)言(如 Java、C++、Python、PHP、Ruby、JavaScript、Node.js、Go、Delphi 等),這對(duì)于需要在不同語(yǔ)言之間進(jìn)行通信的分布式系統(tǒng)尤為重要。
  • 簡(jiǎn)化開發(fā):開發(fā)者可以使用自己熟悉的語(yǔ)言編寫服務(wù)端和客戶端代碼,而不需要擔(dān)心底層協(xié)議的復(fù)雜性。

高效的序列化和反序列化:

  • 二進(jìn)制協(xié)議:Thrift 使用高效的二進(jìn)制協(xié)議進(jìn)行數(shù)據(jù)傳輸,相比于 JSON 或 XML 更加緊湊,減少了帶寬消耗并提高了傳輸速度。
  • 多種協(xié)議選項(xiàng):除了默認(rèn)的二進(jìn)制協(xié)議外,Thrift 還提供了其他協(xié)議選項(xiàng)(如 TCompactProtocol、TJSONProtocol),可以根據(jù)具體需求選擇合適的協(xié)議。

靈活的傳輸層:

  • 多種傳輸方式:Thrift 支持多種傳輸層實(shí)現(xiàn),包括 TCP/IP、HTTP、內(nèi)存緩沖區(qū)等,可以輕松集成到現(xiàn)有的網(wǎng)絡(luò)架構(gòu)中。
  • 可擴(kuò)展性:易于擴(kuò)展和定制,可以根據(jù)項(xiàng)目需求調(diào)整傳輸層的行為。

安全性:

  • 加密傳輸:可以通過 SSL/TLS 加密傳輸層,保護(hù)數(shù)據(jù)安全。
  • 身份驗(yàn)證和授權(quán):結(jié)合其他安全機(jī)制,可以實(shí)現(xiàn)細(xì)粒度的身份驗(yàn)證和授權(quán)控制。

RPC 模式:

  • 同步和異步調(diào)用:Thrift 支持同步和異步 RPC 調(diào)用,適用于各種客戶端-服務(wù)器模型的應(yīng)用場(chǎng)景。
  • 簡(jiǎn)單易用:通過定義 IDL 文件,可以快速生成客戶端和服務(wù)端代碼,減少重復(fù)工作。

創(chuàng)建service.thrift文件

首先,在項(xiàng)目的根目錄下創(chuàng)建一個(gè)名為idl的文件夾,然后在其中創(chuàng)建service.thrift文件。

// idl/service.thrift
namespace java com.example.service
namespace go service

enum ErrorCode {
    SUCCESS = 0,          // 成功
    UNKNOWN_ERROR = 1,    // 未知錯(cuò)誤
    INVALID_REQUEST = 2,  // 請(qǐng)求無(wú)效
}

struct Request {
    1: required string message,  // 請(qǐng)求消息
}

struct Response {
    1: required ErrorCode errorCode,  // 錯(cuò)誤碼
    2: optional string errorMessage,  // 錯(cuò)誤信息
    3: optional string result,        // 結(jié)果
}

service MyService {
    Response processRequest(1: Request request) throws (1: Exception e),  // 處理請(qǐng)求的方法
}

使用Thrift編譯器生成Java和Go代碼

# 生成Java代碼
thrift --gen java -out src/main/java idl/service.thrift

# 生成Go代碼
thrift --gen go -out ./gen-go idl/service.thrift

之后,src/main/java目錄下會(huì)生成Java代碼,而在當(dāng)前目錄下生成gen-go文件夾,包含Go代碼。

Java代碼實(shí)操

<!-- pom.xml -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath/><!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Detailed demo project for Spring Boot and Apache Thrift integration</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
   <groupId>org.apache.thrift</groupId>
   <artifactId>libthrift</artifactId>
   <version>0.18.1</version>
</dependency>
<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
   <groupId>ch.qos.logback</groupId>
   <artifactId>logback-classic</artifactId>
</dependency>
<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
</plugins>
</build>
</project>

Thrift客戶端配置

// src/main/java/com/example/demo/config/ThriftConfig.java
package com.example.demo.config;

import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import com.example.service.MyService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Configuration
publicclass ThriftConfig {

    privatestaticfinal Logger logger = LoggerFactory.getLogger(ThriftConfig.class);

    @Bean
    public MyService.Client thriftClient() {
        // 創(chuàng)建Thrift傳輸層,連接到本地9090端口
        TTransport transport = new TSocket("localhost", 9090);
        try {
            // 打開傳輸層連接
            transport.open();
            // 返回MyService客戶端實(shí)例,使用二進(jìn)制協(xié)議
            returnnew MyService.Client(new TBinaryProtocol(transport));
        } catch (TTransportException e) {
            // 記錄錯(cuò)誤日志并拋出異常
            logger.error("Failed to open Thrift client connection", e);
            thrownew RuntimeException(e);
        }
    }
}

Controller

接收HTTP請(qǐng)求并通過Thrift客戶端調(diào)用遠(yuǎn)程服務(wù):

// src/main/java/com/example/demo/controller/ApiController.java
package com.example.demo.controller;

import com.example.service.Request;
import com.example.service.Response;
import com.example.service.MyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RestController
@RequestMapping("/api")
publicclass ApiController {

    privatestaticfinal Logger logger = LoggerFactory.getLogger(ApiController.class);

    privatefinal MyService.Client client;

    @Autowired
    public ApiController(MyService.Client client) {
        this.client = client;
    }

    @PostMapping("/process")
    public ResponseEntity<String> process(@RequestBody String message) {
        // 創(chuàng)建請(qǐng)求對(duì)象
        Request request = new Request(message);
        try {
            // 調(diào)用Thrift客戶端的processRequest方法
            Response response = client.processRequest(request);
            // 根據(jù)響應(yīng)結(jié)果返回不同的HTTP狀態(tài)碼和消息
            if (response.getErrorCode() == com.example.service.ErrorCode.SUCCESS) {
                returnnew ResponseEntity<>(response.getResult(), HttpStatus.OK);
            } else {
                logger.warn("Error processing request: {}", response.getErrorMessage());
                returnnew ResponseEntity<>(response.getErrorMessage(), HttpStatus.BAD_REQUEST);
            }
        } catch (Exception e) {
            // 捕獲異常并記錄錯(cuò)誤日志,返回內(nèi)部服務(wù)器錯(cuò)誤
            logger.error("Exception while processing request", e);
            returnnew ResponseEntity<>("Internal Server Error", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}

啟動(dòng)主類

// src/main/java/com/example/demo/DemoApplication.java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

實(shí)現(xiàn)Go的服務(wù)端

// gen-go/server.go
package main

import (
"context"
"fmt"
"log"
"net"

"github.com/apache/thrift/lib/go/thrift"
 service "path/to/gen-go/service"
)

type myHandler struct{}

// ProcessRequest 處理請(qǐng)求的方法
func (h *myHandler) ProcessRequest(ctx context.Context, request *service.Request) (*service.Response, error) {
 log.Printf("Received request: %s\n", request.Message)
iflen(request.Message) == 0 {
// 如果請(qǐng)求消息為空,返回INVALID_REQUEST錯(cuò)誤
return &service.Response{
   ErrorCode:    service.ErrorCode_INVALID_REQUEST,
   ErrorMessage: "Invalid request",
  }, nil
 }
// 返回成功響應(yīng)
return &service.Response{
  ErrorCode: service.ErrorCode_SUCCESS,
  Result:    fmt.Sprintf("Processed: %s", request.Message),
 }, nil
}

func main() {
 handler := &myHandler{}
 processor := service.NewMyServiceProcessor(handler)

// 創(chuàng)建Thrift服務(wù)器監(jiān)聽9090端口
 serverTransport, err := thrift.NewTServerSocket(":9090")
if err != nil {
  log.Fatalf("Error opening server socket: %s", err.Error())
 }

 tFactory := thrift.NewTFramedTransportFactory(thrift.NewTBufferedTransportFactory(8192))
 pFactory := thrift.NewTBinaryProtocolFactoryDefault()

// 創(chuàng)建Thrift簡(jiǎn)單服務(wù)器
 server := thrift.NewTSimpleServer4(processor, serverTransport, tFactory, pFactory)

 fmt.Println("Starting the simple server... on port 9090...")
 err = server.Serve()
if err != nil {
  log.Fatalf("Error starting Thrift server: %s", err.Error())
 }
}

運(yùn)行Go服務(wù)端

在終端中運(yùn)行Go服務(wù)端:

cd gen-go
go run server.go

測(cè)試

curl -X POST http://localhost:8080/api/process -H "Content-Type: text/plain" -d "Hello from Go!"

Respons:

Processed: Hello from Go!


責(zé)任編輯:武曉燕 來(lái)源: Java知識(shí)日歷
相關(guān)推薦

2025-03-12 08:42:28

2025-02-12 08:52:44

2012-01-18 10:41:29

ibmdw

2025-03-06 08:37:01

2025-03-06 10:59:24

2025-03-21 08:55:36

SpringOpenFeignAPI

2023-03-21 15:30:54

微服務(wù)通信架構(gòu)

2009-01-08 17:45:10

服務(wù)器WebLinux

2025-03-07 08:31:54

2025-03-11 09:28:34

2022-05-16 08:07:15

微服務(wù)容器通信

2022-01-16 23:10:40

語(yǔ)言服務(wù)注冊(cè)

2010-09-14 10:34:17

DIV CSS

2024-04-24 12:03:20

2022-08-08 13:55:47

通信設(shè)計(jì)模式微服務(wù)

2010-03-15 18:08:01

Python編程語(yǔ)言

2025-04-08 08:50:37

SpringCamel系統(tǒng)

2023-12-04 07:14:40

通信微服務(wù)

2025-03-26 01:55:00

Spring協(xié)議物聯(lián)網(wǎng)

2025-01-20 00:10:00

Go語(yǔ)言Kratos
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)