We have two Service Fabric stateless services. We have upgraded our service fabric runtime to the latest version and now want to use the latest V2(V2_1) runtime for communication. We have also upgraded the Service Fabric SDK to the latest version.
- MathService. It has two endpoints exposed to communication.
- EvilMathTeacherService. It calls those two endpoints to do some things. It also has an endpoint exposed.
These two services can talk to each other using the latest V2(V2_1) runtime. We have another application, a WinForm application, that wants to call the EvilMathTeacherService to make it do something evil. Problem is when we use the V2(V2_1) runtime to make the call to the service fabric service/s from this Winform application which resides outside the fabric cluster, it does not work. It does not do anything.
So my question would be- is there anything I can do to make it happen? Or is there no way to communicate to the services from outside in the latest V2(V2_1) runtime? We are able to do this using the V1 runtime and it's perfectly fine in the old V1 runtime.
Code sample: (Relevant portion)
Service 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>
Service 2: EvilMathTeacherService.cs
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[]
{
new ServiceInstanceListener(
context => new FabricTransportServiceRemotingListener(
context,
_questionnaire,
new FabricTransportRemotingListenerSettings()
{
EndpointResourceName = "Questionnaire_v2"
}),
"Questionnaire_v2")
};
}
In the RunAsync Method:
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);
}
}
This is the Questionnaire.cs class that's making the call to the MathService
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);
}
This is working as expected. But when I make a similar call from my winform application to the EvilMathTeacherService or the MathService itself, the call doesn't seem to make it to the services.
Winform application portion: 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());
}
}
I am following this link from their official documentation- https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-communication-remoting#how-to-use-remoting-v2-stack
Please point out anything I am missing here. To assert again - I am having the problem when calling the services from a Winform application outside the fabric cluster using the Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Runtime.
Or this cannot be done using the V2 runtime anymore? Because we are doing the same thing successfully using the V1 runtime.
Sample code project:
FabricTransportServiceRemotingClientFactory
from the V2 namespace? docs.microsoft.com/en-us/dotnet/api/… – LoekDsettings.UseWrappedMessage = true;
– LoekD