/// <summary> /// 本地执行方法 /// </summary> /// <param name="serviceEntry"></param> /// <param name="invokeMessage"></param> /// <param name="resultMessage"></param> /// <returns></returns> private async Task LocalServiceExecuteAsync(RemoteExecutorContext context, RemoteCallBackData resultMessage) { try { CancellationTokenSource cancelTokenSource = new CancellationTokenSource(); if (!cancelTokenSource.IsCancellationRequested) { object result = await context.ServiceEntry.Func(context); Task task = result as Task; if (task == null) { resultMessage.Result = result; } else { task.Wait(cancelTokenSource.Token); TypeInfo taskType = task.GetType().GetTypeInfo(); if (taskType.IsGenericType) { resultMessage.Result = taskType.GetProperty("Result")?.GetValue(task); } } resultMessage.ResultType = context.ServiceEntry.Descriptor.ReturnDesc; } } catch (Exception ex) { _logger.Error("throw exception when excuting local service: " + context.ServiceEntry.Descriptor.Id, ex); resultMessage.ExceptionMessage = ex.Message; } }
public async Task <IActionResult> ExecutePath(string path, [FromQuery] GateWayQueryString query, [ModelBinder] GateWayModel model) { Dictionary <string, object> paras = new Dictionary <string, object>(); if (model?.Data != null) { paras = model.Data; } if (query.Collection.Count > 0) { foreach (string key in query.Collection.AllKeys) { paras[key.ToLower()] = query.Collection[key]; } } RemoteCallBackData result = await GateWayClient.Invoke(path, paras, Request.Method, _container); if (result.ResultType != typeof(FileData).ToString()) { return(new JsonResult(result.Result)); } FileData file = result.Result as FileData; return(File(file?.Data, "application/octet-stream", file?.FileName)); }
public static async Task <RemoteCallBackData> Invoke(string path, IDictionary <string, object> paras, string httpMethod, IContainer container) { IRemoteServiceExecutor remoteServiceInvoker = container.Resolve <IRemoteServiceExecutor>(); ISerializer converter = container.Resolve <ISerializer>(); RemoteCallBackData result = await remoteServiceInvoker.InvokeAsync(path, paras, httpMethod); if (!string.IsNullOrEmpty(result.ExceptionMessage)) { throw new HttpStatusCodeException(400, $"{result.ToErrorString()}", path); } if (!string.IsNullOrEmpty(result.ErrorCode) || !string.IsNullOrEmpty(result.ErrorMsg)) { if (int.TryParse(result.ErrorCode, out int erroCode) && erroCode > 200 && erroCode < 600) { throw new HttpStatusCodeException(erroCode, result.ToErrorString(), path); } return(new RemoteCallBackData { ErrorCode = result.ErrorCode, ErrorMsg = result.ErrorMsg }); } if (result.ResultType == typeof(FileData).ToString()) { object file = converter.Deserialize(result.Result, typeof(FileData)); result.Result = file; } return(result); }
private static void Main(string[] args) { Thread.Sleep(10000); var containerBuilder = new ContainerBuilder(); var builder = new ServiceHostClientBuilder(containerBuilder).UseRpcForTransfer(); using (var host = builder.Build()) { ITransportClient client = host.Container.Resolve <ITransportClientFactory>() .CreateClient(new ServerAddress("127.0.0.1", 8008)); //ITransportClient client = container.Resolve<ITransportClientFactory>() // .DecorationFactory(container.Resolve<ISerializer>()) // .CreateClient(new ServerAddress("127.0.0.1", 8007)); RemoteCallData sendMessage = new RemoteCallData { ServiceId = "base/fastdfs", Parameters = new Dictionary <string, object> { { "message", 12 }, { "myout", 122 } } }; RemoteCallBackData result = client.SendAsync(sendMessage).Result; Console.Write(result.Result.ToString()); Console.ReadLine(); } }
public async Task <T> InvokeAsync <T>(string serviceIdOrPath, IDictionary <string, object> paras) { _logger.Debug($"开始启动服务: {serviceIdOrPath}"); RemoteCallBackData result = await InvokeAsync(serviceIdOrPath, paras); if (!string.IsNullOrEmpty(result.ExceptionMessage)) { _logger.Debug($"执行服务: {serviceIdOrPath} 发生错误: {result.ExceptionMessage}"); throw new Exception(result.ExceptionMessage); } if (result.Result == null) { _logger.Debug($"执行服务: {serviceIdOrPath} 返回空。"); return(default(T)); } object value; if (result.Result is Task <T> task) { value = _typeConvertProvider.Convert(task.Result, typeof(T)); } else { value = _typeConvertProvider.Convert(result.Result, typeof(T)); } _logger.Debug($"服务执行完毕,路径为: {serviceIdOrPath}."); return((T)value); }
public async Task <RemoteCallBackData> InvokeAsync(string serviceIdOrPath, IDictionary <string, object> paras, string httpMethod = "get", string token = null) { if (paras == null) { paras = new ConcurrentDictionary <string, object>(); } if (!(_cache != null && _cache.TryGet(serviceIdOrPath + "_" + httpMethod.ToLower(), out List <ServerAddress> service))) { service = await GetServiceByPathAsync(serviceIdOrPath, httpMethod); } if (service == null || service.Count == 0) { return(new RemoteCallBackData { ErrorCode = "404", ErrorMsg = $"路径为:{serviceIdOrPath}, 没有找到!" }); } if (token == null && _serviceTokenGetter?.GetToken != null) { token = _serviceTokenGetter.GetToken(); } RemoteCallBackData result = await InvokeAsync(service, serviceIdOrPath, paras, token); if (!string.IsNullOrEmpty(result.ExceptionMessage)) { return(new RemoteCallBackData { ErrorCode = "400", ErrorMsg = $"{serviceIdOrPath}, {result.ToErrorString()}" }); } if (string.IsNullOrEmpty(result.ErrorCode) && string.IsNullOrEmpty(result.ErrorMsg)) { return(result); } if (int.TryParse(result.ErrorCode, out int erroCode) && erroCode > 200 && erroCode < 600) { return(new RemoteCallBackData { ErrorCode = result.ErrorCode, ErrorMsg = $"{serviceIdOrPath}, {result.ToErrorString()}" }); } return(result); }
/// <summary> /// 服务内部调用方法 /// </summary> /// <param name="serverAddress">服务地址</param> /// <param name="sendMessage">请求内容</param> public static async Task <T> InternalCall <T>(List <ServerAddress> service, RemoteCallData sendMessage) { ContainerBuilder containerBuilder = new ContainerBuilder(); Core.Client.IServiceHostClientBuilder builder = new ServiceHostClientBuilder(containerBuilder).UseRpcForTransfer() .UsePollingAddressSelector(BalanceType.RoundRobin); using (Core.IServiceHost host = builder.Build()) { IAddressSelector addressSelector = host.Container.Resolve <IAddressSelector>(); ServerAddress desc = await addressSelector.GetAddressAsync(service); ITransportClient client = host.Container.Resolve <ITransportClientFactory>() .CreateClient(desc); RemoteCallBackData result = client.SendAsync(sendMessage).Result; return(JsonConvert.DeserializeObject <T>(result.Result.ToString())); } }
private async Task OnReceived(IChannelHandlerContext channel, TransportMsg message) { _logger.Debug($"开始触发服务: {message.Id}"); if (message.ContentType == typeof(RemoteCallData).FullName) { IResponse response = new RpcResponse(channel, _serializer, _logger); RemoteExecutorContext thisContext = new RemoteExecutorContext(message, _serviceEntryContainer, response, _serializer, _logger, _serviceDiscovery); RequestDel lastInvoke = new RequestDel(async context => { RemoteCallBackData resultMessage = new RemoteCallBackData(); if (context.ServiceEntry == null) { resultMessage.ExceptionMessage = $"没有此服务:{context.RemoteInvokeMessage.ServiceId}"; await response.WriteAsync(message.Id, resultMessage); } else if (context.ServiceEntry.Descriptor.WaitExecution) { await LocalServiceExecuteAsync(context, resultMessage); await response.WriteAsync(message.Id, resultMessage); } else { await response.WriteAsync(message.Id, resultMessage); await Task.Factory.StartNew(async() => { await LocalServiceExecuteAsync(context, resultMessage); }); } }); foreach (Func <RequestDel, RequestDel> middleware in _middlewares) { lastInvoke = middleware.Invoke(lastInvoke); } await lastInvoke.Invoke(thisContext); } else { _logger.Debug($"msg: {message.Id}, message type is not an RemoteCallData."); } }
public async Task WriteAsync(string messageId, RemoteCallBackData resultMessage) { try { _logger.Debug($"结束处理任务: {messageId}"); TransportMsg transportMsg = new TransportMsg { Id = messageId, Content = resultMessage, ContentType = resultMessage.GetType().ToString() }; var data = LZ4MessagePackSerializer.FromJson(_serializer.Serialize <string>(transportMsg)); IByteBuffer buffer = Unpooled.Buffer(data.Length, data.Length); buffer.WriteBytes(data); await _channel.WriteAndFlushAsync(buffer); } catch (Exception ex) { _logger.Error("抛出错误 消息为: " + messageId, ex); } }
public static IServiceHostClientBuilder UseInServerForDiscovery(this IServiceHostClientBuilder serviceHostBuilder, params ServerAddress[] address) { serviceHostBuilder.RegisterService(cb => { cb.RegisterType <ClientServiceDiscovery>().As <IClientServiceDiscovery>().SingleInstance(); }); serviceHostBuilder.AddInitializer(container => { IClientServiceDiscovery clientDiscovery = container.Resolve <IClientServiceDiscovery>(); IRemoteServiceExecutor remoteExecutor = container.Resolve <IRemoteServiceExecutor>(); ISerializer serializer = container.Resolve <ISerializer>(); ITypeConvertProvider typeConverter = container.Resolve <ITypeConvertProvider>(); ILogger logger = container.Resolve <ILogger>(); StringBuilder sb = new StringBuilder(); foreach (ServerAddress addr in address) { sb.AppendFormat(addr.Code + ","); clientDiscovery.AddRoutesGetter(async() => { RemoteCallBackData result = await remoteExecutor.InvokeAsync(new List <ServerAddress>() { addr }, "Lamp.ServiceDiscovery.InServer.GetRoutesDescAsync".ToLower(), null, null); if (result == null || result.HasError) { return(null); } List <ServiceRouteDesc> routesDesc = (List <ServiceRouteDesc>)typeConverter.Convert(result.Result, typeof(List <ServiceRouteDesc>)); ServerDesc server = new ServerDesc { ServerAddress = addr, ServiceDescriptor = new List <ServiceDesc>() }; server.ServerAddress.IsHealth = true; foreach (ServiceRouteDesc desc in routesDesc) { ServiceDesc item = (ServiceDesc)desc.ServiceDescriptor.Clone(); server.ServiceDescriptor.Add(item); } return(server); }); } if (sb.Length > 0) { logger.Info($"[config]用服务端发现服务 {sb.ToString()}"); } }); serviceHostBuilder.AddRunner(container => { ClientServiceDiscovery clientServiceDiscovery = (ClientServiceDiscovery)container.Resolve <IClientServiceDiscovery>(); clientServiceDiscovery?.RunInInit().Wait(); }); return(serviceHostBuilder); }
public async Task <RemoteCallBackData> InvokeAsync(List <ServerAddress> service, string serviceIdOrPath, IDictionary <string, object> paras, string token) { ServerAddress desc = await _addressSelector.GetAddressAsync(service); if (paras == null) { paras = new ConcurrentDictionary <string, object>(); } if (_retryTimes < 0) { _retryTimes = service.Count; } RemoteCallBackData result = null; Polly.Retry.RetryPolicy retryPolicy = Policy.Handle <Exception>() .RetryAsync(_retryTimes, async(ex, count) => { desc = await _addressSelector.GetAddressAsync(service); _logger.Debug( $"FaultHandling,retry times: {count},serviceId: {serviceIdOrPath},Address: {desc.Code},RemoteServiceCaller excute retry by Polly for exception {ex.Message}"); }); Polly.Wrap.PolicyWrap <RemoteCallBackData> fallbackPolicy = Policy <RemoteCallBackData> .Handle <Exception>() .FallbackAsync(new RemoteCallBackData() { ErrorCode = "500", ErrorMsg = "error occur when communicate with server. server maybe have been down." }) .WrapAsync(retryPolicy); return(await fallbackPolicy.ExecuteAsync(async() => { ITransportClient client = _transportClientFactory.CreateClient(desc); if (client == null) { return new RemoteCallBackData { ErrorCode = "400", ErrorMsg = "服务不可用" }; } _logger.Debug($"invoke: serviceId:{serviceIdOrPath}, parameters count: {paras.Count()}, token:{token}"); Payload payload = new Payload(); if (!string.IsNullOrEmpty(token) && _authorizationHandler != null && desc.EnableAuthorization) { var authorizationContext = _authorizationHandler.GetAuthorizationContext(token, desc.Roles); if (authorizationContext != null) { payload.Items = authorizationContext; } else { return new RemoteCallBackData { ErrorMsg = "没有权限", ErrorCode = "401" }; } } result = await client.SendAsync(new RemoteCallData { Payload = payload, Parameters = paras, ServiceId = serviceIdOrPath, Token = token, }); return result; })); }