using BayonetTransfer.Common.Json; using Newtonsoft.Json; using RabbitMQ.Client; using RabbitMQ.Client.Events; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace BayonetTransfer { internal class Program { /// /// 接收到的卡口数据缓存 /// private static ConcurrentDictionary List_Bayonet { get; set; } /// /// 卡口数据保存计时器 /// private static System.Timers.Timer UploadTimer { get; set; } /// /// 卡口数据保存线程 /// private static System.Threading.Thread UploadThread { get; set; } public delegate bool ControlCtrlDelegate(int CtrlType); [DllImport("kernel32.dll")] private static extern bool SetConsoleCtrlHandler(ControlCtrlDelegate HandlerRoutine, bool Add); private static ControlCtrlDelegate cancelHandler = new ControlCtrlDelegate(HandlerRoutine); public static bool HandlerRoutine(int CtrlType) { switch (CtrlType) { case 0: Console.WriteLine("0工具被强制关闭"); //Ctrl+C关闭 break; case 2: Console.WriteLine("2工具被强制关闭");//按控制台关闭按钮关闭 break; } Console.ReadLine(); return false; } static void Main(string[] args) { SetConsoleCtrlHandler(cancelHandler, true); List_Bayonet = new ConcurrentDictionary(); //数据上传定时器 UploadTimer = new System.Timers.Timer(1 * 60 * 1000); //注册定时器执行事件方法 UploadTimer.Elapsed += UploadTimer_Elapsed; //启动定时器 UploadTimer.Start(); try { //启动RabbitMQ消息队列接收服务 Subcribe(); } catch (Exception ex) { Console.Write(string.Format("RabbitMQ连接异常:{0}\n", ex.ToString())); } Console.ReadKey(); } /// /// 上传定时器方法 /// /// /// private static void UploadTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (UploadThread == null || !UploadThread.IsAlive) { UploadThread = new System.Threading.Thread(() => { try { UploadDataToSerive(); } catch (Exception ex) { Console.WriteLine($"卡口数据上传失败:{ex.Message}"); Common.LoggerHelper.WriteLogger($"卡口数据上传失败:{ex.ToString()}"); } }) { IsBackground = true }; UploadThread.Start(); } } /// /// 启动RabbitMQ消息队列接收服务 /// private static void Subcribe() { string str_HostName = ConfigurationManager.AppSettings["HostName"]; string str_Port = ConfigurationManager.AppSettings["Port"]; string str_UserName = ConfigurationManager.AppSettings["UserName"]; string str_Password = ConfigurationManager.AppSettings["Password"]; //实例化一个连接工厂和其配置为使用所需的主机,虚拟主机和证书(证书) ConnectionFactory factory = new ConnectionFactory { HostName = str_HostName,//"112.30.55.253",//RabbitMQ主机服务地址 Port = int.Parse(str_Port),//5672,//RabbitMQ主机服务端口 UserName = str_UserName,//"yishang",//用户名 Password = str_Password,//"Yishang%2022",//密码 VirtualHost = "/"//默认情况可省略此行 }; //创建一个AMQP 0-9-1连接 using (IConnection connection = factory.CreateConnection()) { //创建一个AMQP 0-9-1频道,该对象提供了大部分 的操作(方法)协议。 using (IModel channel = connection.CreateModel()) { #region 定义队列、交换器并绑定 //队列 channel.QueueDeclare("yishang", true, false, false, null); //交换器 channel.ExchangeDeclare("entrance_flow_exchange", ExchangeType.Fanout, true, false, null); //绑定 channel.QueueBind("yishang", "entrance_flow_exchange", "RoutingKey", null); #endregion Console.WriteLine("卡口数据接收服务已准备就绪~~"); //消费者 var consumer = new EventingBasicConsumer(channel); consumer.Received += (model, ea) => { var body = ea.Body; var message = Encoding.UTF8.GetString(body.ToArray()); string str_Key = Guid.NewGuid().ToString("N"); try { var bayonet = JsonConvert.DeserializeObject(message, new JsonSerializerSettings() { ContractResolver = new OcrWriteResolver() }); List_Bayonet.AddOrUpdate(str_Key, bayonet, (key, bay) => bayonet); Console.WriteLine($"[{bayonet.InOut_Time}]{bayonet.License_Plate},{bayonet.Serverpart_Name}{bayonet.Serverpart_Region}"); } catch (Exception ex) { Common.LoggerHelper.WriteLogger($"卡口数据接收解析异常,GUID:{str_Key},接收到的数据:{message},错误信息:{ex.Message}"); } }; //自动ack消费 channel.BasicConsume("yishang", true, consumer); Console.ReadLine(); } } } /// /// 保存接收到的卡口数据到服务器 /// private static void UploadDataToSerive() { //接口地址 string str_ApiURL = ConfigurationManager.AppSettings["ApiURL"];//"http://openapi.eshangtech.com:7080/WebApi/BigData/AddBayonet" Console.WriteLine("接口地址:" + str_ApiURL); //定义上传到接口的数据列表 List list_ApiBayonet = new List(); //定义已处理的卡口数据列表Key,在数据上传成功后,移除数据缓存 List str_Remove = new List(); Console.WriteLine($"【{DateTime.Now}】开始上传卡口数据到服务器"); //记录文本日志 Common.LoggerHelper.WriteLogger("开始上传卡口数据到服务器"); //从缓存中取出全部需要处理的数据 foreach (var model in List_Bayonet.ToArray()) { //停留时长 int.TryParse(model.Value.Stay_Times, out int int_StayTimes); //转换为接口数据格式 list_ApiBayonet.Add(new Model.ApiBayonetModel { Serverpart_Name = model.Value.Serverpart_Name, Serverpart_Region = model.Value.Serverpart_Region, InOut_Type = model.Value.InOut_Type, InOut_Time = long.Parse(model.Value.InOut_Time.ToString("yyyyMMddHHmmss")), Vehicle_Type = model.Value.Vehicle_Type, License_Plate = model.Value.License_Plate, Vehicle_Speed = model.Value.Vehicle_Speed, Stay_Times = int_StayTimes, Bayonet_Desc = model.Value.Bayonet_Desc }); //添加待移除数据Key到列表 str_Remove.Add(model.Key); } //记录文本日志 Common.LoggerHelper.WriteLogger($"本次接收{list_ApiBayonet.Count}条卡口流水"); //每次上传的数据量(经过测试,安徽卡口抓拍数量,每分钟最大值在400条左右, //Api接口每秒处理数据量在100条左右,综合后设定每次最大上传500条,以保证接口稳定和数据及时性) int int_Size = 500; //缓存数据分页 int int_PageCount = (int)Math.Ceiling((decimal)list_ApiBayonet.Count / int_Size); for (int i = 0; i < int_PageCount; i++) { //取分页数据 var list_Temp = list_ApiBayonet.Skip(i * int_Size).Take(int_Size).ToList(); //拼接接口参数字符串 string str_PostData = JsonConvert.SerializeObject(list_Temp); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); try { //调用接口并解析返回的数据 string str_Result = Common.HttpHelper.HttpPost(str_PostData, str_ApiURL, "application/json", 120); //解析接口返回值 Model.ResultDataModel rm_ResultModel = JsonConvert.DeserializeObject>(str_Result); sw.Stop(); //数据上传成功 if (rm_ResultModel.Result_Code == 100) { //删除已上传的缓存数据 str_Remove.ForEach(p => List_Bayonet.TryRemove(p, out _)); Console.WriteLine($"卡口数据上传成功。本次上传{list_Temp.Count}条;用时:{sw.Elapsed.TotalSeconds}秒"); //记录文本日志 Common.LoggerHelper.WriteLogger($"卡口数据上传成功。本次上传{list_Temp.Count}条"); } else { Console.WriteLine($"卡口数据上传失败,接口错误信息:[{rm_ResultModel.Result_Code}]{rm_ResultModel.Result_Desc}"); //记录文本日志 Common.LoggerHelper.WriteLogger($"卡口数据上传失败,接口错误信息:[{rm_ResultModel.Result_Code}]{rm_ResultModel.Result_Desc}"); //记录文本日志 Common.LoggerHelper.WriteLogger($"发送到Api接口的数据:{str_PostData}"); } } catch (Exception ex) { Console.WriteLine($"卡口数据上传失败,错误信息:{ex.Message}"); Common.LoggerHelper.WriteLogger($"卡口数据上传失败,错误信息:{ex.Message}"); Common.LoggerHelper.WriteLogger($"发送到Api接口的数据:{str_PostData}"); } } //记录文本日志 Common.LoggerHelper.WriteLogger($"卡口流水传输结束"); } } }