Reputation: 60741
I am following a tutorial from [this book]:
I am getting the following exception:
There's no doubt that my nodes are running fine:
Here's how my stateless service is setup:
internal sealed class MyStatelessService : StatelessService
{
public MyStatelessService(StatelessServiceContext context)
: base(context)
{ }
/// <summary>
/// Optional override to create listeners (e.g., TCP, HTTP) for this service replica to handle client or user requests.
/// </summary>
/// <returns>A collection of listeners.</returns>
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[0];
}
/// <summary>
/// This is the main entry point for your service instance.
/// </summary>
/// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service instance.</param>
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, "Working-{0}", ++iterations);
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
}
}
}
The way I deploy and get this exception:
What am I doing wrong? How can I get my client connected to my cluster?
The entire solution can be viewed here.
Upvotes: 2
Views: 681
Reputation: 5302
Two things:
Your ICalculatorService
have to be defined in another library project, in order to be shared between your stateless service library and your client project. So:
MyStatelessService.Interfaces
Microsoft.ServiceFabric.Services.Remoting
ICalculatorService
ICalculatorService
from your other two projectsMyStatelessService.Interfaces
to your client application and your stateless service library.ICalculatorService
ICalculatorService
should be referenced from the same libraryYour client will be:
using Microsoft.ServiceFabric.Services.Remoting.Client;
using MyStatelessService.Interfaces;
using System;
static void Main(string[] args)
{
var calculatorClient = ServiceProxy.Create<ICalculatorService>
(new Uri("fabric:/CalculatorService/MyStatelessService"));
var result = calculatorClient.Add(1, 2).Result;
Console.WriteLine(result);
Console.ReadKey();
}
Change your MyStatelessService
's Program.cs
part after the try
statement with this:
ServiceRuntime.RegisterServiceAsync("MyStatelessServiceType",
context => new CalculatorService(context)).GetAwaiter().GetResult();
ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(CalculatorService).Name);
Instead of CalculatorService
, you were referencing MyStatelessService
.
Upvotes: 2
Reputation: 731
When creating your stateless service you called your service MyStatelessService
instead of CalculatorService
and you called your application CalculatorService
instead of CalculatorApplication
. As the book states at step 1 under 'The first version' "Create a new Service Fabric application named CalculatorApplication with a service named CalculatorService". You created an application named CalculatorService
and a service called MyStatelessService
. You then made a new service file within the stateless service project. You should never create a new service within a service. Use the generated service.cs
(MyStatelessService.cs
in your case) file instead. One way to solve your problem is to copy the implementation of CalculatorService
into your stateless service and delete CalculatorService.cs
. Your stateless service will be:
internal sealed class MyStatelessService: StatelessService, ICalculatorService
{
public MyStatelessService(StatelessServiceContext serviceContext) : base(serviceContext)
{
}
public Task<int> Add(int a, int b)
{
return Task.FromResult<int>(a + b);
}
public Task<int> Subtract(int a, int b)
{
return Task.FromResult<int>(a - b);
}
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[] { new ServiceInstanceListener(context => this.CreateServiceRemotingListener(context)) };
}
}
However, it's unconventional to call an application 'service', so I'd recommend to create a new project and paste your current implementation into it.
When creating a new project, name your application CalculatorApplication.
And then create the service with the name CalculatorService.
Your CalculatorService.cs
file is made automatically, so just paste your current implementation into it. (The same as MyStatelessService above, but with the name CalculatorService.)
Upvotes: 0
Reputation: 11470
You're attempting to access your service through remoting, but your service is not enabled for remoting.
You need to return a communication listener from CreateServiceInstanceListeners
and implement IService
.
Upvotes: 2