Example #1
0
        /// <summary>
        /// 参加指定标识的分布式事务,直到事务执行完成。一个分布式事务包含若干本地事务
        /// </summary>
        /// <param name="identity">标识一个分布式事务</param>
        /// <returns></returns>
        public bool AttendTransaction(string identity)
        {
            DistTransInfo info = new DistTransInfo();

            info.ClientIdentity  = base.CurrentContext.Request.ClientIdentity;
            info.CurrentDTCState = DistTrans3PCState.CanCommit;
            info.LastStateTime   = DateTime.Now;
            info.TransIdentity   = identity;
            //DTResourceList.Add(info);
            DateTime dtcStart = DateTime.Now;
            //获取一个当前事务标识的协调器线程
            DTController controller = DTController.CheckStartController(identity);

            CurrentDTCState = DistTrans3PCState.CanCommit;
            while (CurrentDTCState != DistTrans3PCState.Completed)
            {
                //获取资源服务器的事务状态,资源服务器可能自身或者因为网络情况出错
                if (!SendDTCState(info, controller, identity))
                {
                    break;
                }
            }
            SendDTCState(info, controller, identity);
            DTController.RemoveController(identity);
            Console.WriteLine("DTC Current Use time:{0}(s)", DateTime.Now.Subtract(dtcStart).TotalSeconds);
            return(true);
        }
        /// <summary>
        /// 3阶段分布式事务请求函数,执行完本地事务操作后,请求线程将继续工作,处理分布式提交的问题
        /// </summary>
        /// <typeparam name="T">本地事务操作函数的返回类型</typeparam>
        /// <param name="client">分布式事务服务的代理客户端</param>
        /// <param name="dbHelper">数据访问对象</param>
        /// <param name="transFunction">事务操作函数</param>
        /// <returns>返回事务操作函数的结果</returns>
        public T DistTrans3PCRequest <T>(Proxy client, AdoHelper dbHelper, Func <AdoHelper, T> transFunction)
        {
            string         transIdentity = this.TransIdentity;
            ServiceRequest request       = new ServiceRequest();

            request.ServiceName = "DTCService";
            request.MethodName  = "AttendTransaction";
            request.Parameters  = new object[] { transIdentity };

            DateTime dtcReqTime = DateTime.Now;

            ResourceServerState = DistTrans3PCState.CanCommit;
            System.Threading.CancellationTokenSource cts = new System.Threading.CancellationTokenSource();
            var tcs = new TaskCompletionSource <T>();

            //可以在外部开启事务,以方便出错,回滚事务,这里检查下是否开启了事务
            if (dbHelper.TransactionCount <= 0)
            {
                dbHelper.BeginTransaction();
            }

            DataType resultDataType = MessageConverter <T> .GetResponseDataType();

            client.ErrorMessage += client_ErrorMessage;
            client.RequestService <bool, DistTrans3PCState, DistTrans3PCState>(request.ServiceUrl, resultDataType,
                                                                               r =>
            {
                PrintLog("MSF DTC({0}) Controller Process Reuslt:{1},Receive time:{2}", transIdentity, r, DateTime.Now.ToString("HH:mm:ss.fff"));
                client.Close();
            },
                                                                               s => {
                var DTR_State = ProcessDistTrans3PCState <T>(client, dbHelper, transFunction, s, tcs, transIdentity);
                if (DTR_State == DistTrans3PCState.Completed)
                {
                    PrintLog("MSF DTC({0}) 3PC Request Completed,use time:{1} seconds.", transIdentity, DateTime.Now.Subtract(dtcReqTime).TotalSeconds);
                }
                return(DTR_State);
            }
                                                                               );

            try
            {
                tcs.Task.Wait();
                return(tcs.Task.Result);
            }
            catch (Exception ex)
            {
                PrintLog("MSF DTC({0}) Task Error:{1}", transIdentity, ex.Message);
                TryRollback(dbHelper);
            }

            return(default(T));
        }
Example #3
0
        //private static System.Collections.Concurrent.ConcurrentBag<DistTransInfo> DTResourceList = new System.Collections.Concurrent.ConcurrentBag<DistTransInfo>();

        /// <summary>
        /// (资源服务器向协调器服务)注册事务操作
        /// </summary>
        /// <param name="identity">事务标识,需要在一个分布式事务下的服务请求必须使用同一个事务标识</param>
        /// <returns></returns>
        public ServiceEventSource RegisterTransaction(string identity)
        {
            //事务计数器累加
            System.Threading.Interlocked.Increment(ref TransactionResourceCount);

            return(new ServiceEventSource(new object(), 5, () => {
                //注册即向资源服务器发出 CanCommit请求
                //base.CurrentContext.PublishData(DistTrans3PCState.CanCommit);
                CurrentDTCState = DistTrans3PCState.CanCommit;
                while (CurrentDTCState != DistTrans3PCState.Completed)
                {
                    CurrentDTCState = base.CurrentContext.CallBackFunction <DistTrans3PCState, DistTrans3PCState>(CurrentDTCState);
                    Console.WriteLine("Callback Message:{0}", CurrentDTCState);
                }
            }));
        }
Example #4
0
        private bool SendDTCState(DistTransInfo info, DTController controller, string identity)
        {
            string clientIdentity = string.Format("[{0}:{1}-{2}]", base.CurrentContext.Request.ClientIP,
                                                  base.CurrentContext.Request.ClientPort,
                                                  base.CurrentContext.Request.ClientIdentity);

            try
            {
                Console.WriteLine("DTC Service Callback {0} Message:{1}", clientIdentity, CurrentDTCState);
                info.CurrentDTCState = base.CurrentContext.CallBackFunction <DistTrans3PCState, DistTrans3PCState>(CurrentDTCState);
                info.LastStateTime   = DateTime.Now;
                CurrentDTCState      = controller.GetDTCState(info.CurrentDTCState);
                return(true);
            }
            catch (Exception ex)
            {
                Console.WriteLine("DTC Service Callback {0}  Error:{1}", clientIdentity, ex.Message);
                return(false);
            }
        }
Example #5
0
 void client_ErrorMessage(object sender, MessageSubscriber.MessageEventArgs e)
 {
     ResourceServerState = DistTrans3PCState.CommunicationInterrupt;
     PrintLog("MSF DTC({0}) Service Proxy Error:{1}", this.TransIdentity, e.MessageText);
 }
Example #6
0
        /// <summary>
        /// 3阶段分布式事务请求函数,执行完本地事务操作后,请求线程将继续工作,处理分布式提交的问题
        /// </summary>
        /// <typeparam name="T">本地事务操作函数的返回类型</typeparam>
        /// <param name="client">分布式事务服务的代理客户端</param>
        /// <param name="dbHelper">数据访问对象</param>
        /// <param name="transFunction">事务操作函数</param>
        /// <returns>返回事务操作函数的结果</returns>
        public T DistTrans3PCRequest <T>(Proxy client, AdoHelper dbHelper, Func <AdoHelper, T> transFunction)
        {
            string         transIdentity = this.TransIdentity;
            ServiceRequest request       = new ServiceRequest();

            request.ServiceName = "DTCService";
            request.MethodName  = "AttendTransaction";
            request.Parameters  = new object[] { transIdentity };

            DateTime dtcReqTime = DateTime.Now;

            ResourceServerState = DistTrans3PCState.CanCommit;
            System.Threading.CancellationTokenSource cts = new System.Threading.CancellationTokenSource();
            var tcs = new TaskCompletionSource <T>();

            //可以在外部开启事务,以方便出错,回滚事务,这里检查下是否开启了事务
            if (dbHelper.TransactionCount <= 0)
            {
                dbHelper.BeginTransaction();
            }

            DataType resultDataType = MessageConverter <T> .GetResponseDataType();

            client.ErrorMessage += client_ErrorMessage;
            client.RequestService <bool, DistTrans3PCState, DistTrans3PCState>(request.ServiceUrl, resultDataType,
                                                                               r =>
            {
                PrintLog("MSF DTC({0}) Controller Process Reuslt:{1},Receive time:{2}", transIdentity, r, DateTime.Now.ToString("HH:mm:ss.fff"));
                client.Close();
            },
                                                                               s =>
            {
                PrintLog("MSF DTC({0}) Resource at {1} receive DTC Controller state:{2}", transIdentity, DateTime.Now.ToString("HH:mm:ss.fff"), s);
                if (s == DistTrans3PCState.CanCommit)
                {
                    try
                    {
                        T t = transFunction(dbHelper);
                        ResourceServerState = DistTrans3PCState.Rep_Yes_1PC;
                        tcs.SetResult(t);
                    }
                    catch (Exception ex)
                    {
                        PrintLog(ex.Message);
                        ResourceServerState = DistTrans3PCState.Rep_No_1PC;
                        tcs.SetException(ex);
                    }
                    //警告:如果自此之后,很长时间没有收到协调服务器的任何回复,本地应回滚事务
                    new Task(() =>
                    {
                        DateTime currOptTime = DateTime.Now;
                        PrintLog("MSF DTC({0}) 1PC,Child moniter task has started at time:{1}", transIdentity, currOptTime.ToString("HH:mm:ss.fff"));

                        while (ResourceServerState != DistTrans3PCState.Completed)
                        {
                            System.Threading.Thread.Sleep(10);
                            if (ResourceServerState != DistTrans3PCState.Rep_Yes_1PC && ResourceServerState != DistTrans3PCState.Rep_No_1PC)
                            {
                                //在1阶段,只要发现通信中断,就应该回滚事务
                                if (ResourceServerState == DistTrans3PCState.CommunicationInterrupt)
                                {
                                    TryRollback(dbHelper);
                                    client.Close();
                                    PrintLog("** MSF DTC({0}) 1PC,Child moniter task check Communication Interrupt ,Rollback Transaction,task break!", transIdentity);
                                }
                                else
                                {
                                    PrintLog("MSF DTC({0}) 1PC,Child moniter task find DistTrans3PCState has changed,Now is {1},task break!", transIdentity, ResourceServerState);
                                }
                                break;
                            }
                            else
                            {
                                //在1阶段回复消息后,超过一分钟,资源服务器没有收到协调服务器的任何响应,回滚本地事务
                                if (DateTime.Now.Subtract(currOptTime).TotalSeconds > 60)
                                {
                                    TryRollback(dbHelper);
                                    client.Close();
                                    PrintLog("** MSF DTC({0}) 1PC,Child moniter task check Opreation timeout,Rollback Transaction,task break!", transIdentity);
                                    break;
                                }
                            }
                        }
                    }, TaskCreationOptions.None).Start();

                    return(ResourceServerState);
                }
                else if (s == DistTrans3PCState.PreCommit)
                {
                    ResourceServerState = DistTrans3PCState.ACK_Yes_2PC;
                    //警告:如果自此之后,如果成功确认资源服务器进入第二阶段,但是很长时间没有收到协调服务器的任何回复,本地应提交事务
                    new Task(() =>
                    {
                        DateTime currOptTime = DateTime.Now;
                        PrintLog("MSF DTC({0}) 2PC,Child moniter task has started at time:{1}", transIdentity, currOptTime.ToString("HH:mm:ss.fff"));

                        while (ResourceServerState != DistTrans3PCState.Completed)
                        {
                            System.Threading.Thread.Sleep(10);
                            if (ResourceServerState != DistTrans3PCState.ACK_Yes_2PC)
                            {
                                //在2阶段,如果在1秒内就检测到通信已经中断,事务控制器可能难以收到预提交确认信息,考虑回滚本地事务
                                if (ResourceServerState == DistTrans3PCState.CommunicationInterrupt)
                                {
                                    if (DateTime.Now.Subtract(currOptTime).TotalMilliseconds < 1000)
                                    {
                                        TryRollback(dbHelper);
                                        PrintLog("** MSF DTC({0}) 2PC,Child moniter find Communication Interrupt ,task break!", transIdentity);
                                    }
                                    else
                                    {
                                        //否则,1秒后才发现连接已经断开,预提交确认信号大概率已经发送过去,不用再等,提交本地事务
                                        TryCommit(dbHelper);
                                        PrintLog("MSF DTC({0}) 2PC,Child moniter find Communication Interrupt,but ACK_Yes_2PC send ok,tansaction Commit ,task break!", transIdentity);
                                    }
                                    //已经结束事务,关闭通信连接
                                    client.Close();
                                }
                                else
                                {
                                    //如果通信未中断且已经是其它状态,退出当前子任务
                                    PrintLog("MSF DTC({0}) 2PC,Child moniter task find DistTrans3PCState has changed,Now is {1},task break!", transIdentity, ResourceServerState);
                                }
                                break;
                            }
                            else
                            {
                                //在2阶段,通信未中断,超过30秒,资源服务器没有收到协调服务器的任何响应,提交本地事务
                                if (DateTime.Now.Subtract(currOptTime).TotalSeconds > 30)
                                {
                                    TryCommit(dbHelper);
                                    client.Close();
                                    PrintLog("** MSF DTC({0}) 2PC,Child moniter task check Opreation timeout,Commit Transaction,task break!", transIdentity);
                                    break;
                                }
                            }
                        }
                    }, TaskCreationOptions.None).Start();

                    return(ResourceServerState);
                }
                else if (s == DistTrans3PCState.Abort)
                {
                    TryRollback(dbHelper);
                    ResourceServerState = DistTrans3PCState.ACK_No_2PC;
                    return(ResourceServerState);
                }
                else if (s == DistTrans3PCState.DoCommit)
                {
                    if (TryCommit(dbHelper))
                    {
                        ResourceServerState = DistTrans3PCState.Rep_Yes_3PC;
                    }
                    else
                    {
                        ResourceServerState = DistTrans3PCState.Rep_No_3PC;
                    }

                    return(ResourceServerState);
                }
                else
                {
                    //其它参数,原样返回
                    ResourceServerState = s;
                    if (s == DistTrans3PCState.Completed)
                    {
                        PrintLog("MSF DTC({0}) 3PC Request Completed,use time:{1} seconds.", transIdentity, DateTime.Now.Subtract(dtcReqTime).TotalSeconds);
                    }
                    return(s);
                }
            });



            try
            {
                tcs.Task.Wait();
                return(tcs.Task.Result);
            }
            catch (Exception ex)
            {
                PrintLog("MSF DTC({0}) Task Error:{1}", transIdentity, ex.Message);
                TryRollback(dbHelper);
            }

            return(default(T));
        }
Example #7
0
        /// <summary>
        /// 获取分布式事务的状态,注意某个调用线程可能会被阻塞等待
        /// </summary>
        /// <param name="resourceState">资源服务器响应的状态</param>
        /// <returns></returns>
        public DistTrans3PCState GetDTCState(DistTrans3PCState resourceState)
        {
            if (resourceState == DistTrans3PCState.Rep_No_1PC)
            {
                //在1阶段,只要有一个资源服务器响应为不成功,则协调器将发出 终止指令。
                this.TransAbort = true;
                return(DistTrans3PCState.Abort);
            }
            else if (resourceState == DistTrans3PCState.Rep_Yes_1PC)
            {
                //当前线程增加一个事务准备成功的计数器
                System.Threading.Interlocked.Increment(ref PrearedOKCount);
                int waiteTime = 0;
                int timeSpan  = 10;//毫秒
                while (PrearedOKCount < TransResourceCount)
                {
                    //如果等待超时,则应该取消当前分布式事务
                    if (waiteTime >= MAX_WAIT_TIME)
                    {
                        this.TransAbort = true;
                        PrintLog("MSF DTC{0} 1PC waite timeout ({1} ms),transaction Abort.", this.TransIdentity, MAX_WAIT_TIME);
                    }
                    if (this.TransAbort)
                    {
                        return(DistTrans3PCState.Abort);
                    }
                    System.Threading.Thread.Sleep(timeSpan);
                    waiteTime += timeSpan;
                }
                //如果每个事务资源服务器执行都成功,进入第二阶段:预提交阶段
                return(DistTrans3PCState.PreCommit);
            }
            else if (resourceState == DistTrans3PCState.ACK_No_2PC)
            {
                return(DistTrans3PCState.Completed);
            }
            else if (resourceState == DistTrans3PCState.ACK_Yes_2PC)
            {
                //如果收到资源服务器预备提交的回复,得等待所有资源服务器确认回复此信息,然后发出提交指令
                //如果等待到超时,也没有等到预提交的全部回复,说明某个资源服务器或者网络出现问题,应该发出终止指令
                //注意:这里的等待,应该比资源服务器等待提交指令的时间要短
                //当前线程增加一个事务准备成功的计数器
                System.Threading.Interlocked.Increment(ref PreCommitOKCount);
                int waiteTime = 0;
                int timeSpan  = 10;//毫秒
                while (PreCommitOKCount < TransResourceCount)
                {
                    //如果等待超时(10秒),则应该取消当前分布式事务
                    if (waiteTime >= 10000)
                    {
                        this.TransAbort = true;
                        PrintLog("MSF DTC({0}) 2PC waite timeout ({1} ms),transaction Abort.", this.TransIdentity, waiteTime);
                    }

                    if (this.TransAbort)
                    {
                        return(DistTrans3PCState.Abort);
                    }
                    System.Threading.Thread.Sleep(timeSpan);
                    waiteTime += timeSpan;
                }
                //如果每个事务资源服务器都已经回复,进入第三阶段:提交阶段
                return(DistTrans3PCState.DoCommit);
            }
            else if (resourceState == DistTrans3PCState.Rep_No_3PC)
            {
                return(DistTrans3PCState.Completed);
            }
            else if (resourceState == DistTrans3PCState.Rep_Yes_3PC)
            {
                return(DistTrans3PCState.Completed);
            }
            else
            {
                return(DistTrans3PCState.Completed);
            }
        }
        private DistTrans3PCState ProcessDistTrans3PCState <T>(Proxy client, AdoHelper dbHelper, Func <AdoHelper, T> transFunction, DistTrans3PCState s, TaskCompletionSource <T> tcs, string transIdentity)
        {
            PrintLog("MSF DTC({0}) Resource at {1} receive DTC Controller state:{2}", transIdentity, DateTime.Now.ToString("HH:mm:ss.fff"), s);
            if (s == DistTrans3PCState.CanCommit)
            {
                try
                {
                    T t = transFunction(dbHelper);
                    ResourceServerState = DistTrans3PCState.Rep_Yes_1PC;
                    tcs.SetResult(t);
                }
                catch (Exception ex)
                {
                    PrintLog(ex.Message);
                    ResourceServerState = DistTrans3PCState.Rep_No_1PC;
                    tcs.SetException(ex);
                }
                //警告:如果自此之后,很长时间没有收到协调服务器的任何回复,本地应回滚事务
                new Task(() =>
                {
                    DateTime currOptTime = DateTime.Now;
                    PrintLog("MSF DTC({0}) 1PC,Child moniter task has started at time:{1}", transIdentity, currOptTime.ToString("HH:mm:ss.fff"));

                    while (ResourceServerState != DistTrans3PCState.Completed)
                    {
                        System.Threading.Thread.Sleep(10);
                        if (ResourceServerState != DistTrans3PCState.Rep_Yes_1PC && ResourceServerState != DistTrans3PCState.Rep_No_1PC)
                        {
                            //在1阶段,只要发现通信中断,就应该回滚事务
                            if (ResourceServerState == DistTrans3PCState.CommunicationInterrupt)
                            {
                                TryRollback(dbHelper);
                                client.Close();
                                PrintLog("** MSF DTC({0}) 1PC,Child moniter task check Communication Interrupt ,Rollback Transaction,task break!", transIdentity);
                            }
                            else
                            {
                                PrintLog("MSF DTC({0}) 1PC,Child moniter task find DistTrans3PCState has changed,Now is {1},task break!", transIdentity, ResourceServerState);
                            }
                            break;
                        }
                        else
                        {
                            //在1阶段回复消息后,超过一分钟,资源服务器没有收到协调服务器的任何响应,回滚本地事务
                            if (DateTime.Now.Subtract(currOptTime).TotalSeconds > 60)
                            {
                                TryRollback(dbHelper);
                                client.Close();
                                PrintLog("** MSF DTC({0}) 1PC,Child moniter task check Opreation timeout,Rollback Transaction,task break!", transIdentity);
                                break;
                            }
                        }
                    }
                }, TaskCreationOptions.None).Start();

                return(ResourceServerState);
            }
            else if (s == DistTrans3PCState.PreCommit)
            {
                ResourceServerState = DistTrans3PCState.ACK_Yes_2PC;
                //警告:如果自此之后,如果成功确认资源服务器进入第二阶段,但是很长时间没有收到协调服务器的任何回复,本地应提交事务
                new Task(() =>
                {
                    DateTime currOptTime = DateTime.Now;
                    PrintLog("MSF DTC({0}) 2PC,Child moniter task has started at time:{1}", transIdentity, currOptTime.ToString("HH:mm:ss.fff"));

                    while (ResourceServerState != DistTrans3PCState.Completed)
                    {
                        System.Threading.Thread.Sleep(10);
                        if (ResourceServerState != DistTrans3PCState.ACK_Yes_2PC)
                        {
                            //在2阶段,如果在1秒内就检测到通信已经中断,事务控制器可能难以收到预提交确认信息,考虑回滚本地事务
                            if (ResourceServerState == DistTrans3PCState.CommunicationInterrupt)
                            {
                                if (DateTime.Now.Subtract(currOptTime).TotalMilliseconds < 1000)
                                {
                                    TryRollback(dbHelper);
                                    PrintLog("** MSF DTC({0}) 2PC,Child moniter find Communication Interrupt ,task break!", transIdentity);
                                }
                                else
                                {
                                    //否则,1秒后才发现连接已经断开,预提交确认信号大概率已经发送过去,不用再等,提交本地事务
                                    TryCommit(dbHelper);
                                    PrintLog("MSF DTC({0}) 2PC,Child moniter find Communication Interrupt,but ACK_Yes_2PC send ok,tansaction Commit ,task break!", transIdentity);
                                }
                                //已经结束事务,关闭通信连接
                                client.Close();
                            }
                            else
                            {
                                //如果通信未中断且已经是其它状态,退出当前子任务
                                PrintLog("MSF DTC({0}) 2PC,Child moniter task find DistTrans3PCState has changed,Now is {1},task break!", transIdentity, ResourceServerState);
                            }
                            break;
                        }
                        else
                        {
                            //在2阶段,通信未中断,超过30秒,资源服务器没有收到协调服务器的任何响应,提交本地事务
                            if (DateTime.Now.Subtract(currOptTime).TotalSeconds > 30)
                            {
                                TryCommit(dbHelper);
                                client.Close();
                                PrintLog("** MSF DTC({0}) 2PC,Child moniter task check Opreation timeout,Commit Transaction,task break!", transIdentity);
                                break;
                            }
                        }
                    }
                }, TaskCreationOptions.None).Start();

                return(ResourceServerState);
            }
            else if (s == DistTrans3PCState.Abort)
            {
                TryRollback(dbHelper);
                ResourceServerState = DistTrans3PCState.ACK_No_2PC;
                return(ResourceServerState);
            }
            else if (s == DistTrans3PCState.DoCommit)
            {
                if (TryCommit(dbHelper))
                {
                    ResourceServerState = DistTrans3PCState.Rep_Yes_3PC;
                }
                else
                {
                    ResourceServerState = DistTrans3PCState.Rep_No_3PC;
                }

                return(ResourceServerState);
            }
            else
            {
                //其它参数,原样返回
                ResourceServerState = s;
                return(s);
            }
        }