- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个简单的 Service Fabric 群集,我想在其中从无状态 ASP.NET Core 2.0 Web API 调用无状态服务。
我做的第一件事是创建一个具有简单接口(interface)和 DTO 的 .NET Standard 2.0 类库:
public interface IMicroService : IService
{
Task<MyDto> GetMahDto(int id);
}
public class MyDto
{
public string Name { get; set; }
}
然后,我用它创建了一个 NuGet 包,并将该包作为依赖项添加到我的 Web API(MyServiceApi 项目)和无状态服务 (MyService)。
服务的监听器定义为
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
var fabricListener = new ServiceInstanceListener((context) =>
{
var fabricRemotingListener = new FabricTransportServiceRemotingListener(
serviceContext: context,
serviceRemotingMessageHandler: null,
remotingListenerSettings: new Microsoft.ServiceFabric.Services.Remoting.FabricTransport.Runtime.FabricTransportRemotingListenerSettings()
{
EndpointResourceName = "myendpoint"
},
serializationProvider: null);
return fabricRemotingListener;
},
"mylistener");
return new ServiceInstanceListener[] { fabricListener };
}
接口(interface)实现很简单
public Task<MyDto> GetMahDto(int id)
{
return Task.FromResult(new MyDto() { Name=$"Hallo from TheService in FabricSandbox3 project, id: {id}" });
}
在 MyServiceApi 中,我有一个看起来像这样的 Controller 方法
[HttpGet]
public async Task<MyDto> Get()
{
var svc = ServiceProxy.Create<ContractsStandard.IMicroService>(new Uri("fabric:/FabricSandbox4/TheService"), listenerName: "mylistener");
return await svc.GetMahDto(23);
}
当我启动调试器时,我可以单步执行 MyServiceApi 的 Controller 方法,但它会抛出以下异常:
System.AggregateException:“发生一个或多个错误。 (异常 System.ArgumentException 在服务上未处理,无法序列化以传输到客户端。详细的远程异常信息:System.ArgumentException:找不到此 Id 的接口(interface) -488762776 在 Microsoft.ServiceFabric.Services.Remoting.V2.ServiceRemotingMessageSerializersManager.GetInterfaceDetails(Int32 interfaceId) 在 Microsoft.ServiceFabric.Services.Remoting.V2.ServiceRemotingMessageSerializersManager.CreateSerializers(Int32 InterfaceId) 在 System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func
2 valueFactory) 在 Microsoft.ServiceFabric.Services.Remoting.V2.ServiceRemotingMessageSerializersManager.GetRequestBodySerializer(Int32 interfaceId) 在 Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Runtime.FabricTransportMessageHandler.CreateRemotingRequestMessage(FabricTransportMessage FabricTransportMessage,秒表秒表) 在 Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Runtime.FabricTransportMessageHandler.d__7.MoveNext())'
我在诊断事件中没有发现任何看起来有希望的内容,而且我所看到的类似问题(在此站点和其他地方)的唯一提及通常涉及不同程序集中的类型,鉴于此,这不是问题共享接口(interface)包含在 NuGet 包中。
有什么想法我可能会出错吗?
最佳答案
请参阅此答案的底部以直接找到最终解决方案。
我找到了一个部分令人满意的答案。但是,我并不完全知道它为什么有效。我偶然发现这一点纯属偶然。我一直在研究一种通过结构请求无缝传递 header 的方法,这就是我最终实现这一点的方法。
引用上面的监听器代码,特别注意这一行:
serviceRemotingMessageHandler: null,
为了使其正常工作,我创建了自己的 IServiceRemotingMessageHandler 实现。请注意,它只是将调用委托(delegate)给基本类型:
class TestRemotingDispatcher : ServiceRemotingMessageDispatcher, IServiceRemotingMessageHandler
{
public TestRemotingDispatcher(
ServiceContext serviceContext, IService serviceImplementation, IServiceRemotingMessageBodyFactory serviceRemotingMessageBodyFactory = null) :
base(serviceContext, serviceImplementation, serviceRemotingMessageBodyFactory)
{
}
public override void HandleOneWayMessage(IServiceRemotingRequestMessage requestMessage)
{
base.HandleOneWayMessage(requestMessage);
}
public override Task<IServiceRemotingResponseMessageBody> HandleRequestResponseAsync(
ServiceRemotingDispatchHeaders requestMessageDispatchHeaders, IServiceRemotingRequestMessageBody requestMessageBody, CancellationToken cancellationToken)
{
return base.HandleRequestResponseAsync(requestMessageDispatchHeaders, requestMessageBody, cancellationToken);
}
public override Task<IServiceRemotingResponseMessage> HandleRequestResponseAsync(IServiceRemotingRequestContext requestContext, IServiceRemotingRequestMessage requestMessage)
{
return base.HandleRequestResponseAsync(requestContext, requestMessage);
}
}
然后监听器就变成了
var fabricListener = new ServiceInstanceListener((context) =>
{
var fabricRemotingListener = new FabricTransportServiceRemotingListener(
serviceContext: context,
serviceRemotingMessageHandler: new TestRemotingDispatcher(context, this),
remotingListenerSettings: new Microsoft.ServiceFabric.Services.Remoting.FabricTransport.Runtime.FabricTransportRemotingListenerSettings()
{
EndpointResourceName = "mngendpoint"
},
serializationProvider: null);
return fabricRemotingListener;
},
"mnglistener");
这按预期工作。如果我弄清楚原因,我会更新。
编辑:我还没有弄清楚为什么显式分配 serviceRemotingMessageHandler 有效,但上面显示的 ServiceRemotingMessageDispatcher 的子类型不是必需的。它将通过分配内置实现来工作:
serviceRemotingMessageHandler: new ServiceRemotingMessageDispatcher(context, serviceInstance)
最终解释
这一切都归咎于我的错误。请注意,我首先将 null 分配给 serviceRemotingMessageHandler,这是不正确的。查看源代码后,有一个构造函数将为您创建一个调度程序。通过按照我的方式分配 null,监听器中不存在调度程序。
public FabricTransportServiceRemotingListener(
ServiceContext serviceContext,
IService serviceImplementation,
FabricTransportRemotingListenerSettings remotingListenerSettings = null,
IServiceRemotingMessageSerializationProvider serializationProvider = null)
: this(
serviceContext,
new ServiceRemotingMessageDispatcher(
serviceContext,
serviceImplementation,
GetMessageBodyFactory(serializationProvider, remotingListenerSettings)),
remotingListenerSettings,
serializationProvider)
{
}
异常消息肯定让我走上了错误的道路,但至少对(自己造成的)问题有一个很好的解释。
关于azure - Service Fabric : System. ArgumentException:找不到具有此 ID 的接口(interface) -488762776,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51735285/
例如,我有一个父类Author: class Author { String name static hasMany = [ fiction: Book,
代码如下: dojo.query(subNav.navClass).forEach(function(node, index, arr){ if(dojo.style(node, 'd
我有一个带有 Id 和姓名的学生表和一个带有 Id 和 friend Id 的 Friends 表。我想加入这两个表并找到学生的 friend 。 例如,Ashley 的 friend 是 Saman
我通过互联网浏览,但仍未找到问题的答案。应该很容易: class Parent { String name Child child } 当我有一个 child 对象时,如何获得它的 paren
我正在尝试创建一个以 Firebase 作为我的后端的社交应用。现在我正面临如何(在哪里?)找到 friend 功能的问题。 我有每个用户的邮件地址。 我可以访问用户的电话也预订。 在传统的后端中,我
我主要想澄清以下几点: 1。有人告诉我,在 iOS 5 及以下版本中,如果您使用 Game Center 设置多人游戏,则“查找 Facebook 好友”(如与好友争夺战)的功能不是内置的,因此您需要
关于redis docker镜像ENTRYPOINT脚本 docker-entrypoint.sh : #!/bin/sh set -e # first arg is `-f` or `--some-
我是一名优秀的程序员,十分优秀!