Spring Cloud整合Thrift RPC(二) - spring-cloud-thrift-

前言

上一篇简单的阐述了 spring-cloud-thrift-starter 这个插件的配置和使用,并引入了一个 calculator的项目。本文将基于一个银行存款、取款的业务场景,给出一套 thrift在生产环境的应用案例。

首先设计如下几张简单的数据库表:银行( bank)、分支( branch)、银行卡( deposit_card)、客户( customer)、存款历史纪录( deposit_history)、取款历史纪录( withdraw_history)。

Spring Cloud整合Thrift RPC(二) - spring-cloud-thrift-

正文

项目结构如下,依然是由三个模块组成:

Spring Cloud整合Thrift RPC(二) - spring-cloud-thrift-

  • deposit

  • deposit-client

  • deposit-iface

  • deposit-server

Thrift IDL编写

关于 thrift更复杂的用法可以参考 ApacheThrift基础学习系列,根据数据库表的设计编写 deposit.thrift。

deposit.thrift定义了以下四个部分:命名空间 ( namespace)、枚举类型 ( enum)、结构类型 ( struct)和服务类型 ( service)。

(a). 命名空间 ( namespace)

// 指定编译生成的源代码的包路径名称

namespace java com.icekredit.rpc.thrift.examples.thrift

(b). 枚举类型 ( enum)

// 通过枚举定义银行分支所属区域

enum ThriftRegion {

   NORTH = 1,

   CENTRAL = 2,

   SOUTH = 3,

   EAST = 4,

   SOUTHWEST = 5,

   NORTHWEST = 6,

   NORTHEAST = 7

}

// 存款完成状态

enum ThriftDepositStatus {

   FINISHED = 1,

   PROCCEDING = 2,

   FAILED = 3

}

// 取款完成状态

enum ThriftWithdrawStatus {

   FINISHED = 1,

   PROCCEDING = 2,

   FAILED = 3

}

(c). 结构类型 ( struct)

// 银行

struct ThriftBank {

   1: required i64 id,

   2: required string code,

   3: required string name,

   4: optional string description,

   5: optional map<ThriftRegion, list<ThriftBranch>> branches

}

// 银行分支

struct ThriftBranch {

   1: required i64 id,

   2: required string code,

   3: required string name,

   4: required string address,

   5: optional i32 staffs,

   6: optional ThriftBank bank,

   7: optional ThriftRegion region

}

// 客户

struct ThriftCustomer {

   1: required string IDNumber,

   2: required string name,

   3: required string birthday,

   4: required i32 sex = 0,

   5: required i32 age,

   6: optional list<string> address,

   7: optional set<ThriftDepositCard> depositCards

}

// 银行卡

struct ThriftDepositCard {

   1: required string id,

   2: required bool isVip,

   3: required string openingTime,

   4: required double accountBalance,

   5: optional double accountFlow,

   6: optional ThriftBranch branch,

   7: optional ThriftCustomer customer,

   8: optional list<ThriftDeposit> depositHistory,

   9: optional list<ThriftWithdraw> WithdrawHistory

}

// 存款历史纪录

struct ThriftDeposit {

   1: required string serialNumber,

   2: required double transactionAmount,

   3: required string submittedTime,

   4: optional string finishedTime,

   5: optional ThriftDepositStatus status,

   6: optional ThriftDepositCard depositCard

}

// 取款历史纪录

struct ThriftWithdraw {

   1: required string serialNumber,

   2: required double transactionAmount,

   3: required string submittedTime,

   4: optional string finishedTime,

   5: optional ThriftWithdrawStatus status,

   6: optional ThriftDepositCard depositCard

}

(d). 服务类型 ( service)

// 银行 - 业务服务定义

service ThriftBankService {

   void registerNewBank(ThriftBank bank);

   list<ThriftBank> queryAllBanks();

   ThriftBank getBankById(i64 bankId);

   map<ThriftRegion, list<ThriftBranch>> queryAllBranchesByRegion(i64 bankId);

}

// 银行分支 - 业务服务定义

service ThriftBranchService {

   void addNewBranch(i64 bankId, ThriftBranch branch);

   list<ThriftBranch> queryAllBranches(i64 bankId);

   ThriftBranch getBranchById(i64 branchId);

}

// 客户 - 业务服务定义

service ThriftCustomerService {

   ThriftCustomer getCustomerById(string customerId);

   list<ThriftCustomer> queryAllCustomers();

   void addNewUser(ThriftCustomer customer);

   void modifyUserById(string customerId, ThriftCustomer customer);

   i32 getTotalDepositCard(string customerId);

}

// 银行卡 - 业务服务定义

service ThriftDepositCardService {

   set<ThriftDepositCard> queryAllDepositCards(string customerId);

   void addNewDepositCard(string customerId, ThriftDepositCard depositCard);

   ThriftDepositStatus depositMoney(string depositCardId, double money);

   ThriftWithdrawStatus withdrawMoney(string depositCardId, double money);

   list<ThriftDeposit> queryDepositHistorys(string depositCardId);

   list<ThriftWithdraw> queryWithdrawHistorys(string depositCardId);

}

进入 src/main/thrift目录,编译生成所需的枚举类、结构类和业务服务类的源文件。

thrift -gen java ./deposit.thrift

所有生成的源文件都位于同一个命名空间(包)下面: com.icekredit.rpc.thrift.examples.thrift

Spring Cloud整合Thrift RPC(二) - spring-cloud-thrift-

中间契约(deposit-iface)

将上述源文件拷贝到 deposit-iface 模块中。

Spring Cloud整合Thrift RPC(二) - spring-cloud-thrift-

通过 Mybatis逆向工程插件生成 SQLMapper的 XML和接口文件以及实体类。

友情提示: Mybatis逆向工程生成的实体类 ( entity),需要和 Thrift编译生成器生成的结构类 ( struct) 区分开来。而 Thrift生成器生成的所有源文件,都一定程度封装了底层的通信方式和相关协议,开发人员是不应该动手脚的。

为了在 Thrift中通过 Mybatis完成数据持久化,必须在实体类 ( entity)包装一层与结构类 ( struct)相互转换的方法。
在每个实体类中,根据业务添加以下两个方法,以 DepositCard为例:

  • toThrift():将实体类对象转换为结构类对象。
    public ThriftDepositCard toThrift() {

        ThriftDepositCard thriftDepositCard = new ThriftDepositCard();

        thriftDepositCard.setId(this.getId());

        thriftDepositCard.setAccountBalance(this.getAccountBalance());

        thriftDepositCard.setAccountFlow(this.getAccountFlow());

        thriftDepositCard.setIsVip(this.getIsVip());

        thriftDepositCard.setOpeningTime(this.getOpeningTime());

        ThriftBranch thriftBranch = new ThriftBranch();

        thriftBranch.setId(this.getBranchId());

        thriftDepositCard.setBranch(thriftBranch);

        ThriftCustomer thriftCustomer = new ThriftCustomer();

        thriftCustomer.setIDNumber(this.getCustomerId());

        thriftDepositCard.setCustomer(thriftCustomer);

        return thriftDepositCard;

    }
  • fromThrift():静态方法,将结构类对象转换为实体类对象。
    public static DepositCard fromThrift(ThriftDepositCard thriftDepositCard) {

        DepositCard depositCard = new DepositCard();

        depositCard.setId(thriftDepositCard.getId());

        depositCard.setAccountBalance(thriftDepositCard.getAccountBalance());

        depositCard.setAccountFlow(thriftDepositCard.getAccountFlow());

        depositCard.setIsVip(thriftDepositCard.isIsVip());

        ThriftCustomer thriftCustomer = thriftDepositCard.getCustomer();

        if (thriftCustomer != null) {

            String customerIDNumber = thriftCustomer.getIDNumber();

            depositCard.setCustomerId(customerIDNumber);

        }

        ThriftBranch thriftBranch = thriftDepositCard.getBranch();

        if (thriftBranch != null) {

            Long branchId = thriftBranch.getId();

            depositCard.setBranchId(branchId);

        }

        depositCard.setOpeningTime(thriftDepositCard.getOpeningTime());

        return depositCard;

    }

服务端(deposit-server)

在服务端模块引入:

  • spring-cloud-starter-thrift-server: thrift服务端的 starter程序。

  • calculator-iface:中间契约模块,这里作为服务端骨架( Skeleton)程序。

pom.xml

<parent>

    <groupId>com.icekredit.rpc.thrift.examples</groupId>

    <artifactId>deposit</artifactId>

    <version>1.0-SNAPSHOT</version>

</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>deposit-server</artifactId>

<packaging>jar</packaging>

<dependencies>

    <!-- Thrift相关依赖 -->

    <dependency>

        <groupId>com.icekredit.rpc.thrift</groupId>

        <artifactId>spring-cloud-starter-thrift-server</artifactId>

        <version>1.0-SNAPSHOT</version>

    </dependency>

    <dependency>

        <groupId>com.icekredit.rpc.thrift.examples</groupId>

        <artifactId>deposit-iface</artifactId>

        <version>1.0-SNAPSHOT</version>

    </dependency>

    <!-- SpringBoot依赖 -->

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-actuator</artifactId>

    </dependency>

    <!-- 数据库相关依赖 -->

    <dependency>

        <groupId>mysql</groupId>

        <artifactId>mysql-connector-java</artifactId>

    </dependency>

    <dependency>

        <groupId>com.alibaba</groupId>

        <artifactId>druid-spring-boot-starter</artifactId>

        <version>1.1.5</version>

    </dependency>

    <dependency>

        <groupId>org.mybatis.spring.boot</groupId>

        <artifactId>mybatis-spring-boot-starter</artifactId>

        <version>1.3.0</version>

    </dependency>

    <!-- Swagger依赖 -->

    <dependency>

        <groupId>io.springfox</groupId>

        <artifactId>springfox-swagger2</artifactId>

        <version>2.6.1</version>

    </dependency>

    <dependency>

        <groupId>io.springfox</groupId>

        <artifactId>springfox-swagger-ui</artifactId>

        <version>2.6.1</version>

    </dependency>

</dependencies>

<build>

    <plugins>

        <plugin>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-maven-plugin</artifactId>

        </plugin>

    </plugins>

</build>

在 application.yml中配置 thrift服务端的运行参数、数据源连接池参数和 Mybatis相关属性:

application.yml

server:

  port: 8080

endpoints:

  actuator:

    sensitive: false

    enabled: true

management:

  security:

    enabled: false

spring:

  datasource:

    druid:

      url: jdbc:mysql://localhost:3306/deposit?useUnicode=true&characterEncoding=utf-8

      driver-class-name: com.mysql.jdbc.Driver

      username: root

      password: root

  thrift:

    server:

      service-id: deposit-server-rpc

      service-model: hsHa

      port: 25000

      worker-queue-capacity: 1000

      hs-ha:

        min-worker-threads: 5

        max-worker-threads: 20

        keep-alived-time: 3

mybatis:

  mapper-locations: classpath:mapper/*.xml

  type-aliases-package: com.icekredit.rpc.thrift.examples.http.entities

logging:

  level:

    root: INFO

    com:

      icekredit:

        rpc:

          thrift:

            examples:

              mapper: DEBUG

服务端程序启动入口类,设置 SwaggerAPI所在的包路径名称。

Application.java

@SpringBootApplication

@EnableSwagger2

public class Application {

    public static void main(String[] args) {

        SpringApplication.run(Application.class, args);

    }

    @Bean

    public Docket createRestfulApi() {

        return new Docket(DocumentationType.SWAGGER_2)

                .apiInfo(apiInfo())

                .select()

                .apis(RequestHandlerSelectors.basePackage("com.icekredit.rpc.thrift.examples.service.http.controller"))

                .paths(PathSelectors.any())

                .build();

    }

    private ApiInfo apiInfo() {

        return new ApiInfoBuilder()

                .title("Deposit Server")

                .description("Deposit Server")

                .version("1.0")

                .build();

    }

}

编写服务端的 Thrift的实现,以 ThriftDepositCardService为例,由实现类 ThriftDepositCardServiceImpl实现 ThriftDepositCardService.Iface接口的方法:

ThriftDepositCardServiceImpl.java

@ThriftService(name = "thriftDepositCardService")

public class ThriftDepositCardServiceImpl implements ThriftDepositCardService.Iface {

    private final BranchMapper branchMapper;

    private final DepositCardMapper depositCardMapper;

    private final CustomerMapper customerMapper;

    private final DepositHistoryMapper depositHistoryMapper;

    private final WithdrawHistoryMapper withdrawHistoryMapper;

    @Autowired

    public ThriftDepositCardServiceImpl(BranchMapper branchMapper, DepositCardMapper depositCardMapper, CustomerMapper customerMapper, DepositHistoryMapper depositHistoryMapper, WithdrawHistoryMapper withdrawHistoryMapper) {

        this.branchMapper = branchMapper;

        this.depositCardMapper = depositCardMapper;

        this.customerMapper = customerMapper;

        this.depositHistoryMapper = depositHistoryMapper;

        this.withdrawHistoryMapper = withdrawHistoryMapper;

    }

    @Override

    public Set<ThriftDepositCard> queryAllDepositCards(String customerId) throws TException {

        List<DepositCard> depositCardList = depositCardMapper.queryAllDepositCards(customerId);

        // 查询客户持有的银行卡

        return depositCardList.stream().map(depositCard -> {

            ThriftDepositCard thriftDepositCard = depositCard.toThrift();

            Long branchId = depositCard.getBranchId();

            if (Objects.nonNull(branchId) && branchId > 0L) {

                Branch branch = branchMapper.findById(branchId);

                ThriftBranch thriftBranch = branch.toThrift();

                ThriftBank thriftBank = new ThriftBank();

                thriftBank.setId(branch.getBankId());

                thriftBranch.setBank(thriftBank);

                thriftDepositCard.setBranch(thriftBranch);

            }

            Customer customer = customerMapper.findById(customerId);

            ThriftCustomer thriftCustomer = customer.toThrift();

            thriftDepositCard.setCustomer(thriftCustomer);

            return thriftDepositCard;

        }).collect(Collectors.toSet());

    }

    @Override

    @Transactional

    public void addNewDepositCard(String customerId, ThriftDepositCard depositCard) throws TException {

        DepositCard newDepositCard = DepositCard.fromThrift(depositCard);

        // 新增银行卡信息

        depositCardMapper.save(newDepositCard);

    }

    @Override

    @Transactional

    public ThriftDepositStatus depositMoney(String depositCardId, double money) throws TException {

        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

        try {

            DepositHistory depositHistory = new DepositHistory();

            depositHistory.setSubmittedTime(sf.format(new Date()));

            depositCardMapper.incrementMoney(depositCardId, money);

            depositHistory.setFinishedTime(sf.format(new Date()));

            depositHistory.setSerialNumber(UUID.randomUUID().toString().replace("-", ""));

            depositHistory.setTransactionAmount(money);

            depositHistory.setDepositCardId(depositCardId);

            depositHistory.setStatus(1);

            // 新增存款历史记录

            depositHistoryMapper.save(depositHistory);

            return ThriftDepositStatus.FINISHED;

        } catch (Exception e) {

            e.printStackTrace();

            return ThriftDepositStatus.FAILED;

        }

    }

    @Override

    @Transactional

    public ThriftWithdrawStatus withdrawMoney(String depositCardId, double money) throws TException {

        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

        try {

            WithdrawHistory withdrawHistory = new WithdrawHistory();

            withdrawHistory.setSubmittedTime(sf.format(new Date()));

            depositCardMapper.decrementMoney(depositCardId, money);

            withdrawHistory.setFinishedTime(sf.format(new Date()));

            withdrawHistory.setSerialNumber(UUID.randomUUID().toString().replace("-", ""));

            withdrawHistory.setTransactionAmount(money);

            withdrawHistory.setDepositCardId(depositCardId);

            withdrawHistory.setStatus(1);

            // 新增取款历史记录

            withdrawHistoryMapper.save(withdrawHistory);

            return ThriftWithdrawStatus.FINISHED;

        } catch (Exception e) {

            e.printStackTrace();

            return ThriftWithdrawStatus.FAILED;

        }

    }

    @Override

    public List<ThriftDeposit> queryDepositHistorys(String depositCardId) throws TException {

        List<DepositHistory> depositHistory = depositHistoryMapper.queryDepositHistoryList(depositCardId);

        // 查询存款历史纪录

        return depositHistory.stream().map(DepositHistory::toThrift).collect(Collectors.toList());

    }

    @Override

    public List<ThriftWithdraw> queryWithdrawHistorys(String depositCardId) throws TException {

        List<WithdrawHistory> withdrawHistory = withdrawHistoryMapper.queryWithdrawHistoryList(depositCardId);

        // 查询取款历史纪录

        return withdrawHistory.stream().map(WithdrawHistory::toThrift).collect(Collectors.toList());

    }

}

Mybatis持久层,还是以 DepositCardMapper为例:

DepositCardMapper.java

@Repository

@Mapper

public interface DepositCardMapper {

    int save(DepositCard record);

    List<DepositCard> queryAllDepositCards(@Param("customerId") String customerId);

    void decrementMoney(@Param("depositCardId") String depositCardId, @Param("money") Double money);

    void incrementMoney(@Param("depositCardId") String depositCardId, @Param("money") Double money);

    Long countRowsByCustomerId(@Param("customerId") String customerId);

}

DepositCardMapper.xml

<insert id="save" parameterType="com.icekredit.rpc.thrift.examples.http.entities.DepositCard">

    INSERT INTO deposit_card (id, is_vip, opening_time,

                              account_balance, account_flow, branch_id,

                              customer_id)

    VALUES (#{id,jdbcType=VARCHAR}, #{isVip,jdbcType=BIT}, #{openingTime,jdbcType=VARCHAR},

            #{accountBalance,jdbcType=DOUBLE}, #{accountFlow,jdbcType=DOUBLE}, #{branchId,jdbcType=BIGINT},

            #{customerId,jdbcType=VARCHAR})

</insert>

<select id="queryAllDepositCards" resultMap="BaseResultMap" parameterType="java.lang.String">

    SELECT

    <include refid="Base_Column_List"/>

    FROM deposit_card

    WHERE customer_id = #{customerId}

</select>

<select id="countRowsByCustomerId" resultType="java.lang.Long" parameterType="java.lang.String">

    SELECT COUNT(id)

    FROM deposit_card

    WHERE customer_id = #{customerId}

</select>

<update id="decrementMoney">

    UPDATE deposit_card

    <set>

        <if test="money != null">

            account_balance = account_balance - #{money},

        </if>

    </set>

    WHERE id = #{depositCardId}

</update>

<update id="incrementMoney">

    UPDATE deposit_card

    <set>

        <if test="money != null">

            account_balance = account_balance + #{money},

        </if>

    </set>

    WHERE id = #{depositCardId}

</update>

客户端(deposit-client)

同样,在客户端模块引入:

  • spring-cloud-starter-thrift-client: thrift客户端的 starter程序。

  • deposit-iface:中间契约模块,这里作为客户端桩( Stub)程序。

pom.xml

<parent>

    <groupId>com.icekredit.rpc.thrift.examples</groupId>

    <artifactId>deposit</artifactId>

    <version>1.0-SNAPSHOT</version>

</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>deposit-client</artifactId>

<dependencies>

    <!-- Thrift相关依赖 -->

    <dependency>

        <groupId>com.icekredit.rpc.thrift</groupId>

        <artifactId>spring-cloud-starter-thrift-client</artifactId>

        <version>1.0-SNAPSHOT</version>

    </dependency>

    <dependency>

        <groupId>com.icekredit.rpc.thrift.examples</groupId>

        <artifactId>deposit-iface</artifactId>

        <version>1.0-SNAPSHOT</version>

    </dependency>

    <!-- SpringBoot依赖 -->

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-actuator</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>

    <!-- Spring Cloud Consul服务注册与发现 -->

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-consul-discovery</artifactId>

    </dependency>

    <!-- Spring Cloud声明式Restful客户端 -->

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-feign</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-ribbon</artifactId>

    </dependency>

    <!-- Swagger依赖 -->

    <dependency>

        <groupId>io.springfox</groupId>

        <artifactId>springfox-swagger2</artifactId>

        <version>2.6.1</version>

    </dependency>

    <dependency>

        <groupId>io.springfox</groupId>

        <artifactId>springfox-swagger-ui</artifactId>

        <version>2.6.1</version>

    </dependency>

</dependencies>

<dependencyManagement>

    <dependencies>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-dependencies</artifactId>

            <version>${spring-cloud.version}</version>

            <type>pom</type>

            <scope>import</scope>

        </dependency>

    </dependencies>

</dependencyManagement>

<build>

    <plugins>

        <plugin>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-maven-plugin</artifactId>

        </plugin>

    </plugins>

</build>

在 application.yml中配置 thrift的客户端的的运行参数和 Consul 的服务注册与发现的参数:

application.yml

server:

  port: 8080

endpoints:

  actuator:

    sensitive: false

    enabled: true

management:

  security:

    enabled: false

spring:

  cloud:

    consul:

      host: 192.168.91.128

      port: 8500

      discovery:

        register: false

        register-health-check: true

        health-check-interval: 30s

      retry:

        max-attempts: 3

        max-interval: 2000

  thrift:

    client:

      package-to-scan: com.icekredit.rpc.thrift.examples.thrift.client

      service-model: hsHa

      pool:

        retry-times: 3

        pool-max-total-per-key: 200

        pool-min-idle-per-key: 10

        pool-max-idle-per-key: 40

        pool-max-wait: 10000

        connect-timeout: 5000

客户端程序启动入口类,设置 SwaggerAPI所在的包路径名称,同时允许自身作为注册程序注册到注册中心。

@SpringBootApplication

@EnableFeignClients

@EnableDiscoveryClient

@EnableSwagger2

public class Application {

    public static void main(String[] args) {

        SpringApplication.run(Application.class, args);

    }

    @Bean

    public Docket createRestfulApi() {

        return new Docket(DocumentationType.SWAGGER_2)

                .apiInfo(apiInfo())

                .select()

                .apis(RequestHandlerSelectors.basePackage("com.icekredit.rpc.thrift.examples"))

                .paths(PathSelectors.any())

                .build();

    }

    private ApiInfo apiInfo() {

        return new ApiInfoBuilder()

                .title("Deposit Client")

                .description("Deposit Client")

                .version("1.0")

                .build();

    }

}

在客户端使用 @ThriftClient注解标识服务端的 thrift服务代理接口,代理服务 ID为 deposit-server-rpc,代理的目标类是 ThriftDepositCardService。

DepositCardThriftClient.java

@ThriftClient(serviceId = "deposit-server-rpc", refer = ThriftDepositCardService.class)

public interface DepositCardThriftClient extends ThriftClientAware<ThriftDepositCardService.Client> {

}

BankThriftClient.java

@ThriftClient(serviceId = "deposit-server-rpc", refer = ThriftBankService.class)

public interface BankThriftClient extends ThriftClientAware<ThriftBankService.Client> {

}

在客户端控制器中通过 ThriftReferer注入需要使用的服务代理接口,通过 thriftClient.client()即可获取 Thrift客户端桩对象,然后实现远程服务的调用。

DepositCardRpcController.java

@RestController

@RequestMapping("/rpc/deposit")

public class DepositCardRpcController {

    @ThriftReferer

    private DepositCardThriftClient thriftClient;

    @GetMapping("/queryAllDepositCards")

    public List<DepositCard> queryAllDepositCards(@RequestParam("customerId") String customerId)

            throws Exception {

        return thriftClient.client().queryAllDepositCards(customerId)

                .stream().map(DepositCard::fromThrift)

                .collect(Collectors.toList());

    }

    @PostMapping("/addNewDepositCard")

    public void addNewDepositCard(DepositCard depositCard) throws Exception {

        thriftClient.client().addNewDepositCard(depositCard.getCustomerId(), depositCard.toThrift());

    }

    @GetMapping("/depositMoney")

    public ThriftDepositStatus depositMoney(@RequestParam("depositCardId") String depositCardId,

                                            @RequestParam("money") double money) throws Exception {

        return thriftClient.client().depositMoney(depositCardId, money);

    }

    @GetMapping("/withdrawMoney")

    public ThriftWithdrawStatus withdrawMoney(@RequestParam("depositCardId") String depositCardId,

                                              @RequestParam("money") double money) throws Exception {

        return thriftClient.client().withdrawMoney(depositCardId, money);

    }

    @GetMapping("/queryDepositHistory")

    public List<DepositHistory> queryDepositHistory(@RequestParam("depositCardId") String depositCardId)

            throws Exception {

        return thriftClient.client().queryDepositHistorys(depositCardId)

                .stream().map(DepositHistory::fromThrift)

                .collect(Collectors.toList());

    }

    @GetMapping("/queryWithdrawHistory")

    public List<WithdrawHistory> queryWithdrawHistory(@RequestParam("depositCardId") String depositCardId)

            throws Exception {

        return thriftClient.client().queryWithdrawHistorys(depositCardId)

                .stream().map(WithdrawHistory::fromThrift)

                .collect(Collectors.toList());

    }

}

BankRpcController.java

@RestController

@RequestMapping("/rpc/bank")

public class BankRpcController {

    @ThriftReferer

    private BankThriftClient thriftClient;

    @PostMapping("/addNewBank")

    public void addNewBank(Bank bank) throws Exception {

        thriftClient.client().registerNewBank(bank.toThrift());

    }

    @GetMapping("/getBankById")

    public Bank getBankById(@RequestParam("bankId") Long bankId) throws Exception {

        return Bank.fromThrift(thriftClient.client().getBankById(bankId));

    }

    @GetMapping("/queryAllBranchesByRegion")

    public Map<Region, List<Branch>> queryAllBranchesByRegion(@RequestParam("bankId") Long bankId) throws Exception {

        Map<ThriftRegion, List<ThriftBranch>> thriftRegionListMap = thriftClient.client()

                .queryAllBranchesByRegion(bankId);

        Map<Region, List<Branch>> regionListMap = new HashMap<>();

        for (Map.Entry<ThriftRegion, List<ThriftBranch>> entry : thriftRegionListMap.entrySet()) {

            ThriftRegion thriftRegion = entry.getKey();

            Region region = Region.findByValue(thriftRegion.getValue());

            List<ThriftBranch> thriftBranches = entry.getValue();

            List<Branch> branchList = thriftBranches.stream().map(Branch::fromThrift).collect(Collectors.toList());

            regionListMap.put(region, branchList);

        }

        return regionListMap;

    }

}

因为服务代理客户端接口使用 @ThriftClient标识,通过(服务ID + 客户端桩 + 版本号)唯一标识, 即使同时注入多个服务代理客户端接口, @ThriftReferer也可忽略注解属性的配置。

总结

有一点是肯定的,那就是在已有技术框架(比如说: Spring + Mybatis/JPA)内,为了提高服务的性能和吞吐量,而引入诸如 Thrift的 RPC框架,编程难度和复杂度是会大大提高的。好比一把双刃剑,技术选型时还需要多方面权衡利弊。

欢迎关注技术公众号: 零壹技术栈

Spring Cloud整合Thrift RPC(二) - spring-cloud-thrift-

本帐号将持续分享后端技术干货,包括虚拟机基础,多线程编程,高性能框架,异步、缓存和消息中间件,分布式和微服务,架构学习和进阶等学习资料和文章。

上一篇:springmvc-04


下一篇:Vue中使用axios调用后端接口的坑