internal static unsafe ResolvedServiceEndpoint CreateFromNative(IntPtr endpointIntPtr) { var endpoint = new ResolvedServiceEndpoint(); var nativeEndpoint = (NativeTypes.FABRIC_RESOLVED_SERVICE_ENDPOINT *)endpointIntPtr; string address = NativeTypes.FromNativeString(nativeEndpoint->Address); endpoint.Address = address; endpoint.Role = (ServiceEndpointRole)nativeEndpoint->Role; return(endpoint); }
private async Task ProcessInputRequest(HttpListenerContext context, CancellationToken cancelRequest) { String output = null; try { string vin = context.Request.QueryString["vin"]; // The partitioning scheme of the processing service is a range of integers from 0 - 25. // This generates a partition key within that range by converting the first letter of the input name // into its numerica position in the alphabet. char firstLetterOfLastName = vin.First(); int partitionKey = Char.ToUpper(firstLetterOfLastName) - 'A'; // Get the Service Partition ResolvedServicePartition partition = await this.servicePartitionResolver.ResolveAsync(clientServiceUri, partitionKey, cancelRequest); ResolvedServiceEndpoint ep = partition.GetEndpoint(); JObject addresses = JObject.Parse(ep.Address); string primaryReplicaAddress = addresses["Endpoints"]["Gateway"].Value <string>(); string url = primaryReplicaAddress + "api/vehicles/" + vin + "/lock"; UriBuilder primaryReplicaUriBuilder = new UriBuilder(url); string result = await this.httpClient.GetStringAsync(primaryReplicaUriBuilder.Uri); output = String.Format( "Result: {0}. Partition key: '{1}' generated from the first letter '{2}' of input value '{3}'.", result, partitionKey, firstLetterOfLastName, vin); } catch (Exception ex) { output = ex.Message; } using (HttpListenerResponse response = context.Response) { if (output != null) { byte[] outBytes = Encoding.UTF8.GetBytes(output); response.OutputStream.Write(outBytes, 0, outBytes.Length); } } }
/// <summary> /// Gets the first endpoint from the array of endpoints within a ResolvedServiceEndpoint. /// </summary> /// <param name="rse">ResolvedServiceEndpoint instance.</param> /// <returns>String containing the replica address.</returns> /// <exception cref="InvalidProgramException">ResolvedServiceEndpoint address list coudln't be parsed or no endpoints exist.</exception> public static string GetFirstEndpoint(this ResolvedServiceEndpoint rse) { ServiceEndpointCollection sec = null; if (ServiceEndpointCollection.TryParseEndpointsString(rse.Address, out sec)) { string replicaAddress; if (sec.TryGetFirstEndpointAddress(out replicaAddress)) { return(replicaAddress); } } throw new InvalidProgramException("ResolvedServiceEndpoint had invalid address"); }
public async Task <string> GetServiceEndpoint(string cluster, Uri serviceInstanceUri, string serviceEndpointName, CancellationToken token) { FabricClient fabricClient = this.GetClient(cluster); // this resolution may return a stale address if the service moved recently. // However, for a single-partition stateless services it shouldn't matter because each instance will publish the same address. ResolvedServicePartition rsp = await fabricClient.ServiceManager.ResolveServicePartitionAsync(serviceInstanceUri, this.readOperationTimeout, token); ResolvedServiceEndpoint endpoint = rsp.GetEndpoint(); // This assumes the service uses the Reliable Services framework, // where the endpoint is always a JSON object that can contain multiple endpoints. JObject endpointJson = JObject.Parse(endpoint.Address); return(endpointJson["Endpoints"][serviceEndpointName].Value <string>()); }
public CommunicationClientCacheEntry <TCommunicationClient> GetOrAddClientCacheEntry( ResolvedServiceEndpoint endpoint, string listenerName, ResolvedServicePartition rsp) { var key = new PartitionClientCacheKey(endpoint, listenerName); return(this.cache.GetOrAdd( key, new CommunicationClientCacheEntry <TCommunicationClient>() { Endpoint = endpoint, ListenerName = listenerName, Rsp = rsp })); }
private async Task RewriteRequestUriAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var resolver = new ServicePartitionResolver(() => new FabricClient()); // // Resolve service endpoint // ResolvedServiceEndpoint endpoint = null; if (_computePartitionKeyAsLong != null) { var partition = await resolver.ResolveAsync(_serviceName, _computePartitionKeyAsLong(request), cancellationToken); endpoint = partition.Endpoints.First(p => p.Role == ServiceEndpointRole.StatefulPrimary); } else if (_computePartitionKeyAsString != null) { var partition = await resolver.ResolveAsync(_serviceName, _computePartitionKeyAsString(request), cancellationToken); endpoint = partition.Endpoints.First(p => p.Role == ServiceEndpointRole.StatefulPrimary); } else { var partition = await resolver.ResolveAsync(_serviceName, cancellationToken); endpoint = partition.Endpoints.First(p => p.Role == ServiceEndpointRole.Stateless); } // // Parse the endpoint // dynamic address = JsonConvert.DeserializeObject(endpoint.Address); string urlString = address.Endpoints[""]; Uri url = new Uri(urlString, UriKind.Absolute); // // Rewrite request URL // var builder = new UriBuilder(request.RequestUri) { Scheme = url.Scheme, Host = url.Host, Port = url.Port }; request.RequestUri = builder.Uri; }
private async Task <string> ResolveApiAddress() { //Warning: Very simplistic/optimistic implementation //This demo uses only 1 partition. Other stateful services might have more.. ServicePartitionResolver resolver = ServicePartitionResolver.GetDefault(); ResolvedServicePartition partition = await resolver.ResolveAsync( new Uri("fabric:/TrafficServiceFabric/TrafficApi"), new ServicePartitionKey(0), CancellationToken.None); ResolvedServiceEndpoint endpoint = partition.GetEndpoint(); JObject addresses = JObject.Parse(endpoint.Address); string address = (string)addresses["Endpoints"].First(); return(address); }
protected override Task <CommunicationClient> CreateClientAsync( ResolvedServiceEndpoint endpoint, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(endpoint.Address) || !endpoint.Address.StartsWith("http")) { throw new InvalidOperationException("The endpoint address is not valid. Please resolve again."); } string endpointAddress = endpoint.Address; if (!endpointAddress.EndsWith("/")) { endpointAddress = endpointAddress + "/"; } // Create a communication client. This doesn't establish a session with the server. return(Task.FromResult(new CommunicationClient(new Uri(endpointAddress), this.OperationTimeout, this.ReadWriteTimeout))); }
public void Constructor_SetClientProperties() { string listenerName = nameof(Constructor_SetClientProperties); ResolvedServiceEndpoint endpoint = MockQueryPartitionFactory.CreateResolvedServiceEndpoint(string.Empty); ResolvedServicePartition partition = MockQueryPartitionFactory.CreateResolvedServicePartition( new Uri("http://localhost"), new List <ResolvedServiceEndpoint>()); Mock <IServiceRemotingClient> clientMock = new Mock <IServiceRemotingClient>(); clientMock.SetupGet(c => c.ListenerName).Returns(listenerName); clientMock.SetupGet(c => c.Endpoint).Returns(endpoint); clientMock.SetupGet(c => c.ResolvedServicePartition).Returns(partition); ServiceRemotingClientWrapper wrapper = new ServiceRemotingClientWrapper(clientMock.Object); Assert.AreEqual(clientMock.Object, wrapper.Client); Assert.AreEqual(listenerName, wrapper.ListenerName); Assert.AreEqual(endpoint, wrapper.Endpoint); Assert.AreEqual(partition, wrapper.ResolvedServicePartition); }
/// <summary> /// Gets the endpoint from the array of endpoints using the listener name. /// </summary> /// <param name="rse">ResolvedServiceEndpoint instance.</param> /// <param name="name">Listener name.</param> /// <returns>String containing the replica address.</returns> /// <exception cref="ArgumentException">ResolvedServiceEndpoint address list coudln't be parsed.</exception> /// <exception cref="InvalidProgramException">ResolvedServiceEndpoint address list coudln't be parsed.</exception> public static string GetEndpoint(this ResolvedServiceEndpoint rse, string name) { ServiceEndpointCollection sec = null; if (ServiceEndpointCollection.TryParseEndpointsString(rse.Address, out sec)) { string replicaAddress; if (sec.TryGetEndpointAddress(name, out replicaAddress)) { return(replicaAddress); } else { throw new ArgumentException(nameof(name)); } } else { throw new InvalidProgramException("ResolvedServiceEndpoint had invalid address"); } }
public async Task <string> GetAPIResult() { String responseString = string.Empty; ResolvedServicePartition mypartition = await resolver.ResolveAsync(serviceUri, new ServicePartitionKey(), new CancellationToken()); ResolvedServiceEndpoint endpoint = mypartition.GetEndpoint(); JObject addresses = JObject.Parse(endpoint.Address); string address = (string)addresses["Endpoints"].First(); HttpClient client = new HttpClient(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, address + "/api/values"); HttpResponseMessage response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { responseString = await response.Content.ReadAsStringAsync(); } return(responseString); }
/// <summary> /// Calls a service endpoint with retries. /// </summary> /// <typeparam name="TResult">Type of the result.</typeparam> /// <param name="rsp">ResolvedServicePartition instance.</param> /// <param name="token">CancellationToken instance.</param> /// <param name="func">Fucntion to execute, actually makeing the HTTP request.</param> /// <returns>Result of the function execution.</returns> private async Task <TResult> CallAsync <TResult>(ResolvedServicePartition rsp, CancellationToken token, Func <ResolvedServiceEndpoint, CancellationToken, Task <TResult> > func) { TResult result = default(TResult); // Wrap in a retry policy. await _retryPolicy.ExecuteWithRetriesAsync(async (ct) => { try { ResolvedServiceEndpoint rse = rsp.GetEndpoint(); result = await func(rse, ct); } catch (FabricTransientException) { rsp = await GetRspAsync(((Int64RangePartitionInformation)rsp.Info).LowKey, token).ConfigureAwait(false); } catch (HttpRequestException ex) when((ex.InnerException as WebException)?.Status == WebExceptionStatus.ConnectFailure) { rsp = await GetRspAsync(((Int64RangePartitionInformation)rsp.Info).LowKey, token).ConfigureAwait(false); } }, cancellationToken : token); return(result); }
public async Task <(bool HasEndPoint, Dictionary <string, string> EndPoint)> GetServiceEndpoint(string serviceName, CancellationToken token) { var serviceInstanceUri = new Uri(serviceName); ResolvedServicePartition rsp = await fabricClient.ServiceManager.ResolveServicePartitionAsync(serviceInstanceUri, this.readOperationTimeout, token); ResolvedServiceEndpoint endpoint = rsp.GetEndpoint(); // This assumes the service uses the Reliable Services framework, // where the endpoint is always a JSON object that can contain multiple endpoints. JObject endpointJson = JObject.Parse(endpoint.Address); if (endpointJson["Endpoints"].HasValues) { var endpoints = new Dictionary <string, string>(); endpoints.Add("MCTypeEndpoint", endpointJson["Endpoints"]["MCTypeEndpoint"].Value <string>()); endpoints.Add("MCrcon", endpointJson["Endpoints"]["MCrcon"].Value <string>()); return(true, endpoints); } return(false, new Dictionary <string, string>()); }
/// <summary> /// Execute the HealthCheck request. /// </summary> /// <param name="hc">HealthCheck description.</param> /// <param name="partition">Partition instance.</param> /// <returns>HealthCheck instance.</returns> internal async Task <HealthCheck> ExecuteHealthCheckAsync(HealthCheck hc, Partition partition) { // Check passed parameters. if ((null == partition) || (default(HealthCheck) == hc)) { return(default(HealthCheck)); } // Get the service endpoint of the service being tested. ResolvedServiceEndpoint rse = await this.GetServiceEndpointAsync(hc.ServiceName, partition); if (null == rse) { return(default(HealthCheck)); } // If an endpoint name was specified, search for that name within the ResolvedServiceEndpoint instance. string baseAddress = (string.IsNullOrWhiteSpace(hc.Endpoint)) ? rse.GetFirstEndpoint() : rse.GetEndpoint(hc.Endpoint); Uri uri = new Uri($"{baseAddress}/{hc.SuffixPath}"); // Create the HttpRequest message. HttpRequestMessage request = this.CreateRequestMessage(hc, uri); try { bool success = true; HealthState hs = HealthState.Ok; // Make the request to the service being tested. Stopwatch sw = Stopwatch.StartNew(); HttpResponseMessage response = await this._http.SendAsync(request, HttpCompletionOption.ResponseContentRead, this._token); sw.Stop(); // Evaluate the result of the request. If specific codes were provided, check each of the code arrays to find the result code. if ((null != hc.WarningStatusCodes) && (hc.WarningStatusCodes.Contains((int)response.StatusCode))) { hs = HealthState.Warning; success = false; } else if ((null != hc.ErrorStatusCodes) && (hc.ErrorStatusCodes.Contains((int)response.StatusCode))) { hs = HealthState.Error; success = false; } else if (false == response.StatusCode.IsSuccessCode()) { hs = HealthState.Error; success = false; } // Report health result to Service Fabric. this.Client.HealthManager.ReportHealth(new PartitionHealthReport(hc.Partition, new HealthInformation("Watchdog Health Check", hc.Name, hs))); // Report the availability of the tested service to the telemetry provider. await this._telemetry.ReportAvailabilityAsync( hc.ServiceName.AbsoluteUri, hc.Partition.ToString(), hc.Name, hc.LastAttempt, TimeSpan.FromMilliseconds(hc.Duration), null, success, this._token); // Return a new HealthCheck instance containing the results of the request. long count = (success) ? 0 : hc.FailureCount + 1; return(hc.UpdateWith(DateTime.UtcNow, count, sw.ElapsedMilliseconds, response.StatusCode)); } catch (FabricTransientException ex) { ServiceEventSource.Current.Exception(ex.Message, ex.GetType().Name, nameof(this.ExecuteHealthCheckAsync)); return(hc.UpdateWith(DateTime.UtcNow, hc.FailureCount + 1, -1, System.Net.HttpStatusCode.InternalServerError)); } catch (Exception ex) { ServiceEventSource.Current.Exception(ex.Message, ex.GetType().Name, nameof(this.ExecuteHealthCheckAsync)); throw; } }
public PartitionClientCacheKey(ResolvedServiceEndpoint endpoint, string listenerName) { this.Endpoint = endpoint; this.ListenerName = listenerName; }
private static IReadOnlyDictionary <String, String> DeserializeEndpoints(ResolvedServiceEndpoint partitionEndpoint) { return(s_javaScriptSerializer.Deserialize <EndpointsCollection>(partitionEndpoint.Address).Endpoints); }
public static TestServicePartitionInfo Convert(ResolvedServicePartition resolvedPartition, ResolvedServiceEndpoint resolvedEndpoint, int partitionIdentifierNumber) { ThrowIf.Null(resolvedPartition, "resolvedPartition"); ThrowIf.Null(resolvedEndpoint, "resolvedEndpoint"); ServicePartitionKind keyType = ServicePartitionKind.Invalid; object rangeHighKey = null; object rangeLowKey = null; switch (resolvedPartition.Info.Kind) { case ServicePartitionKind.Singleton: keyType = ServicePartitionKind.Singleton; break; case ServicePartitionKind.Int64Range: keyType = ServicePartitionKind.Int64Range; rangeHighKey = ((System.Fabric.Int64RangePartitionInformation)resolvedPartition.Info).HighKey; rangeLowKey = ((System.Fabric.Int64RangePartitionInformation)resolvedPartition.Info).LowKey; break; case ServicePartitionKind.Named: keyType = ServicePartitionKind.Named; break; default: throw new InvalidOperationException("Unknown ServicePartitionKind " + resolvedPartition.Info.Kind.ToString() + "."); } TestServicePartitionInfo testServicePartitionInfo = new TestServicePartitionInfo() { Location = resolvedEndpoint.Address, Name = resolvedPartition.ServiceName, Id = resolvedPartition.Info.Id, KeyType = keyType, RangeHighKey = rangeHighKey, RangeLowKey = rangeLowKey, Role = resolvedEndpoint.Role, PartitionIdentifier = partitionIdentifierNumber, }; if (resolvedPartition.Endpoints.Any(e => e.Role == ServiceEndpointRole.StatefulPrimary)) { testServicePartitionInfo.IsPrimaryEndpoint = resolvedPartition.GetEndpoint().Address == resolvedEndpoint.Address; } else { testServicePartitionInfo.IsPrimaryEndpoint = false; } return(testServicePartitionInfo); }
protected override Task <ServiceFabricWebSocketClient> CreateClientAsync(ResolvedServiceEndpoint endpoint, CancellationToken cancellationToken) { return(Task.FromResult(new ServiceFabricWebSocketClient(endpoint.Address))); }
private void QueryPartitionEndpoints(List <BackupEnabledServiceReference> backupEnabledServices, Application app, Service service, Partition partition, ResolvedServiceEndpoint endpoint) { var endpointJson = JObject.Parse(endpoint.Address); var serviceEndpoint = endpointJson["Endpoints"][BackupRestoreService.BackupRestoreServiceEndpointName]; if (serviceEndpoint != null) { string endpointAddress = serviceEndpoint.Value <string>(); var serviceDescription = new BackupEnabledServiceReference { ApplicationName = app.ApplicationName, ServiceName = service.ServiceName, Int64RangePartitionGuid = partition.PartitionInformation.Id, Endpoint = new Uri(endpointAddress) }; backupEnabledServices.Add(serviceDescription); } }
protected override bool ValidateClient(ResolvedServiceEndpoint endpoint, ServiceFabricWebSocketClient client) { return(client.BaseAddress == endpoint.Address); }