配置 Bolt 服务

Bolt 服务的名称源自 RPC 使用的底层通信框架 Bolt。相对于传统的 WebService,Bolt 支持更加复杂的对象,序列化后的对象更小,且提供了更为丰富的调用方式(sync、oneway、callback、future 等),支持更广泛的应用场景。

在 SOFA 中,Bolt 服务提供方使用的端口是 12200,详情请参见 配置说明

发布及引用 Bolt 服务

SOFA 中的 RPC 通过 Binding 模型定义不同的通信协议,每接入一种新的协议,就会增加一种 Binding 模型。要在 SOFA 中添加 RPC 的 Bolt 协议的实现,就需要在 Binding 模型中增加一个 <sofa:binding.bolt/>

  • 发布一个 Bolt 的服务需在 <sofa:service> 中添加 <sofa:binding.bolt/>,示例如下:

    <!-- 发布 Bolt 服务 -->
    <sofa:service interface="com.alipay.test.SampleService" ref="sampleService" unique-id="service1">
         <sofa:binding.bolt/>
    </sofa:service>
  • 引用一个 Bolt 的服务需在 <sofa:reference> 中添加 <sofa:binding.bolt/>,示例如下:

    <!-- 引用 Bolt 服务 -->
    <sofa:reference interface="com.alipay.test.SampleService" id="sampleService">
         <sofa:binding.bolt/>
    </sofa:reference>

Bolt 服务完整配置

Bolt 配置标签主要有 global-attrsmethod 两种,同时配置时,以 method 中的配置为准。可配置的参数如下:

  • type:调用方式。取值为 sync、oneway、callback、future,默认为 sync。

  • timeout:超时时间。默认为 3000 ms。

  • callback-class:调用方式为 callback 时的回调对象类。

  • callback-ref:调用方式为 callback 时的回调 Spring Bean 引用。

Bolt 服务发布完整配置

<sofa:service interface="com.alipay.test.SampleService" ref="sampleService" unique-id="service1">
    <sofa:binding.bolt>
        <sofa:global-attrs timeout="5000"/>
        <!-- 此处方法名 service 为示例,需要替换成实际方法名。 -->
        <sofa:method name="service" timeout="3000"/>
    </sofa:binding.bolt>
</sofa:service>

Bolt 服务引用完整配置

<sofa:reference id="sampleService" interface="com.alipay.test.SampleService" unique-id="service1">
    <sofa:binding.bolt>
        <sofa:global-attrs timeout="5000" test-url="localhost:12200" address-wait-time="1000"
            connect.timeout="1000" connect.num="-1" idle.timeout="-1" idle.timeout.read="-1"/>
        <!-- method 配置的属性优先级高于 global-attrs 中的配置。 -->
        <!-- 此处方法名 futureMethod 和 callbackMethod 为示例,需要替换成实际方法名。 -->
        <sofa:method name="futureMethod" type="future" timeout="5000"/>
        <sofa:method name="callbackMethod" type="callback" timeout="3000"
            callback-class="com.alipay.test.TestCallback"/>
    </sofa:binding.bolt>
</sofa:reference>

Bolt 服务提供方配置

Bolt 的底层服务提供方是一个 Java NIO Server (Non-blocking I/O Server),SOFA 框架提供几个选项来调整 Bolt Server 的一些属性。详情请参见 配置说明

Bolt 服务消费方配置

Bolt 引用调用方式

Bolt 提供多种调用方式,以满足各种业务场景的需求。目前,Bolt 提供的调用方式有以下几种:

调用方式

类型

说明

sync

同步

Bolt 默认的调用方式。

oneway

异步

消费方发送请求后直接返回,忽略提供方的处理结果。

callback

异步

消费方提供一个回调接口,当提供方返回后,SOFA 框架会执行回调接口。

future

异步

消费方发起调用后马上返回,当需要结果时,消费方需要主动去获取数据。

  • sync 调用

    Bolt 默认的调用方式,支持在服务提供方和消费方配置超时时间:

    • 服务提供方

      XML 配置如下:

      <!-- 服务方超时配置 -->
      <sofa:service interface="com.alipay.test.SampleService2" ref="sampleService2">
          <sofa:binding.bolt>
          <!-- 此处方法名 service 为示例,需要替换成实际方法名。 -->
          <sofa:method name="service" timeout="5000"/>
          </sofa:binding.bolt>
      </sofa:service>
    • 服务消费方

      XML 配置如下:

      <!-- 消费方超时配置 -->
      <sofa:reference interface="com.alipay.test.SampleService2" id="sampleServiceSync">
          <sofa:binding.bolt>
               <!-- 超时全局配置 -->
                <sofa:global-attrs timeout="8000" test-url="127.0.0.1:12200"/>
                <!-- 如果配置了 method ,优先使用 method 配置。 -->
                <!-- 此处方法名 service 为示例,需要替换成实际方法名。 -->
                <sofa:method name="service" type="sync" timeout="10000"/>
          </sofa:binding.bolt>
      </sofa:reference>

      type的默认取值为 sync。如果您有多个方法需要配置超时时间,并且超时时间都相同,也可以设置全局的超时时间。XML 配置如下:

      <!-- 消费方批量配置超时时间 -->
      <sofa:reference interface="com.alipay.test.SampleService2" id="sampleServiceSync">
           <sofa:binding.bolt>
                <sofa:global-attrs timeout="5000" test-url="127.0.0.1:12200"/>
           </sofa:binding.bolt>
      </sofa:reference>

      说明

      如果在消费方配置了超时时间,那么将以消费方的超时时间为准,提供方的超时时间将被覆盖;如果消费方没有配置,则以提供方的超时时间为准。超时时间优先级:reference method > reference global-attrs > service method > service global-attrs

  • oneway 调用

    如果是 oneway 调用方式,消费方不关心结果,在发起调用后直接返回,框架会忽略提供方的处理结果。在 Bolt 中,在 XML 中针对 method 的配置如下:

    <!-- 配置 oneway -->
    <sofa:reference interface="com.alipay.test.SampleService2" id="sampleService2">
        <sofa:binding.bolt>
            <sofa:global-attrs test-url="127.0.0.1:12200"/>
            <!-- 此处方法名 service 为示例,需要替换成实际方法名。 -->
            <sofa:method name="service" type="oneway"/>
        </sofa:binding.bolt>
    </sofa:reference>
    说明

    由于消费方是直接返回,不关心处理结果,所以在 oneway 方式下配置超时属性是无效的。

  • callback 调用

    callback 是一种异步回调方式,消费方需要提供回调接口。在调用结束后,回调接口会被框架调用。callback 接口支持通过配置 class 或引用 Bean 的方式实现 callback:

    • 配置 class

      XML 配置如下:

      <!-- callback 调用配置 -->
      <sofa:reference interface="com.alipay.test.SampleService2" id="sampleService">
          <sofa:binding.bolt>
              <!-- 此处方法名 testCallback 为示例,需要替换成实际方法名。 -->
              <sofa:method name="testCallback" type="callback" callback-class="com.alipay.test.binding.tr.MyCallBackHandler"/>
          </sofa:binding.bolt>
      </sofa:reference>
    • 引用 Bean

      XML 配置如下:

      <!-- 使用 Bean 来实现 callback 接口 -->
      <bean id="myCallBackHandlerBean"class="com.alipay.test.binding.tr.MyCallBackHandler"/>
      <sofa:reference interface="com.alipay.test.SampleService2" id="sampleService">
          <sofa:binding.bolt>
              <!-- 此处方法名 testCallback 为示例,需要替换成实际方法名。 -->
              <sofa:method name="testCallback" type="callback" callback-ref="myCallBackHandlerBean"/>
          </sofa:binding.bolt>
      </sofa:reference>

需要注意,使用 callback 调用方式时,callback 接口必须实现 com.alipay.sofa.rpc.api.callback.SofaResponseCallback。这个接口包含三个方法,说明如下:

public interface SofaResponseCallback {

  /**
   * 当服务提供方业务层正常返回结果,sofa-remoting 层将回调该方法。
   * @param appResponse response object。
   * @param methodName 调用服务对应的方法名。
   * @param request callback 对应的 request。
   `*/
  public void onAppResponse(Object appResponse, String methodName, RequestBase request);

  /**
   * 当服务提供方业务层抛出异常,sofa-remoting 层将回调该方法。
   * @param t 服务方业务层抛出的异常。
   * @param methodName 调用服务对应的方法名。
   * @param request callback 对应的 request。
   `*/
  public void onAppException(Throwable t, String methodName, RequestBase request);

  /**
   * 当 sofa-remoting 层出现异常时,回调该方法。
   * @param sofaException sofa-remoting 层异常。
   * @param methodName 调用服务对应的方法名。
   * @param request callback 对应的 request。
   `*/
  public void onSofaException(SofaRpcException sofaException, String methodName,
                             RequestBase request);

}
  • future 调用

    future 也是一种异步的调用方式。消费方发起调用后,马上返回。当需要结果时,消费方需要主动去获取数据。使用 future 的方式调用,配置和其他方式类似,只需要在 method 层面设置 type 为 future 即可。XML 配置如下:

    <!-- Future 调用配置 -->
    <sofa:reference interface="com.alipay.test.SampleService" id="sampleServiceFuture">
        <sofa:binding.bolt>
            <sofa:global-attrs test-url="127.0.0.1:12200"/>
            <!-- 此处方法名 service 为示例,需要替换成实际方法名。 -->
            <sofa:method name="service" type="future"/>
        </sofa:binding.bolt>
    </sofa:reference>

    使用 future 调用,返回的结果保存在一个 ThreadLocal 线程变量里面,可以通过如下方式获取这个线程变量的值:

    // Future 获取调用结果。
    public void testFuture() throws SofaException, InterruptedException {
      sampleServiceFuture.service();
      Object result = SofaResponseFuture.getResponse(1000, true);
    
      Assert.assertEquals("Hello, world!", result);
    }

    要拿到 future 调用后的结果,只需要调用 SofaResponseFuturegetResponse 方法即可。getResponse 方法的两个参数说明如下:

    • 第一个参数是超时时间,含义是调用线程等待的最长时间,负数表示无等待时间限制,零表示立即返回,单位是毫秒。

    • 第二个参数代表是否清除 ThreadLocal 变量的值,如果设为 true,则返回 response 之前,先清除 ThreadLocal 的值,避免内存泄漏。

Bolt 引用详细配置

除了各种调用方式之外,Bolt 还在消费方提供了各种配置选项,这些选项不太常用,列举如下:

配置项

类型

默认值

说明

connect.timeout

INTEGER

1000

消费方连接超时时间。

单位:ms

connect.num

INTEGER

-1

消费方连接数。

-1 代表不设置(默认为每个目标地址建立一个连接)。

idle.timeout

INTEGER

-1

消费方最大空闲时间。

-1 表示使用底层默认值(底层默认值为 0,表示永远不会有读 idle)。该配置也是心跳的时间间隔,当请求 idle 时间超过配置时间后,发送心跳到服务方。

idle.timeout.read

INTEGER

-1

消费方最大读空闲时间。

-1 表示使用底层默认值(底层默认值为 30)。如果 idle.timeout > 0,在 idle.timeout + idle.timeout.read 时间内,如果没有请求发生,那么该连接将会自动断开。

address-wait-time

INTEGER

0

reference 生成时,等待服务注册中心将地址推送到消费方的时间。

单位:ms

取值范围:[0, 30000]

取值超过 30000 时,默认调整为 30000 。