全部产品

配置 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 的底层服务提供方是一个 Java NIO Server (Non-blocking I/O Server)。SOFA 框架提供几个选项来调整 BOLT Server 的一些属性,详见 配置说明

BOLT 服务消费方配置

BOLT 引用调用方式

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

调用方式

类型

说明

sync

同步

BOLT 默认的调用方式

oneway

异步

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

callback

异步

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

future

异步

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

sync 调用

BOLT 默认的调用方式。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>
说明

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

消费方的超时时间配置和提供方类似,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,则默认 type 为 sync。如果有多个方法需要配置超时时间,并且超时时间都相同,也可以设置全局的超时时间。

<!-- 消费方批量配置超时时间 -->
<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>

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 方式下配置超时属性是无效的。

<!-- 超时设置无效 -->
<sofa:reference interface="com.alipay.test.SampleService2" id="sampleService">
    <sofa:binding.bolt>
        <sofa:global-attrs test-url="127.0.0.1:12200"/>
        <!-- 此处方法名 service 为示例,需要替换成实际方法名 -->
        <sofa:method name="service" type="oneway" timeout="1000"/>
    </sofa:binding.bolt>
</sofa:reference>

callback 调用

callback 是一种异步回调的方式,消费方需要提供回调接口,在调用结束后,回调接口会被框架调用。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>

上面的 callback 接口是通过配置 class 的方式来实现的,SOFA 也提供了通过引用一个 Bean 的方式来实现 callback。

<!-- 使用 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 即可。

<!-- 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)

正整数,以毫秒为单位(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

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

0 (ms)

最大值为 30000 ms,超过这个值的配置将调整为 30000 ms。

BOLT 服务完整配置

BOLT 配置标签主要有两种:global-attrsmethod。如果 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>