/// <summary> /// 远程调用。 /// </summary> /// <typeparam name="T">返回类型。</typeparam> /// <param name="parameters">参数字典。</param> /// <param name="serviceId">服务Id。</param> /// <returns>调用结果。</returns> protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId) { object result = default(T); var command = await _commandProvider.GetCommand(serviceId); RemoteInvokeResultMessage message; if (!command.RequestCacheEnabled) { message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey); if (message == null) { var invoker = _serviceProvider.GetInstances <IClusterInvoker>(command.Strategy.ToString()); return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey)); } } else { var invocation = GetInvocation(parameters, serviceId, typeof(T)); await _interceptor.Intercept(invocation); message = invocation.ReturnValue is RemoteInvokeResultMessage ? invocation.ReturnValue as RemoteInvokeResultMessage : null; result = invocation.ReturnValue; } if (message != null) { result = _typeConvertibleService.Convert(message.Result, typeof(T)); } return((T)result); }
/// <summary> /// 远程调用。 /// </summary> /// <typeparam name="T">返回类型。</typeparam> /// <param name="parameters">参数字典。</param> /// <param name="serviceId">服务Id。</param> /// <returns>调用结果。</returns> protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId) { object result = default(T); var vt = _commandProvider.GetCommand(serviceId); var command = vt.IsCompletedSuccessfully ? vt.Result : await vt; RemoteInvokeResultMessage message = null; var decodeJOject = typeof(T) == TypeHelper.ObjectType; IInvocation invocation = null; var existsInterceptor = _interceptors.Any(); var serviceRoute = await _serviceRouteProvider.Locate(serviceId); if ((serviceRoute == null || !serviceRoute.ServiceDescriptor.ExistIntercept()) || decodeJOject) { message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject); if (message == null) { if (command.FallBackName != null && _serviceProvider.IsRegistered <IFallbackInvoker>(command.FallBackName) && command.Strategy == StrategyType.FallBack) { var invoker = _serviceProvider.GetInstances <IFallbackInvoker>(command.FallBackName); return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey)); } else { var invoker = _serviceProvider.GetInstances <IClusterInvoker>(command.Strategy.ToString()); return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey, typeof(T) == TypeHelper.ObjectType)); } } } else { invocation = invocation == null?GetInvocation(parameters, serviceId, typeof(T)) : invocation; foreach (var interceptor in _interceptors) { var interceptReuslt = await Intercept(interceptor, invocation); message = interceptReuslt.Item1; result = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2; } } if (message != null) { if (message.Result == null) { result = message.Result; } else { result = _typeConvertibleService.Convert(message.Result, typeof(T)); } } return((T)result); }
/// <summary> /// 远程调用。 /// </summary> /// <typeparam name="T">返回类型。</typeparam> /// <param name="parameters">参数字典。</param> /// <param name="serviceId">服务Id。</param> /// <returns>调用结果。</returns> protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId) { object result = default(T); var command = await _commandProvider.GetCommand(serviceId); RemoteInvokeResultMessage message = null; var decodeJOject = typeof(T) == UtilityType.ObjectType; IInvocation invocation = null; var existsInterceptor = _interceptors.Any(); if ((_cacheInterceptor == null || !command.RequestCacheEnabled) && !existsInterceptor) { message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject); if (message == null || !message.IsSucceedRemoteInvokeCalled()) { return(await FallBackRetryInvoke <T>(parameters, serviceId, command)); } } if (_cacheInterceptor != null && command.RequestCacheEnabled) { invocation = GetCacheInvocation(parameters, serviceId, typeof(T)); if (invocation != null) { var interceptReuslt = await Intercept(_cacheInterceptor, invocation); message = interceptReuslt.Item1; result = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2; } else { message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject); if (message == null || !message.IsSucceedRemoteInvokeCalled()) { return(await FallBackRetryInvoke <T>(parameters, serviceId, command)); } } } if (existsInterceptor) { invocation = invocation == null?GetInvocation(parameters, serviceId, typeof(T)) : invocation; foreach (var interceptor in _interceptors) { var interceptReuslt = await Intercept(interceptor, invocation); message = interceptReuslt.Item1; result = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2; } } if (message != null) { result = await GetInvokeResult <T>(message); } return((T)result); }
/// <summary> /// 远程调用。 /// </summary> /// <typeparam name="T">返回类型。</typeparam> /// <param name="parameters">参数字典。</param> /// <param name="serviceId">服务Id。</param> /// <returns>调用结果。</returns> protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId) { object result = default(T); var command = await _commandProvider.GetCommand(serviceId); RemoteInvokeResultMessage message = null; var decodeJOject = typeof(T) == UtilityType.ObjectType; IInvocation invocation = null; var existsInterceptor = _interceptors.Any(); if ((!command.RequestCacheEnabled || decodeJOject) && !existsInterceptor) { message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject); if (message == null) { if (command.FallBackName != null && _serviceProvider.IsRegistered <IFallbackInvoker>(command.FallBackName) && command.Strategy == StrategyType.FallBack) { var invoker = _serviceProvider.GetInstances <IFallbackInvoker>(command.FallBackName); return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey)); } else { var invoker = _serviceProvider.GetInstances <IClusterInvoker>(command.Strategy.ToString()); return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey, typeof(T) == UtilityType.ObjectType)); } } } if (command.RequestCacheEnabled && !decodeJOject) { invocation = GetCacheInvocation(parameters, serviceId, typeof(T)); var interceptReuslt = await Intercept(_cacheInterceptor, invocation); message = interceptReuslt.Item1; result = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2; } if (existsInterceptor) { invocation = invocation == null?GetInvocation(parameters, serviceId, typeof(T)) : invocation; foreach (var interceptor in _interceptors) { var interceptReuslt = await Intercept(interceptor, invocation); message = interceptReuslt.Item1; result = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2; } } if (message != null) { result = _typeConvertibleService.Convert(message.Result, typeof(T)); } return((T)result); }
public async Task Invoke(IDictionary <string, object> parameters, string serviceId, string serviceKey) { var command = _serviceCommandProvider.GetCommand(serviceId); var result = await _serviceCommandProvider.Run(command.Injection, command.InjectionNamespaces); if (result is Boolean) { if ((bool)result) { var entries = _serviceEntryManager.GetEntries().ToList(); var entry = entries.Where(p => p.Descriptor.Id == serviceId).FirstOrDefault(); await entry.Func(serviceKey, parameters); } } }
public async Task <RemoteInvokeResultMessage> InvokeAsync(IDictionary <string, object> parameters, string serviceId, string serviceKey, bool decodeJOject, bool isFailoverInvoke = false) { var serviceInvokeInfos = _serviceInvokeListenInfo.GetOrAdd(serviceId, new ServiceInvokeListenInfo() { FirstInvokeTime = DateTime.Now, FinalRemoteInvokeTime = DateTime.Now }); UpdateAttachments(parameters); RpcContext.GetContext().SetAttachment("isFailoverInvoke", isFailoverInvoke); var command = await _commandProvider.GetCommand(serviceId); var intervalSeconds = (DateTime.Now - serviceInvokeInfos.FinalRemoteInvokeTime).TotalSeconds; bool reachConcurrentRequest() => serviceInvokeInfos.ConcurrentRequests > command.MaxConcurrentRequests; bool reachRequestVolumeThreshold() => intervalSeconds <= 10 && serviceInvokeInfos.SinceFaultRemoteServiceRequests > command.BreakerRequestVolumeThreshold; bool reachErrorThresholdPercentage() { var errorThresholdPercent = serviceInvokeInfos.FaultRemoteServiceRequests / (serviceInvokeInfos.RemoteServiceRequests ?? 1) * 100; return(errorThresholdPercent > command.BreakeErrorThresholdPercentage && serviceInvokeInfos.RemoteServiceRequests.HasValue && serviceInvokeInfos.RemoteServiceRequests.Value > 1); } var item = GetHashItem(command, parameters); if (command.BreakerForceClosed) { _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); }); return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, item)); } else { if (reachConcurrentRequest() || reachRequestVolumeThreshold() || reachErrorThresholdPercentage()) { if (intervalSeconds * 1000 > command.BreakeSleepWindowInMilliseconds || isFailoverInvoke) { return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, item)); } else { _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); }); if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug($"当前服务{serviceId}-{serviceKey}当前不可用,请稍后重试"); } var breakeSeconds = Math.Round((command.BreakeSleepWindowInMilliseconds - intervalSeconds * 1000) / 1000, 0); return(new RemoteInvokeResultMessage() { ExceptionMessage = $"当前没有可用的服务{serviceId}-{serviceKey},请稍后{breakeSeconds}s后重试", StatusCode = StatusCode.ServiceUnavailability }); } } else { return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, item)); } } }
/// <summary> /// 调用. /// </summary> /// <param name="parameters">The parameters.</param> /// <param name="serviceId">The service identifier.</param> /// <param name="serviceKey">The service key.</param> /// <param name="decodeJOject">if set to <c>true</c> [decode j oject].</param> /// <returns>Task.</returns> public async Task Invoke(IDictionary <string, object> parameters, string serviceId, string serviceKey, bool decodeJOject) { var vt = _serviceCommandProvider.GetCommand(serviceId); var command = vt.IsCompletedSuccessfully ? vt.Result : await vt; var result = await _serviceCommandProvider.Run(command.Injection, command.InjectionNamespaces); if (result is bool) { if ((bool)result) { var entries = _serviceEntryManager.GetEntries().ToList(); var entry = entries.Where(p => p.Descriptor.Id == serviceId).FirstOrDefault(); await entry.Func(serviceKey, parameters); } } }
/// <summary> /// 解析服务地址。 /// </summary> /// <param name="serviceId">服务Id。</param> /// <returns>服务地址模型。</returns> /// 1.从字典中拿到serviceroute对象 /// 2.从字典中拿到服务描述符集合 /// 3.获取或添加serviceroute /// 4.添加服务id到白名单 /// 5.根据服务描述符得到地址并判断地址是否是可用的(地址应该是多个) /// 6.添加到集合中 /// 7.拿到服务命今 /// 8.根据负载分流策略拿到一个选择器 /// 9.返回addressmodel public async ValueTask <AddressModel> Resolver(string serviceId, string item) { if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug($"准备为服务id:{serviceId},解析可用地址。"); } var serviceRouteTask = _serviceRouteProvider.Locate(serviceId); var serviceRoute = serviceRouteTask.IsCompletedSuccessfully ? serviceRouteTask.Result : await serviceRouteTask; if (serviceRoute == null) { if (_logger.IsEnabled(LogLevel.Warning)) { _logger.LogWarning($"根据服务id:{serviceId},找不到相关服务信息。"); } return(null); } _serviceHeartbeatManager.AddWhitelist(serviceId); var address = new List <AddressModel>(); foreach (var addressModel in serviceRoute.Address) { _healthCheckService.Monitor(addressModel); var task = _healthCheckService.IsHealth(addressModel); if (!(task.IsCompletedSuccessfully ? task.Result : await task)) { continue; } address.Add(addressModel); } if (address.Count == 0) { if (_logger.IsEnabled(LogLevel.Warning)) { _logger.LogWarning($"根据服务id:{serviceId},找不到可用的地址。"); } return(null); } if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation($"根据服务id:{serviceId},找到以下可用地址:{string.Join(",", address.Select(i => i.ToString()))}。"); } var vtCommand = _commandProvider.GetCommand(serviceId); var command = vtCommand.IsCompletedSuccessfully ? vtCommand.Result : await vtCommand; var addressSelector = _addressSelectors[command.ShuntStrategy.ToString()]; var vt = addressSelector.SelectAsync(new AddressSelectContext { Descriptor = serviceRoute.ServiceDescriptor, Address = address, Item = item }); return(vt.IsCompletedSuccessfully ? vt.Result : await vt); }
/// <summary> /// 远程调用。 /// </summary> /// <typeparam name="T">返回类型。</typeparam> /// <param name="parameters">参数字典。</param> /// <param name="serviceId">服务Id。</param> /// <returns>调用结果。</returns> protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId) { var message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey); if (message == null) { var command = _commandProvider.GetCommand(serviceId); var invoker = _serviceProvider.GetInstances <IClusterInvoker>(command.Strategy.ToString()); return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey)); } if (message == null) { return(default(T)); } var result = _typeConvertibleService.Convert(message.Result, typeof(T)); return((T)result); }
public async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId, string _serviceKey, bool decodeJOject) { var time = 0; T result = default(T); RemoteInvokeResultMessage message = null; var command = await _commandProvider.GetCommand(serviceId); do { message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject); if (message != null && message.Result != null) { result = (T)_typeConvertibleService.Convert(message.Result, typeof(T)); } } while (message == null && ++time < command.FailoverCluster); return(result); }
public async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId, string _serviceKey, bool decodeJOject) { var time = 0; T result = default(T); RemoteInvokeResultMessage message = null; var command = await _commandProvider.GetCommand(serviceId); do { message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject, true); if (message != null) { if (message.StatusCode == StatusCode.Success) { if (message.Result != null) { result = (T)_typeConvertibleService.Convert(message.Result, typeof(T)); } else { result = default(T); } } else if (message.IsFailedRemoteInvokeCalled()) { continue; } else if (message.IsSucceedRemoteInvokeCalled()) { throw message.GetExceptionByStatusCode(); } } } while ((message == null || !message.IsSucceedRemoteInvokeCalled()) && ++time < command.FailoverCluster); if (message == null) { throw new CPlatformException($"{serviceId}远程服务调用失败,暂不存在可用的服务实例"); } if (message.StatusCode != StatusCode.Success) { throw message.GetExceptionByStatusCode(); } return(result); }
/// <summary> /// 远程调用。 /// </summary> /// <typeparam name="T">返回类型。</typeparam> /// <param name="parameters">参数字典。</param> /// <param name="serviceId">服务Id。</param> /// <returns>调用结果。</returns> protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId) { object result = default(T); var command = await _commandProvider.GetCommand(serviceId); RemoteInvokeResultMessage message; var decodeJOject = typeof(T) == UtilityType.ObjectType; if (!command.RequestCacheEnabled || decodeJOject) { var v = typeof(T).FullName; message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject); if (message == null) { if (command.FallBackName != null && _serviceProvider.IsRegistered <IFallbackInvoker>(command.FallBackName) && command.Strategy == StrategyType.FallBack) { var invoker = _serviceProvider.GetInstances <IFallbackInvoker>(command.FallBackName); return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey)); } else { var invoker = _serviceProvider.GetInstances <IClusterInvoker>(command.Strategy.ToString()); return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey, typeof(T) == UtilityType.ObjectType)); } } } else { var invocation = GetInvocation(parameters, serviceId, typeof(T)); await _interceptor.Intercept(invocation); message = invocation.ReturnValue is RemoteInvokeResultMessage ? invocation.ReturnValue as RemoteInvokeResultMessage : null; result = invocation.ReturnValue; } if (message != null) { result = _typeConvertibleService.Convert(message.Result, typeof(T)); } return((T)result); }
public async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId, string _serviceKey, bool decodeJOject) { var time = 0; T result = default(T); RemoteInvokeResultMessage message = null; var vtCommand = _commandProvider.GetCommand(serviceId); var command = vtCommand.IsCompletedSuccessfully ? vtCommand.Result : await vtCommand; do { message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject); if (message != null && message.Result != null) { if (message.StatusCode != StatusCode.Success && time >= command.FailoverCluster) { throw new CPlatformException(message.ExceptionMessage, message.StatusCode); } result = (T)_typeConvertibleService.Convert(message.Result, typeof(T)); } } while ((message == null || message.StatusCode == StatusCode.ServiceUnavailability) && ++time < command.FailoverCluster); return(result); }
public async Task <RemoteInvokeResultMessage> InvokeAsync(IDictionary <string, object> parameters, string serviceId, string serviceKey, bool decodeJOject) { var serviceInvokeInfos = _serviceInvokeListenInfo.GetOrAdd(serviceId, new ServiceInvokeListenInfo() { FirstInvokeTime = DateTime.Now, FinalRemoteInvokeTime = DateTime.Now }); var command = await _commandProvider.GetCommand(serviceId); var intervalSeconds = (DateTime.Now - serviceInvokeInfos.FinalRemoteInvokeTime).TotalSeconds; bool reachConcurrentRequest() => serviceInvokeInfos.ConcurrentRequests > command.MaxConcurrentRequests; bool reachRequestVolumeThreshold() => intervalSeconds <= 10 && serviceInvokeInfos.SinceFaultRemoteServiceRequests > command.BreakerRequestVolumeThreshold; bool reachErrorThresholdPercentage() => (double)serviceInvokeInfos.FaultRemoteServiceRequests / (double)(serviceInvokeInfos.RemoteServiceRequests ?? 1) * 100 > command.BreakeErrorThresholdPercentage; var hashCode = GetHashCode(command, parameters); if (command.BreakerForceClosed) { _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); }); return(null); } else { if (reachConcurrentRequest() || reachRequestVolumeThreshold() || reachErrorThresholdPercentage()) { if (intervalSeconds * 1000 > command.BreakeSleepWindowInMilliseconds) { return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, hashCode)); } else { _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); }); return(null); } } else { return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, hashCode)); } } }
public async Task <RemoteInvokeResultMessage> InvokeAsync(IDictionary <string, object> parameters, string serviceId, string serviceKey) { var serviceInvokeInfos = _serviceInvokeListenInfo.GetOrAdd(serviceId, new ServiceInvokeListenInfo()); var command = _commandProvider.GetCommand(serviceId); var intervalSeconds = (DateTime.Now - serviceInvokeInfos.FinalRemoteInvokeTime).TotalSeconds; bool reachConcurrentRequest() => serviceInvokeInfos.ConcurrentRequests > command.MaxConcurrentRequests; bool reachRequestVolumeThreshold() => intervalSeconds <= 10 && serviceInvokeInfos.SinceFaultRemoteServiceRequests > command.BreakerRequestVolumeThreshold; bool reachErrorThresholdPercentage() => serviceInvokeInfos.FaultRemoteServiceRequests / (serviceInvokeInfos.RemoteServiceRequests ?? 1) * 100 > command.BreakeErrorThresholdPercentage; if (command.BreakerForceClosed) { _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); }); return(null); } else { if (reachConcurrentRequest() || reachRequestVolumeThreshold() || reachErrorThresholdPercentage()) { if (intervalSeconds * 1000 > command.BreakeSleepWindowInMilliseconds) { return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey)); } else { _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); }); return(null); } } else { return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey)); } } throw new NotImplementedException(); }
/// <summary> /// 解析服务地址。 /// </summary> /// <param name="serviceId">服务Id。</param> /// <returns>服务地址模型。</returns> /// 1.从字典中拿到serviceroute对象 /// 2.从字典中拿到服务描述符集合 /// 3.获取或添加serviceroute /// 4.添加服务id到白名单 /// 5.根据服务描述符得到地址并判断地址是否是可用的(地址应该是多个) /// 6.添加到集合中 /// 7.拿到服务命今 /// 8.根据负载分流策略拿到一个选择器 /// 9.返回addressmodel public async Task <AddressModel> Resolver(string serviceId, string item) { if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug($"准备为服务id:{serviceId},解析可用地址。"); } var isFailoverInvoke = IsFailoverInvoke(); var serviceRoute = await _serviceRouteProvider.Locate(serviceId, !isFailoverInvoke); if (serviceRoute == null) { throw new CPlatformException($"根据服务id:{serviceId},找不到相关服务信息。【fromCache:{!isFailoverInvoke}】"); } var address = await GetHealthAddress(serviceRoute); if (!address.Any()) { throw new CPlatformException($"根据服务id:{serviceId},找不到可用的服务提供者的地址"); } _serviceHeartbeatManager.AddWhitelist(serviceId); var command = await _commandProvider.GetCommand(serviceId); var addressSelector = _addressSelectors[command.ShuntStrategy.ToString()]; var selectAddress = await addressSelector.SelectAsync(new AddressSelectContext { Descriptor = serviceRoute.ServiceDescriptor, Address = address, Item = item }); return(selectAddress); }
/// <summary> /// 解析服务地址。 /// </summary> /// <param name="serviceId">服务Id。</param> /// <returns>服务地址模型。</returns> public async ValueTask <AddressModel> Resolver(string serviceId, string item) { if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug($"准备为服务id:{serviceId},解析可用地址。"); } _concurrent.TryGetValue(serviceId, out ServiceRoute descriptor); if (descriptor == null) { var descriptors = await _serviceRouteManager.GetRoutesAsync(); descriptor = descriptors.FirstOrDefault(i => i.ServiceDescriptor.Id == serviceId); if (descriptor != null) { _concurrent.GetOrAdd(serviceId, descriptor); _serviceHeartbeatManager.AddWhitelist(serviceId); } else { if (descriptor == null) { if (_logger.IsEnabled(LogLevel.Warning)) { _logger.LogWarning($"根据服务id:{serviceId},找不到相关服务信息。"); } return(null); } } } var address = new List <AddressModel>(); foreach (var addressModel in descriptor.Address) { _healthCheckService.Monitor(addressModel); if (!await _healthCheckService.IsHealth(addressModel)) { continue; } address.Add(addressModel); } if (address.Count == 0) { if (_logger.IsEnabled(LogLevel.Warning)) { _logger.LogWarning($"根据服务id:{serviceId},找不到可用的地址。"); } return(null); } if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation($"根据服务id:{serviceId},找到以下可用地址:{string.Join(",", address.Select(i => i.ToString()))}。"); } var command = await _commandProvider.GetCommand(serviceId); var addressSelector = _addressSelectors[command.ShuntStrategy.ToString()]; return(await addressSelector.SelectAsync(new AddressSelectContext { Descriptor = descriptor.ServiceDescriptor, Address = address, Item = item })); }
/// <summary> /// 远程调用。 /// </summary> /// <typeparam name="T">返回类型。</typeparam> /// <param name="parameters">参数字典。</param> /// <param name="serviceId">服务Id。</param> /// <returns>调用结果。</returns> protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId) { object result = default(T); var vt = _commandProvider.GetCommand(serviceId); var command = vt.IsCompletedSuccessfully ? vt.Result : await vt; RemoteInvokeResultMessage message = null; var decodeJOject = typeof(T) == UtilityType.ObjectType; IInvocation invocation = null; var existsInterceptor = _interceptors.Any(); if ((_cacheInterceptor == null || !command.RequestCacheEnabled) && !existsInterceptor) { message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject); if (message == null) { if (command.FallBackName != null && _serviceProvider.IsRegistered <IFallbackInvoker>(command.FallBackName) && command.Strategy == StrategyType.FallBack) { var invoker = _serviceProvider.GetInstances <IFallbackInvoker>(command.FallBackName); return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey)); } else { var invoker = _serviceProvider.GetInstances <IClusterInvoker>(command.Strategy.ToString()); return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey, typeof(T) == UtilityType.ObjectType)); } } } if (_cacheInterceptor != null && command.RequestCacheEnabled) { invocation = GetCacheInvocation(parameters, serviceId, typeof(T)); var interceptReuslt = await Intercept(_cacheInterceptor, invocation); message = interceptReuslt.Item1; result = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2; } if (existsInterceptor) { invocation = invocation == null?GetInvocation(parameters, serviceId, typeof(T)) : invocation; foreach (var interceptor in _interceptors) { var interceptReuslt = await Intercept(interceptor, invocation); message = interceptReuslt.Item1; result = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2; } } //if (message != null) //{ // if (message.Result == null) result = message.Result; // else result = _typeConvertibleService.Convert(message.Result, typeof(T)); //} if (message != null) { if (message.StatusCode == StatusCode.Success) { result = _typeConvertibleService.Convert(message.Result, typeof(T)); } else { switch (message.StatusCode) { case StatusCode.BusinessError: throw new BusinessException(message.ExceptionMessage); case StatusCode.CommunicationError: throw new CommunicationException(message.ExceptionMessage); case StatusCode.RequestError: case StatusCode.CPlatformError: case StatusCode.UnKnownError: throw new CPlatformException(message.ExceptionMessage, message.StatusCode); case StatusCode.DataAccessError: throw new DataAccessException(message.ExceptionMessage); case StatusCode.UnAuthentication: throw new UnAuthenticationException(message.ExceptionMessage); case StatusCode.UnAuthorized: throw new UnAuthorizedException(message.ExceptionMessage); case StatusCode.UserFriendly: throw new UserFriendlyException(message.ExceptionMessage); case StatusCode.ValidateError: throw new ValidateException(message.ExceptionMessage); } throw new CPlatformException(message.ExceptionMessage, message.StatusCode); } } return((T)result); }
public async Task <RemoteInvokeResultMessage> InvokeAsync(IDictionary <string, object> parameters, string serviceId, string serviceKey, bool decodeJOject) { var serviceInvokeInfos = _serviceInvokeListenInfo.GetOrAdd(serviceId, new ServiceInvokeListenInfo() { FirstInvokeTime = DateTime.Now, FinalRemoteInvokeTime = DateTime.Now }); var vt = _commandProvider.GetCommand(serviceId); var command = vt.IsCompletedSuccessfully ? vt.Result : await vt; var intervalSeconds = (DateTime.Now - serviceInvokeInfos.FinalRemoteInvokeTime).TotalSeconds; bool reachConcurrentRequest() => serviceInvokeInfos.ConcurrentRequests > command.MaxConcurrentRequests; bool reachRequestVolumeThreshold() => intervalSeconds <= 10 && serviceInvokeInfos.SinceFaultRemoteServiceRequests > command.BreakerRequestVolumeThreshold; bool reachErrorThresholdPercentage() => (double)serviceInvokeInfos.FaultRemoteServiceRequests / (double)(serviceInvokeInfos.RemoteServiceRequests ?? 1) * 100 > command.BreakeErrorThresholdPercentage; var item = GetHashItem(command, parameters); if (command.BreakerForceClosed) { _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); }); if (reachConcurrentRequest() || reachRequestVolumeThreshold() || reachErrorThresholdPercentage()) { return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, item)); } else { return(null); } } else { if (reachConcurrentRequest() || reachRequestVolumeThreshold() || reachErrorThresholdPercentage()) { if (intervalSeconds * 1000 > command.BreakeSleepWindowInMilliseconds) { return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, item)); } else { _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); }); if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug("当前服务{serviceId}-{serviceKey}当前不可用,请稍后重试"); } var breakeSeconds = Math.Round((command.BreakeSleepWindowInMilliseconds - intervalSeconds * 1000) / 1000, 0); return(new RemoteInvokeResultMessage() { ExceptionMessage = $"当前服务{serviceId}-{serviceKey}当前不可用,请稍后{breakeSeconds}s后重试", StatusCode = StatusCode.ServiceUnavailability }); //return null; } } else { return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, item)); } } }