Ejemplo n.º 1
0
        /// <summary>
        /// 获取一个到指定服务器的连接
        /// </summary>
        /// <param name="item">配置信息</param>
        /// <returns>rpc连接</returns>
        public static IGrantRpcClient GetClient(ClientItem item)
        {
            if (item.Pool > 0)
            {
                return(Register(item));              // 0,表示开启连接池(默认),1,表示关闭连接池
            }
            string key = GetConnectionPoolKey(item.Ip, item.Port);

            lock (root)
            {
                if (!runing)
                {
                    Check();
                    runing = true;
                }

                if (ConnectionPools.ContainsKey(key))
                {
                    List <ComboxClass <DateTime, IGrantRpcClient> > cls = ConnectionPools[key];
                    if (cls.Count > 0)
                    {
                        // 从队列中取一个连接,并移除掉,防止二次分配
                        IGrantRpcClient c = cls[0].V2;
                        cls.Remove(cls[0]);
                        return(c);
                    }
                }
            }

            // 说明没有取到,这里需要新建,新建的直接返回,不能放到连接池,只有用完的才会放回去
            return(Register(item));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 释放连接回到连接池,回到连接池的连接都是可用的,
        /// 连接只有在用的时候才会检查状态
        /// </summary>
        /// <param name="client"> 客户端</param>
        public static void ReleaseClient(IGrantRpcClient client)
        {
            if (client.Item.Pool > 0)
            {
                client.Close();
                return;// 关闭连接池,连接不在放回,直接释放掉
            }
            string key = GetConnectionPoolKey(client.Item.Ip, client.Item.Port);

            lock (root)
            {
                if (ConnectionPools.ContainsKey(key))
                {
                    ConnectionPools[key]
                    .Add(new ComboxClass <DateTime, IGrantRpcClient> {
                        V1 = DateTime.Now, V2 = client
                    });
                }
                else
                {
                    List <ComboxClass <DateTime, IGrantRpcClient> > cls = new List <ComboxClass <DateTime, IGrantRpcClient> >(1)
                    {
                        new ComboxClass <DateTime, IGrantRpcClient> {
                            V1 = DateTime.Now, V2 = client
                        },
                    };
                    ConnectionPools.Add(key, cls);
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// 新建一个连接
        /// </summary>
        /// <param name="item">连接配置</param>
        /// <returns>连接</returns>
        private static IGrantRpcClient Register(ClientItem item)
        {
            try
            {
                IGrantRpcClient client = null;
                switch (item.ServerType)
                {
                case ServerType.Thrift:
                    client = new GrantThriftClient(item);
                    break;

                case ServerType.HttpWebApi:
                    client = new GrantWebApiClient(item);
                    break;

                default:
                    throw new Exception($"ClientConnectionManager.Register(), ClientItem.ServerType:'{item.ServerType}' is invalid");
                }
                return(client);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, $"ClientConnectionManager.register.Error,ServerInfo={item.ToString()}");
                return(null);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// 代理层使用
        /// </summary>
        /// <param name="args">参数</param>
        /// <param name="url">前端要求将M值体现在路径上,接入层自己来做个转换处理</param>
        /// <returns>string,参数</returns>
        internal static (string c, Result <object> r) Send(Args <object> args, string url)
        {
            var             serverName = "";
            ClientServer    cServer    = null;
            Result <object> rr         = new Result <object>();
            EventId         eventId    = new EventId(0, args.rid);

            try
            {
                // 这里需要重构,统一做成一个Fliter
                ClientType ct = ClientTypeParser.Parser(args.ct);
                switch (ct)
                {
                case ClientType.InnerRpc:     // 需要拦截
                    throw new Exception("你想干什么?");

                case ClientType.QtApp:
                case ClientType.QtWeb:     // 需要要做来源ip和reffer网站,都来着grant的域名
                case ClientType.Unkunwn:   // 未知的和第三方都必须验证appkey
                case ClientType.ThirdPart:
                    break;
                }

                string[] motheds = url.Split("/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                if (motheds == null || motheds.Length < 2)
                {
                    rr.msg = "HttpProxy.Error:Request args Error,Server name Could not found rid=" + args.rid;
                    rr.c   = 503;
                    rr.v   = default(object);
                }
                else
                {
                    #region 重构,获取路由配置

                    string server = motheds[motheds.Length - 2];
                    serverName = server;
                    args.m     = motheds[motheds.Length - 1];
                    int error = 0;
gotoHere:
                    readerWriterLock.AcquireReaderLock(80);
                    ClientItem cItem = null;
                    try
                    {
                        string s = server.ToLower();
                        if (cls.ContainsKey(s))
                        {
                            cServer = cls[s];
                            var clients = cServer.Client;
                            int idx     = 0;
                            switch (cServer.RouterType)
                            {
                            case RouterType.Hash:
                                idx = RouterManager.GetPool(args.uri);
                                break;

                            case RouterType.Polling:
                                idx = RouterManager.GetPolling(0, clients.Length);
                                break;

                            default:
                            case RouterType.Random:
                                idx = RouterManager.GetRandom(0, clients.Length);
                                break;
                            }
                            cItem = clients[idx];
                        }
                        else
                        {
                            StatusCode cc = new StatusCode(402, $"HttpProxy.Error:server :{server} not found rid={args.rid}");
                            rr.c   = cc.code;
                            rr.msg = cc.msg;
                            rr.v   = default(object);
                            logger.LogError(eventId, new LogInfo()
                            {
                                ServiceName   = serverName,
                                ApiName       = args.m,
                                CreatedBy     = "httpProxy",
                                TransactionId = args.rid,
                                UseChain      = JsonConvert.SerializeObject(args.Headers),
                                CodeMsg       = rr.msg,
                                Code          = rr.c,
                                Desc          = $"HttpProxy.Error:server :{server} not found rid={args.rid}",
                            }.ToString());
                        }
                    }
                    catch (Exception e)
                    {
                        string     msg = $"获取路由信息异常{server}{e.Message} rid = {args.rid}";
                        StatusCode cc  = new StatusCode(502, msg);
                        rr.c   = cc.code;
                        rr.msg = cc.msg;
                        rr.v   = default(object);
                        logger.LogError(eventId, e, $"获取Server:{server}路由信息异常");
                    }
                    finally
                    {
                        if (readerWriterLock.IsReaderLockHeld)
                        {
                            readerWriterLock.ReleaseReaderLock();
                        }
                    }

                    #endregion 重构,获取路由配置

                    #region 发送请求

                    if (cItem == null)
                    {
                        string     msg = $"HttpProxy.Error:无法获取路由信息:{server} rid = {args.rid}";
                        StatusCode cc  = new StatusCode(503, msg);
                        rr.c   = cc.code;
                        rr.msg = cc.msg;
                        rr.v   = default(object);

                        logger.LogError(eventId, new LogInfo
                        {
                            ServiceName   = server,
                            ApiName       = args.m,
                            CreatedBy     = "httpProxy",
                            TransactionId = args.rid,
                            Desc          = msg,
                            Code          = rr.c,
                            CodeMsg       = rr.msg,
                            UseChain      = JsonConvert.SerializeObject(args.Headers),
                        }.ToString());
                    }
                    else
                    {
                        cItem.Url = args.m;
                        var jSetting = new JsonSerializerSettings {
                            NullValueHandling = NullValueHandling.Ignore
                        };
                        jSetting.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
                        jSetting.DateFormatString   = "yyyy-MM-dd HH:mm:ss";
                        var msg = JsonConvert.SerializeObject(args, jSetting);
                        logger.LogTrace(eventId, new LogInfo
                        {
                            ServiceName   = server,
                            ApiName       = args.m,
                            CreatedBy     = "httpProxy",
                            TransactionId = args.rid,
                            Desc          = string.Format("开始访问服务器:server={0},ip={1},port={2},args={3},rid={4}",
                                                          cServer.ServerName, cItem.Ip, cItem.Port, msg, args.rid),
                            Code     = StatusCode.OK.code,
                            CodeMsg  = StatusCode.OK.msg,
                            UseChain = JsonConvert.SerializeObject(args.Headers),
                        }.ToString());
                        using (IGrantRpcClient rpcClient = ClientConnectionManager.GetClient(cItem))
                        {
                            string result = null;
                            if (rpcClient.Send(msg, args.m, out result))
                            {
                                var resultObj = JsonConvert.DeserializeObject <Result <object> >(result);
                                logger.LogTrace(eventId, new LogInfo
                                {
                                    ServiceName   = server,
                                    ApiName       = args.m,
                                    CreatedBy     = "httpProxy",
                                    TransactionId = args.rid,
                                    Desc          = string.Format(
                                        "服务器返回:server={0},ip={1},port={2},result={3},rid={4}",
                                        cServer.ServerName, cItem.Ip, cItem.Port, result, args.rid),
                                    Code     = resultObj.c,
                                    CodeMsg  = resultObj.msg,
                                    UseChain = JsonConvert.SerializeObject(args.Headers),
                                }.ToString());
                                return(result, resultObj);  // 直接返回结果
                            }
                        }

                        // 走到这里就说明失败了
                        error += 1;
                        System.Threading.Thread.Sleep(100);
                        // 重试3次
                        if (error < 3)
                        {
                            goto gotoHere; // 失败了就重新去找一个连接重试
                        }

                        // rr = new Result<R> { v = default(R) };
                        // 要知道请求的rid这里只能反解出来
                        StatusCode ccc = new StatusCode(502, "HttpProxy.Error:无法访问远程服务器 rid=" + args.rid);
                        rr = new Result <object>()
                        {
                            c   = ccc.code,
                            msg = ccc.msg,
                            rid = args.rid,
                            uri = args.uri,
                            v   = null,
                        };
                    }
                    #endregion 发送请求
                }
            }
            catch (Exception ex)
            {
                StatusCode cc = new StatusCode(501, "HttpProxy.Error:" + ex.Message);
                rr.c   = cc.code;
                rr.msg = cc.msg;
                rr.v   = default(object);
                logger.LogError(eventId, ex, new LogInfo()
                {
                    ServiceName   = serverName,
                    ApiName       = args.m,
                    CreatedBy     = "httpProxy",
                    TransactionId = args.rid,
                    UseChain      = JsonConvert.SerializeObject(args.Headers),
                    CodeMsg       = rr.msg,
                    Code          = rr.c,
                    Desc          = "GrantRpcClientManager.Send<R, A>.error",
                }.ToString());
            }
            var js = new JsonSerializerSettings {
                NullValueHandling = NullValueHandling.Ignore
            };
            js.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
            js.DateFormatString   = "yyyy-MM-dd HH:mm:ss";
            var rst = JsonConvert.SerializeObject(rr, js);
            logger.LogInformation(eventId, new LogInfo()
            {
                ServiceName   = serverName,
                ApiName       = args.m,
                CreatedBy     = "httpProxy",
                TransactionId = args.rid,
                UseChain      = JsonConvert.SerializeObject(args.Headers),
                CodeMsg       = rr.msg,
                Code          = rr.c,
                Desc          = string.Format("返回结果是:{0}", rst),
            }.ToString());
            return(rst, rr);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// 客户端Rpc调用
        /// </summary>
        /// <typeparam name="R">R</typeparam>
        /// <typeparam name="A">A</typeparam>
        /// <param name="server">server</param>
        /// <param name="m">m</param>
        /// <param name="args">args</param>
        /// <param name="code">code</param>
        /// <returns>RR</returns>
        public static R Send <A, R>(string server, string m, A args, RpcContext context, out StatusCode code)
        {
            Args <A> a = new Args <A>()
            {
                ct      = ClientType.InnerRpc.ToString(), // 只有内部的rpc请求才能如此标记
                cv      = string.Empty,
                m       = m,
                v       = args,
                rid     = Guid.NewGuid().ToString("N"),
                Headers = new Dictionary <string, HeaderValue>(),
            };
            EventId eventId = new EventId(0, a.rid);

            try
            {
                #region 构造路由

                // 添加自己的头信息
                string sk  = $"{ServerSetting.AppName}(idx:{ServerSetting.Pool})_{ServiceEnvironment.ComputerName}_{ServiceEnvironment.ComputerAddress}";
                string key = $"{ServerSetting.AppName}_{HeaderValue.INNERIP}"; // 强制在一个请求链上一个微服务只能被调用一次,防止出现来回循环调用的情况出现
                a.Headers.TryAdd(key, new HeaderValue(sk, HeaderValue.INNERIP, ServiceEnvironment.ComputerAddress));

                // 原样透传rpcContext
                if (context != null)
                {
                    a.ct  = string.IsNullOrEmpty(context.Args.ct) ? a.ct : context.Args.ct;
                    a.cv  = string.IsNullOrEmpty(context.Args.cv) ? a.cv : context.Args.cv;
                    a.rid = string.IsNullOrEmpty(context.Args.rid) ? a.rid : context.Args.rid;
                    a.lg  = string.IsNullOrEmpty(context.Args.lg) ? a.lg : context.Args.lg;
                    a.tk  = string.IsNullOrEmpty(context.Args.tk) ? a.tk : context.Args.tk;
                    a.uri = string.IsNullOrEmpty(context.Args.uri) ? a.uri : context.Args.uri;
                    if (context.Headers != null && context.Headers.Any())
                    {
                        foreach (var item in context.Headers)
                        {
                            a.Headers.TryAdd(item.Key, item.Value);
                        }
                    }
                }

                int error = 0;
gotoHere:
                ClientServer cServer = null;
                ClientItem cItem = null;
                Result <R> rr    = new Result <R>();
                try
                {
                    readerWriterLock.AcquireReaderLock(80);
                    string s = server.ToLower();
                    if (cls.ContainsKey(s))
                    {
                        cServer = cls[s];
                        var clients = cServer.Client;
                        int idx     = 0;
                        switch (cServer.RouterType)
                        {
                        case RouterType.Hash:
                            idx = RouterManager.GetPool(a.uri);
                            break;

                        case RouterType.Polling:
                            idx = RouterManager.GetPolling(0, clients.Length);
                            break;

                        default:
                        case RouterType.Random:
                            idx = RouterManager.GetRandom(0, clients.Length);
                            break;
                        }

                        cItem = clients[idx];
                    }
                    else
                    {
                        StatusCode cc = new StatusCode(402, $"server :{server} not found rid = {a.rid}");
                        rr.c   = cc.code;
                        rr.msg = cc.msg;
                        rr.v   = default(R);
                        logger.LogError(eventId, new LogInfo()
                        {
                            ServiceName   = server,
                            ApiName       = a.m,
                            CreatedBy     = "FrameWork",
                            TransactionId = a.rid,
                            UseChain      = JsonConvert.SerializeObject(a.Headers),
                            CodeMsg       = rr.msg,
                            Code          = rr.c,
                            Desc          = $"server :{server} not found rid = {a.rid}",
                        }.ToString());
                    }
                }
                catch (Exception e)
                {
                    string     msg = $"获取路由信息异常{server}{e.Message} rid={a.rid}";
                    StatusCode cc  = new StatusCode(502, msg);
                    rr.c   = cc.code;
                    rr.msg = cc.msg;
                    rr.v   = default(R);
                    logger.LogCritical(eventId, new LogInfo()
                    {
                        ServiceName   = server,
                        ApiName       = a.m,
                        CreatedBy     = "FrameWork",
                        TransactionId = a.rid,
                        UseChain      = JsonConvert.SerializeObject(a.Headers),
                        CodeMsg       = rr.msg,
                        Code          = rr.c,
                        Desc          = $"获取路由信息异常{server}{e.Message} rid={a.rid}",
                    }.ToString());

                    // GrantLogTextWriter.Write(new Exception(msg, e));
                }
                finally
                {
                    if (readerWriterLock.IsReaderLockHeld)
                    {
                        readerWriterLock.ReleaseReaderLock();
                    }
                }

                #endregion 构造路由

                #region 发送请求
                var jSetting = new JsonSerializerSettings {
                    NullValueHandling = NullValueHandling.Ignore
                };
                jSetting.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
                jSetting.DateFormatString   = "yyyy-MM-dd HH:mm:ss";
                var sendValue = JsonConvert.SerializeObject(a, jSetting);
                if (cItem == null)
                {
                    code = new StatusCode(403, $"{server}的路由信息无法找到 rid={a.rid}");
                    rr.v = default(R);
                }
                else
                {
                    logger.LogInformation(eventId, $"Client发送请求\r\n\tserver={cServer.ServerName},ip={cItem.Ip},port={cItem.Port}\r\n\targs={sendValue}");
                    bool isOk = false;
                    using (IGrantRpcClient rpcClient = ClientConnectionManager.GetClient(cItem))
                    {
                        string result = null;
                        if (rpcClient.Send(sendValue, m, out result))
                        {
                            rr   = JsonConvert.DeserializeObject <Result <R> >(result);
                            code = new StatusCode(rr.c, rr.msg);
                            isOk = true;
                        }
                    }

                    if (!isOk)
                    {
                        error += 1;
                        System.Threading.Thread.Sleep(100);
                        // 重试3次
                        if (error < 3)
                        {
                            goto gotoHere; // 失败了就重新去找一个连接重试,如果是单台短时间内重试就没有意义了
                        }

                        rr = new Result <R> {
                            v = default(R)
                        };
                        code = new StatusCode(501, "client_error无法访问远程服务器 rid=" + a.rid);
                    }
                    else
                    {
                        code = new StatusCode(rr.c, rr.msg);
                    }
                }
                logger.LogInformation(eventId, $"Client返回结果\r\n\tServiceName:{server},ApiName:{a.m},Code:{code.code},CodeMsg:{code.msg},\r\n\tUseChain{JsonConvert.SerializeObject(a.Headers)}\r\n\tResult:{JsonConvert.SerializeObject(rr)}");
                return(rr.v);

                #endregion 发送请求
            }
            catch (Exception e)
            {
                code = new StatusCode(504, $"未知异常:{e.Message}");
                logger.LogError(eventId, e, $"未知异常");
                return(default(R));
            }
        }