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-attrs
和 method
两种,同时配置时,以 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 调用后的结果,只需要调用
SofaResponseFuture
的getResponse
方法即可。getResponse
方法的两个参数说明如下:第一个参数是超时时间,含义是调用线程等待的最长时间,负数表示无等待时间限制,零表示立即返回,单位是毫秒。
第二个参数代表是否清除
ThreadLocal
变量的值,如果设为 true,则返回 response 之前,先清除ThreadLocal
的值,避免内存泄漏。
Bolt 引用详细配置
除了各种调用方式之外,Bolt 还在消费方提供了各种配置选项,这些选项不太常用,列举如下:
配置项 | 类型 | 默认值 | 说明 |
| INTEGER | 1000 | 消费方连接超时时间。 单位:ms |
| INTEGER | -1 | 消费方连接数。 -1 代表不设置(默认为每个目标地址建立一个连接)。 |
| INTEGER | -1 | 消费方最大空闲时间。 -1 表示使用底层默认值(底层默认值为 0,表示永远不会有读 idle)。该配置也是心跳的时间间隔,当请求 idle 时间超过配置时间后,发送心跳到服务方。 |
| INTEGER | -1 | 消费方最大读空闲时间。 -1 表示使用底层默认值(底层默认值为 30)。如果 |
| INTEGER | 0 | reference 生成时,等待服务注册中心将地址推送到消费方的时间。 单位:ms 取值范围:[0, 30000] 取值超过 30000 时,默认调整为 30000 。 |