美文网首页java后台常用开发框架学习
Spring Cloud整合Thrift RPC(二) - 应用

Spring Cloud整合Thrift RPC(二) - 应用

作者: 零壹技术栈 | 来源:发表于2018-09-14 22:50 被阅读416次

    前言

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

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

    image

    正文

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

    image
    • deposit
      • deposit-client
      • deposit-iface
      • deposit-server

    Thrift IDL编写

    关于 thrift更复杂的用法可以参考Apache Thrift基础学习系列,根据数据库表的设计编写 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

    image

    中间契约(deposit-iface)

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

    image

    通过Mybatis逆向工程插件生成SQLMapperXML接口文件以及实体类

    友情提示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-serverthrift服务端的 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
    

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

    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-clientthrift客户端的 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
    

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

    @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服务代理接口代理服务IDdeposit-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)内,为了提高服务的性能吞吐量,而引入诸如ThriftRPC框架,编程难度复杂度是会大大提高的。好比一把双刃剑,技术选型时还需要多方面权衡利弊。


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

    零壹技术栈

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

    相关文章

      网友评论

        本文标题:Spring Cloud整合Thrift RPC(二) - 应用

        本文链接:https://www.haomeiwen.com/subject/kfgagftx.html