Пример #1
0
        /// <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;
            }
        }
Пример #2
0
        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));
        }
Пример #3
0
        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);
        }
Пример #4
0
        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();
            }
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        /// <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()));
            }
        }
Пример #8
0
        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.");
            }
        }
Пример #9
0
 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);
     }
 }
Пример #10
0
        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);
        }
Пример #11
0
        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;
            }));
        }