/// <summary> /// 异步ack /// </summary> private void CanalServerAckStart() { new Thread(() => { _logger.LogInformation("canal-server ack worker thread start ..."); while (!_isDispose) { try { if (_canalConnector == null) { continue; } if (!_queue.TryDequeue(out var batchId)) { continue; } if (batchId > 0) { _canalConnector.Ack(batchId); //如果程序突然关闭 cannal service 会关闭。这里就不会提交,下次重启应用消息会重复推送! } } catch (Exception) { //ignore } } }).Start(); }
/// <summary> /// 发送数据 /// 如果handler处理失败就停止 保证消息 /// </summary> /// <param name="entrys">一个entry表示一个数据库变更</param> /// <param name="batchId"></param> private (long, Dictionary <string, ProcessResult>, List <(string, long)>) Send(List <Entry> entrys, long batchId) { var canalBodyList = GetCanalBodyList(entrys); if (canalBodyList.Count < 1) { return(0, null, null); } if (_registerTypeList == null || !_registerTypeList.Any()) { return(0, null, null); } var groupCount = new List <(string, long)>(); //分组日志 var group = canalBodyList.Select(r => r.Message).GroupBy(r => new { r.DbName, r.TableName, r.EventType }); foreach (var g in group) { groupCount.Add(($"{g.Key.DbName}.{g.Key.TableName}.{g.Key.EventType}", g.Count())); } Dictionary <string, ProcessResult> result = new Dictionary <string, ProcessResult>(); foreach (var re in _registerTypeList) { // ReSharper disable once AssignNullToNotNullAttribute result.Add(re.FullName, new ProcessResult()); } try { foreach (var type in _registerTypeList) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // ReSharper disable once AssignNullToNotNullAttribute var re = result[type.FullName]; foreach (var message in canalBodyList) { var service = _scope.ServiceProvider.GetRequiredService(type) as INotificationHandler <CanalBody>; service?.Handle(message).ConfigureAwait(false).GetAwaiter().GetResult(); re.Total++; if (message.Succ) { re.SuccessCount++; } } stopwatch.Stop(); var doutime = (int)stopwatch.Elapsed.TotalSeconds; var time = doutime > 1 ? ParseTimeSeconds(doutime) : stopwatch.Elapsed.TotalMilliseconds + "ms"; re.ProcessTime = time; } } catch (Exception e) { _logger.LogError(e, "canal produce error,end process!"); Dispose(); return(canalBodyList.Count, result, groupCount); } _canalConnector.Ack(batchId);//如果程序突然关闭 cannal service 会关闭。这里就不会提交,下次重启应用消息会重复推送! return(canalBodyList.Count, result, groupCount); }