通过 Reliable Services 在 Java 中进行服务远程处理Service remoting in Java with Reliable Services

对于不依赖于特定的通信协议或堆栈的服务,如 WebAPI、Windows Communication Foundation (WCF) 或其他服务,Reliable Services 框架提供一种远程处理机制,以便快速而轻松地为这些服务设置远程过程调用。For services that aren't tied to a particular communication protocol or stack, such as WebAPI, Windows Communication Foundation (WCF), or others, the Reliable Services framework provides a remoting mechanism to quickly and easily set up remote procedure calls for services. 本文讨论如何为使用 Java 编写的服务设置远程过程调用。This article discusses how to set up remote procedure calls for services written with Java.

为服务设置远程处理Set up remoting on a service

为服务设置远程处理包括两个简单步骤:Setting up remoting for a service is done in two simple steps:

  1. 为服务创建要实现的接口。Create an interface for your service to implement. 此接口定义可供服务的远程过程调用使用的方法。This interface defines the methods that are available for a remote procedure call on your service. 这些方法必须是返回任务的异步方法。The methods must be task-returning asynchronous methods. 此接口必须实现 microsoft.serviceFabric.services.remoting.Service 以表明此服务具有远程处理接口。The interface must implement microsoft.serviceFabric.services.remoting.Service to signal that the service has a remoting interface.
  2. 在服务中使用远程处理侦听器。Use a remoting listener in your service. 这是可以提供远程处理功能的 CommunicationListener 实现。This is an CommunicationListener implementation that provides remoting capabilities. 可使用 FabricTransportServiceRemotingListener 和默认远程处理传输协议来创建远程处理侦听器。FabricTransportServiceRemotingListener can be used to create a remoting listener using the default remoting transport protocol.

例如,以下无状态服务公开了一个方法,此方法通过远程过程调用获取“Hello World”。For example, the following stateless service exposes a single method to get "Hello World" over a remote procedure call.

import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import java.util.List;
import microsoft.servicefabric.services.communication.runtime.ServiceInstanceListener;
import microsoft.servicefabric.services.remoting.Service;
import microsoft.servicefabric.services.runtime.StatelessService;

public interface MyService extends Service {
    CompletableFuture<String> helloWorldAsync();
}

class MyServiceImpl extends StatelessService implements MyService {
    public MyServiceImpl(StatelessServiceContext context) {
       super(context);
    }

    public CompletableFuture<String> helloWorldAsync() {
        return CompletableFuture.completedFuture("Hello!");
    }

    @Override
    protected List<ServiceInstanceListener> createServiceInstanceListeners() {
        ArrayList<ServiceInstanceListener> listeners = new ArrayList<>();
        listeners.add(new ServiceInstanceListener((context) -> {
            return new FabricTransportServiceRemotingListener(context,this);
        }));
        return listeners;
    }
}

备注

服务接口中的参数和返回类型可以是任何简单、复杂或自定义的类型,但它们必须可序列化。The arguments and the return types in the service interface can be any simple, complex, or custom types, but they must be serializable.

调用远程服务的方法Call remote service methods

若要使用远程处理堆栈在服务上调用方法,可以通过 microsoft.serviceFabric.services.remoting.client.ServiceProxyBase 类对此服务使用本地代理。Calling methods on a service by using the remoting stack is done by using a local proxy to the service through the microsoft.serviceFabric.services.remoting.client.ServiceProxyBase class. ServiceProxyBase 方法通过使用此服务实现的相同接口来创建本地代理。The ServiceProxyBase method creates a local proxy by using the same interface that the service implements. 使用此代理,只需在此接口上远程调用方法。With that proxy, you can simply call methods on the interface remotely.


MyService helloWorldClient = ServiceProxyBase.create(MyService.class, new URI("fabric:/MyApplication/MyHelloWorldService"));

CompletableFuture<String> message = helloWorldClient.helloWorldAsync();

此远程处理框架将服务引发的异常传播到客户端。The remoting framework propagates exceptions thrown at the service to the client. 因此,在客户端使用 ServiceProxyBase 的异常处理逻辑可直接处理服务引发的异常。So exception-handling logic at the client by using ServiceProxyBase can directly handle exceptions that the service throws.

服务代理生存期Service Proxy Lifetime

由于 ServiceProxy 创建是轻量型操作,因此可根据需求随意创建,数目不限。ServiceProxy creation is a lightweight operation, so you can create as many as you need. 如有需要,可重复使用服务代理实例。Service Proxy instances can be reused as long as they are needed. 如果远程过程调用引发了异常,仍可以重复使用相同的代理实例。If a remote procedure call throws an Exception, you can still reuse the same proxy instance. 每个 ServiceProxy 都包含用于通过线路发送消息的通信客户端。Each ServiceProxy contains a communication client used to send messages over the wire. 进行远程调用时,会在内部执行检查,以确认通信客户端是否有效。While invoking remote calls, internal checks are performed to determine if the communication client is valid. 根据这些检查的结果,将创建通信客户端(如有必要)。Based on the results of those checks, the communication client is recreated if needed. 因此,如果发生异常,无需重新创建 ServiceProxyTherefore, if an exception occurs, you do not need to recreate ServiceProxy.

ServiceProxyFactory 生存期ServiceProxyFactory Lifetime

FabricServiceProxyFactory 是为不同远程接口创建代理的工厂。FabricServiceProxyFactory is a factory that creates proxy for different remoting interfaces. 如果使用 API ServiceProxyBase.create创建代理,则框架创建 FabricServiceProxyFactoryIf you use API ServiceProxyBase.create for creating proxy, then framework creates a FabricServiceProxyFactory. 在需要替代 ServiceRemotingClientFactory 属性时,手动创建一个 FabricServiceProxyFactory 是有用的。It is useful to create one manually when you need to override ServiceRemotingClientFactory properties. Factory 是一项高成本操作。Factory is an expensive operation. FabricServiceProxyFactory 维护通信客户端的缓存。FabricServiceProxyFactory maintains cache of communication clients. 最佳做法是尽可能久地缓存 FabricServiceProxyFactoryBest practice is to cache FabricServiceProxyFactory for as long as possible.

远程异常处理Remoting Exception Handling

服务 API 引发的所有远程异常都作为 RuntimeException 或 FabricException 发送回客户端。All the remote exception thrown by service API, are sent back to the client either as RuntimeException or FabricException.

ServiceProxy 对为其创建的服务分区,处理所有故障转移异常。ServiceProxy does handle all Failover Exception for the service partition it is created for. 如果存在故障转移异常(非暂时异常),它将重新解析终结点,并通过正确的终结点重试调用。It re-resolves the endpoints if there is Failover Exceptions(Non-Transient Exceptions) and retries the call with the correct endpoint. 故障转移异常的重试次数无限。Number of retries for failover Exception is indefinite. 在 TransientExceptions 情况下,它仅重试调用。In case of TransientExceptions, it only retries the call.

默认重试参数由 OperationRetrySettings 提供。Default retry parameters are provied by OperationRetrySettings. 可以通过将 OperationRetrySettings 对象传递给 ServiceProxyFactory 构造函数来配置这些值。You can configure these values by passing OperationRetrySettings object to ServiceProxyFactory constructor.

后续步骤Next steps