我们有两个Service Fabric无状态服务。我们已经将服务结构运行时升级到最新版本,现在希望使用最新的V2(V2_1)运行时进行通信。我们还将Service Fabric SDK升级到了最新版本。
这两个服务可以使用最新的V2(V2_1)运行时相互通信。 我们还有另一个应用程序,即WinForm应用程序,该应用程序想要调用EvilMathTeacherService使其变得邪恶。问题是,当我们使用V2(V2_1)运行时从位于结构群集之外的Winform应用程序对服务结构服务进行调用时,它不起作用。它什么也没做。
所以我的问题是-我能做些什么来实现它?还是没有办法在最新的V2(V2_1)运行时中从外部与服务进行通信?我们可以使用V1运行时来做到这一点,并且在旧的V1运行时中完全可以。
代码示例:(相关部分)
服务1:MathService.cs
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[]
{
new ServiceInstanceListener(
context => new FabricTransportServiceRemotingListener(
context,
_mathCalculator_v2,
new FabricTransportRemotingListenerSettings()
{
EndpointResourceName = "MathCalculator_v2"
}),
"MathCalculator_v2"),
new ServiceInstanceListener(
context => new FabricTransportServiceRemotingListener(
context,
_textManipulator_v2,
new FabricTransportRemotingListenerSettings()
{
EndpointResourceName = "TextManipulator_v2"
}),
"TextManipulator_v2")
};
}
ServiceManifest:
<Resources>
<Endpoints>
<!-- This endpoint is used by the communication listener to obtain the port on which to
listen. Please note that if your service is partitioned, this port is shared with
replicas of different partitions that are placed in your code. -->
<Endpoint Name="ServiceEndpointV2_1" />
</Endpoints>
服务2:EvilMathTeacherService.cs
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[]
{
new ServiceInstanceListener(
context => new FabricTransportServiceRemotingListener(
context,
_questionnaire,
new FabricTransportRemotingListenerSettings()
{
EndpointResourceName = "Questionnaire_v2"
}),
"Questionnaire_v2")
};
}
在RunAsync方法中:
protected override async Task RunAsync(CancellationToken cancellationToken)
{
// TODO: Replace the following sample code with your own logic
// or remove this RunAsync override if it's not needed in your service.
long iterations = 0;
while (true)
{
cancellationToken.ThrowIfCancellationRequested();
ServiceEventSource.Current.ServiceMessage(this.Context, "Evil teacher is coming to get you!-{0}", ++iterations);
Random r = new Random();
int first = r.Next(0, 100);
var second = r.Next(200, 400);
try
{
var sum = await _questionnaire.AddTwoNumbers(first, second);
ServiceEventSource.Current.ServiceMessage(this.Context, "Evil Math teacher says - Sum-{0}", sum);
var ifEqual = await _questionnaire.CheckIfTwoNumbersAreEqual(first, second);
ServiceEventSource.Current.ServiceMessage(this.Context, "Evil Math teacher says - If Equal-{0}", ifEqual);
}
catch (Exception ex)
{
throw;
}
await Task.Delay(TimeSpan.FromSeconds(2), cancellationToken);
}
}
这是正在调用MathService的Questionnaire.cs类
public async Task<int> AddTwoNumbers(int a, int b)
{
var uri = new Uri("fabric:/SampleSFV2/MathService");
var proxyFactory = new ServiceProxyFactory((c) =>
{
var settings = new FabricTransportRemotingSettings();
return new FabricTransportServiceRemotingClientFactory(settings);
});
var service = proxyFactory.CreateServiceProxy<IMathCalculator>(uri, listenerName: "MathCalculator_v2");
return await service.Add(a, b);
}
public async Task<bool> CheckIfTwoNumbersAreEqual(int a, int b)
{
var text1 = a.ToString();
var text2 = b.ToString();
var uri = new Uri("fabric:/SampleSFV2/MathService");
var proxyFactory = new ServiceProxyFactory((c) =>
{
var settings = new FabricTransportRemotingSettings();
return new FabricTransportServiceRemotingClientFactory(settings);
});
var service = proxyFactory.CreateServiceProxy<ITextManipulator>(uri, listenerName: "TextManipulator_v2");
return await service.IfEqual(text1, text2);
}
这按预期工作。但是,当我从Winform应用程序向EvilMathTeacherService或MathService本身进行类似调用时,该调用似乎并没有到达服务。
Winform应用程序部分: Form1.cs
private async void button_AddNumbers_Click(object sender, EventArgs e)
{
//int number1 = int.Parse(textBox_Number1.Text);
//int number2 = int.Parse(textBox_Number2.Text);
//var uri = _evilMathServiceUri;
int number1 = 10;
int number2 = 100;
var uri = new Uri("fabric:/SampleSFV2/EvilMathTeacherService");
ServiceProxyFactory proxyFactory = new ServiceProxyFactory((c) =>
{
FabricTransportRemotingSettings settings = new FabricTransportRemotingSettings();
return new FabricTransportServiceRemotingClientFactory(settings);
});
try
{
IQuestionnaire service = proxyFactory.CreateServiceProxy<IQuestionnaire>(uri, listenerName: "Questionnaire_v2");
int result = await service.AddTwoNumbers(number1, number2);
MessageBox.Show("Result= " + result);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
我正在从他们的官方文档中跟踪此链接- https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-communication-remoting#how-to-use-remoting-v2-stack
请指出我在这里缺少的任何内容。再次声明-使用Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Runtime从光纤网络群集之外的Winform应用程序调用服务时遇到问题。
还是不能再使用V2运行时来做到这一点?因为我们使用V1运行时成功地做了同样的事情。
示例代码项目:
答案 0 :(得分:0)
首先要澄清一些混乱,没有“ V1 Service Fabric运行时”或“ V2 Service Fabric运行时”。您看到的是服务远程处理,它是Service Fabric(客户端上的Microsoft.ServiceFabric.Services.Remoting名称空间和ServiceProxyFactory)的.NET RPC实现。
默认情况下,服务远程仅在群集内的服务之间起作用,因为它使用临时范围内的随机分配的端口(假定客户端-服务器之间具有直接连接)。如果您之间有一个NAT设备(如负载平衡器)需要显式打开端口,则此操作将无效。
服务远程处理在Service Fabric中是完全可选的,您不必使用它。对于客户端通信,强烈建议您不要使用它,因为它会将客户端应用程序紧密耦合到后端服务(甚至具有共享程序集),并且以后对API进行版本控制将是一场噩梦。 。我建议在SF服务中使用ASP.NET Core,以将HTTP API公开给WebForms应用程序。