公司数据同步程序的设计思路(三)

在恐慌中度过了一个新年之后,回到了工作岗位,

刚想起来走之前对同步程序的一次改造。

基本上已经接近心目中最完美的状态了,

还有一个需求不太可能需要但很应该比较有用的配置,就是可以配置数据源类型,支持数据库,csv,excel,接口请求等。

本篇接第一篇的末尾。

实现了在每个租户编号下面再做一个数组来配置需要同步的数据。

代码中使用了 Npoco 的 Fetch<dynamic> 动态查询数据,无需建出实体类。

然后将数据转换为 Json 字符串,以二进制写进请求流直接发送请求即可。

配置文件改造后如下:

目前配置的租户数量已经有十个左右了,为了能够分辨,加了一些描述项。

推送任务变成了数组,可配置多个。

还和之前一样,拿到了租户配置对象之后,

使用 Newtonsoft 的 JArray 转换数组配置项:

            ConfigPushItems = JArray.Parse(ConfigItem["PushItems"].ToString());

然后是主要循环体:

运行时输出一些关键的配置信息用来确认没有配置问题,然后循环处理每个任务项:

使用 Npoco 动态查询数据:

        private List<dynamic> GetData(JToken config)
        {
            Print.LogInfo($"开始获取数据:{config["Name"]}");
            var datas = new List<dynamic>();
            using (var db = DBFactory.GetDB())
            {
                datas = db.Fetch<dynamic>(config["GetDataSql"].ToString());
            }
            Print.LogInfo("获取数据条数:" + datas.Count);
            return datas;
        }

二进制推送数据:

private void PushData(JToken pushConfigItem, List<dynamic> data)
        {
            Print.LogInfo($"开始推送数据:{pushConfigItem["Name"]}");
            var allListGroup = DBFactory.GetListGroup(data, 2500);
            Print.LogInfo($"数据分块组数量: {allListGroup.Count}");

            for (int i = 0; i < allListGroup.Count; i++)
            {
                var item = allListGroup[i];
                Print.LogInfo($"本次推送数量:{item.Count}");
                var datastr = JArray.FromObject(item).ToString();
                var pushAddress = string.Format("{0}{1}", HostConfig.GetHostUrl(ConfigItem["Host"].ToString()), pushConfigItem["PushDataAddress"].ToString());
                pushAddress = Url.ChangeArgTag(pushAddress, "esccode", ConfigItem["EscCode"].ToString());
                pushAddress = Url.ChangeArgTag(pushAddress, "accesstoken", ToKen);

                Print.LogInfo($"推送数据URL:{pushAddress}");
                var result = Http.Post(pushAddress, datastr);
                if (result == null)
                { Print.Err("接口返回值为 NULL"); }
                var resultJobj = JObject.Parse(result);
                Print.LogInfo($"推送数据完成 返回体:{result.ToString()}");
            }

            Print.LogInfo($"推送数据:{pushConfigItem["Name"]} 完成");
        }

这里还有一个小插曲,

在正式服务器上执行时总会报 基础链接已关闭 的异常,一开始我还以为是服务器网络设置的问题,

百度的大多解决方案大多是回收请求GC,主动释放请求对象,使用 ServicePointManager 对象设置请求的一些系统级设置。

多次尝试后无果,最后发现数据量在3000条往上就会报这个异常,少于这个数量则没有问题。

所以增加了一道推送数据的分块,每次只推送2500条数据。也算是曲线救国吧。原因的话还不是很清楚,可能是我们平台限制了请求大小?

至此,这个小玩意应该可以满足我可预见的需求了。

稍候将会将代码修改成相对通用的放在我的 github 上。

原文地址:https://www.cnblogs.com/Aaxuan/p/12502426.html