高可用可伸缩微服务架构:基于Dubbo、Spring Cloud和Service Mesh
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.1 Dubbo框架的选型与使用

3.1.1 Dubbo框架的选型

通过表3-1可以看出不同的微服务框架各有优缺点,从分类上来说可以分为两类:服务治理型和多语言型。

表3-1

服务治理型框架包括Dubbo、Dubbox、Motan、Spring Cloud。

多语言型框架包括gRPC、Thrift。

Dubbo是阿里开源的一个高性能优秀的Java服务框架,使应用可通过RPC实现服务的输出和输入功能,同时可以和Spring框架进行无缝集成。

3.1.2 Dubbo框架的使用

在我们正式使用之前,先简单介绍一下Dubbo的架构,对其有一个整体的了解(架构图可参考Dubbo官网)。

通过架构图可以看到,Dubbo提供了三个关键功能:

● 基于接口的远程调用;

● 容错和负载均衡;

● 自动服务注册和发现。

从本章开始我们将正式以支付场景为案例和大家一起探讨微服务从0到1的过程,下面将以一个具体的例子来说明。

1.搭建项目工程结构

项目工程结构分为两个子模块,分别是superpay-tradecenter-core和superpay-tradecenter-facade,这个工程的命名代表支付场景中的交易,具体工程结构如图3-1所示。

图3-1

在图3-1中,我们计划将Dubbo服务的实现类写在superpay-tradecenter-core的facade.impl包中,将接口类写入super-tradecenter-facade工程,这样就将依赖与核心分开了,

2.编写Dubbo服务代码

:本章约定所有的Dubbo服务类都以facade作为后缀。

建立Dubbo服务前需要先创建服务的接口类,在super-tradecenter-facade模块中写入接口类PayTradeFacade,该接口类目前只有一个支付请求方法payRequest:

        public interface PayTradeFacade {

            /**
            * 支付请求
          * @param payRequestDto
          * @return
          */
          public PayResponseDto payRequest(PayRequestDto payRequestDto);
      }

在payRequest方法中有一个入参PayRequestDto,里面主要包括商户支付请求的一些数据,方便后续支付业务进行校验;还有一个参数PayResponseDto,主要是将支付请求的结果返回给调用方,包括返回码和错误描述,代码如下所示。

        public class PayRequestDto {
            private static final long serialVersionUID = -723763178242138577L;

            //商户订单号
            private Long merchantOrderNo;
            //用户电话
            private String phone;
            //用户姓名
            private String userName;
            //支付金额
            private BigDecimal payAmount;
            //商户号
            private String merchantNo;
            //商户请求时间
            private Date merchantReqTime;
            //订单币种
            private String orderCurrency;
        }

        public class PayResponseDto {
            private static final long serialVersionUID = -723763178242138577L;

            //返回码
            private String returnCode;
            //返回信息
            private String returnMsg;

        }

在superpay-tradecenter-core模块中写入PayTradeFacade接口的实现类,代码如下:

        public class PayTradeFacadeImpl implements PayTradeFacade {

            @Override
            public PayResponseDto payRequest(PayRequestDto payRequestDto){
              PayResponseDto payResponseDto = new PayResponseDto();
              payResponseDto.setReturnCode("200");
              return payResponseDto;
            }
        }

在代码中,为了演示Dubbo使用的效果,我们暂时先将payRequest的返回码设置为200,可以把PayTradeFacade接口类看作支付交易的核心子域,而接口类中的payRequest方法是这个核心子域的内聚方法,向上游提供支付请求服务。

服务代码写完以后,接下来要做的就是如何将服务发布出去,为了项目清晰更容易阅读,我们依然采用配置文件的方式发布服务。现在Dubbo的最新版本是2.5.7,也是本示例中使用的版本,Spring配置文件如下所示。

        <! -- 应用名 -->
        <dubbo:application name="superpay"/>
        <! -- Dubbo扫描类路径 -->
        <dubbo:annotation package="com.superpay.core.facade" />
        <! -- 连接到哪个本地注册中心 -->
        <dubbo:registry id="dubbo-registry" address="zookeeper://localhost:2181"/>
        <! -- 用Dubbo协议在20880端口暴露服务 -->
        <dubbo:protocol name="dubbo" port="28080"/>
        <! -- 声明需要暴露的服务接口 -->
        <dubbo:service registry="dubbodemo" timeout="3000" interface="com.tradecenter.facade.PayTradeFacade" ref="payTradeFacade"/>
        <! -- 服务类定义 -->
        <bean id="payTradeFacade" class="com.tradecenter.facade.impl.PayTradeFacadeImpl"/>

最终支付交易工程结构的全貌如图3-2所示,这样基于Dubbo的服务提供者代码就已经实现了,接下来写服务调用端代码和配置。

图3-2

3.编写Dubbo调用端代码

调用端的Dubbo Spring配置内容如下:

        <! -- 应用名 -->
        <dubbo:application name="superpay"/>
        <! -- 连接到哪个本地注册中心 -->
        <dubbo:registry id="dubbo-registry" address="zookeeper://localhost:2181"/>
        <! -- 用Dubbo协议在20880端口暴露服务 -->
        <dubbo:protocol name="dubbo" port="28080"/>
        <! -- 扫描注解包路径,多个包用逗号分隔,不填pacakge则表示扫描当前ApplicationContext中所有的类 -->
        <dubbo:annotation package="com.superpay.core.facade" />

        <dubbo:reference interface="com.tradecenter.facade.PayTradeFacade" timeout="2000"/>

在调用端假定支付网关业务逻辑调用交易服务的支付请求接口,代码逻辑如下:

        @Service
        public class PayGatewayBizImpl implements PayGatewayBiz {
            private static final Logger logger = LoggerFactory.getLogger(PayGatewayBizImpl.class);

            @Autowired
            private PayTradeFacade payTradeFacade;
            public void payRequest(PayRequestDto payRequestDto){
              PayResponseDto payResponseDto = payTradeFacade.payRequest(payRequestDto);
              logger.info("打印Dubbo返回响应编码:" + payResponseDto.getReturnCode());

            }
        }

最终打印结果是:

打印Dubbo返回响应编码:200