我想知道是否能够注入自定义的消息头到出站请求中,以携带额外的信息,而无需反序列化有效载荷来实现类似WCF提供的消息检查器的身份验证、验证或请求关联等功能?
我想知道是否能够注入自定义的消息头到出站请求中,以携带额外的信息,而无需反序列化有效载荷来实现类似WCF提供的消息检查器的身份验证、验证或请求关联等功能?
更新
在SDK v2中,您现在可以(相对容易地)修改可靠服务和演员的标头。请注意,在下面的示例中,为了简洁起见,一些包装器成员被省略。
客户端
我们使用ServiceProxyFactory
来创建代理,而不是静态的ServiceProxy
。然后,我们可以包装IServiceRemotingClientFactory
和IServiceRemotingClient
并拦截服务调用。同样的方法也可以用于ActorProxyFactory
。请注意,这会覆盖诸如WcfServiceRemotingProviderAttribute
之类的属性的行为,因为我们明确指定了客户端工厂。
_proxyFactory = new ServiceProxyFactory(c => new ServiceRemotingClientFactoryWrapper(
// we can use any factory here
new WcfServiceRemotingClientFactory(callbackClient: c)));
private class ServiceRemotingClientFactoryWrapper : IServiceRemotingClientFactory
{
private readonly IServiceRemotingClientFactory _inner;
public ServiceRemotingClientFactoryWrapper(IServiceRemotingClientFactory inner)
{
_inner = inner;
}
public async Task<IServiceRemotingClient> GetClientAsync(Uri serviceUri, ServicePartitionKey partitionKey, TargetReplicaSelector targetReplicaSelector,
string listenerName, OperationRetrySettings retrySettings, CancellationToken cancellationToken)
{
var client = await _inner.GetClientAsync(serviceUri, partitionKey, targetReplicaSelector, listenerName, retrySettings, cancellationToken).ConfigureAwait(false);
return new ServiceRemotingClientWrapper(client);
}
}
private class ServiceRemotingClientWrapper : IServiceRemotingClient
{
private readonly IServiceRemotingClient _inner;
public ServiceRemotingClientWrapper(IServiceRemotingClient inner)
{
_inner = inner;
}
public Task<byte[]> RequestResponseAsync(ServiceRemotingMessageHeaders messageHeaders, byte[] requestBody)
{
// use messageHeaders.AddHeader() here
return _inner.RequestResponseAsync(messageHeaders, requestBody);
}
public void SendOneWay(ServiceRemotingMessageHeaders messageHeaders, byte[] requestBody)
{
// use messageHeaders.AddHeader() here
_inner.SendOneWay(messageHeaders, requestBody);
}
}
服务器
继承自ServiceRemotingDispatcher
和ActorServiceRemotingDispatcher
以检查标题。
class CustomServiceRemotingDispatcher : ServiceRemotingDispatcher
{
public override async Task<byte[]> RequestResponseAsync(IServiceRemotingRequestContext requestContext, ServiceRemotingMessageHeaders messageHeaders, byte[] requestBody)
{
// read messageHeaders here
// or alternatively put them in an AsyncLocal<T> scope
// so they can be accessed down the call chain
return base.RequestResponseAsync(requestContext, messageHeaders, requestBody);
}
}
为了使用这个类,我们需要再次覆盖ServiceRemotingProviderAttribute
,通过直接创建通信侦听器来实现:class MyService : StatelessService
{
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
yield return new ServiceInstanceListener(context => new WcfServiceRemotingListener(context, new CustomServiceRemotingDispatcher());
}
}
ServiceInstanceListener
中,您创建了一个通信侦听器,所有远程通信侦听器(如 WcfServiceRemotingListener
)都接受消息处理程序作为构造函数参数。我已经使这段代码工作。请确保使用最新的 (v2) SDK。 - Eli Arbelreturn proxyFactory.CreateServiceProxy<IMyInterface>( new Uri("fabric:/myapp/myserviceService"), new ServicePartitionKey(0));
- Per我几周前在MSDN论坛上提出了同样的问题,但是那里没有得到回复。
我查看了客户端库的源代码,没有找到添加标头的方法。恐怕唯一的方法是将它们作为方法调用的一部分添加。这可以通过使用请求类作为方法参数并使用继承来完成(例如,具有标头[授权、客户端信息等]的RequestBase类)。然后,您必须确保这些标头对每个请求都设置好,可以通过包装所有调用或手动设置来实现。
非常希望Service Fabric团队能够进一步澄清。