问题
I'm creating a stateless service inside Azure Service Fabric. However, once service starts (or on start of custom communication listener) I need to get addresses of all other instances/partitions of that service.
I'm doing so by creating new FabricClient
and calling fabricClient.QueryManager.GetPartitionListAsync(serviceUri)
. However I'm getting FabricServiceNotFoundException
with message Service does not exist. when a first service instance starts running.
I couldn't find that in documentation, so my question is: how can I get a list of listening endpoint addresses for all active instances of a particular service, running in Azure Service Fabric, when a new instance of that service starts running?
回答1:
Endpoint addresses are actually on service replicas and instances - those are the things that are actually placed on nodes. There is a special method for this in the ServiceManagerClient called ResolveServicePartitionAsync.
In the Reliable Services SDK (in the Microsoft.ServiceFabric.Services.Client namespace) we provide a resolver utility that makes this a bit easier:
ServicePartitionResolver resolver = ServicePartitionResolver.GetDefault();
ResolvedServicePartition partition =
await resolver.ResolveAsync(new Uri("fabric:/MyApp/MyService"), new ServicePartitionKey(), cancellationToken);
The Endpoints property of ResolvedServicePartition is a list of each replica/instance in the partition. The Address property will contain a JSON object, which is a list of key-value pairs containing each listener that's opened by the replica/instance:
{
"Endpoints" :
{ "mylistener1" : "some-address" },
{ "mylistener2" : "some-address" }
...
}
Keep in mind that there's no guaranteed order for when replicas/instances come up, so you may need to retry a few times. Also, replicas and instances will move at times throughout the service's lifetime, so you'll need to keep the list up to date. Basically you can't really just get all this information up front in one go and be set because it's a very dynamic system.
See here for an overview: https://azure.microsoft.com/en-us/documentation/articles/service-fabric-connect-and-communicate-with-services/
And here for more detailed information: https://azure.microsoft.com/en-us/documentation/articles/service-fabric-reliable-services-communication/
回答2:
I'm new to commenting on StackOverflow but here is how I did my service resolution. I ended up making a small library to take care of it.
ResolvedServicePartition partition = await fabricClient.ServiceManager.ResolveServicePartitionAsync("fabric:/Application1/Service1");
// This "endpoint" looks something like this: {\"Endpoints\":{\"\":\"http:\/\/localhost:8448\/\"}}
string randomConfigStoreEndpointJson = partition.GetEndpoint().Address;
// Use Newtonsoft.Json to parse this mess, since JavaScriptSerializer isn't up to the job
JObject endpointObject = JObject.Parse(randomConfigStoreEndpointJson);
// This is the only way I could actually extract the baseUrl without regular expressions
string actualEndpointBaseUrl = endpointObject["Endpoints"].First.First.ToString();
@DannyMeister This takes care of parsing that odd endpoint JSON syntax.
This also works to resolve a stateful service with only one partition. To resolve a stateful service with multiple partitions, you must figure out the partitionKey on the client, then call await fabricClient.ServiceManager.ResolveServicePartitionAsync("fabric:/Application1/Service1", statefulPartitionKey);
instead!
来源:https://stackoverflow.com/questions/38036140/get-all-active-service-instances-on-service-start