记一次 .NET 某电商定向爬虫 内存碎片化分析

一:背景

1. 讲故事

上个月有位朋友wx找到我,说他的程序存在内存泄漏问题,寻求如何解决? 如下图所示:

3d4368e27235947353cc2fc26544c3ec.png

从截图中可以看出,这位朋友对 windbg 的操作还是有些熟悉的,可能缺乏一定的实操经验,所以用了几个命令之后就不知道怎么排查下去了。

既然找到我,那就以我的个人经验在他的dump上继续分析寻找罪魁祸首,闲话不多说,上windbg说话。

二:Windbg 分析

1. 真的存在内存泄漏吗?

追这个系列的朋友应该知道,我无数次的用 !address -summary!eeheap -gc 这两个命令来判断当前的内存泄漏是属于托管层还是非托管层。

0:000> !address -summary--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free                                    358     7dfc`67f60000 ( 125.986 TB)           98.43%
<unknown>                              1087      203`88b6e000 (   2.014 TB)  99.99%    1.57%
Image                                  1532        0`09f11000 ( 159.066 MB)   0.01%    0.00%
Heap                                    249        0`03453000 (  52.324 MB)   0.00%    0.00%
Stack                                    66        0`01fc0000 (  31.750 MB)   0.00%    0.00%
Other                                    10        0`001d1000 (   1.816 MB)   0.00%    0.00%
TEB                                      22        0`0002c000 ( 176.000 kB)   0.00%    0.00%
PEB                                       1        0`00001000 (   4.000 kB)   0.00%    0.00%--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_MAPPED                              183      200`00d06000 (   2.000 TB)  99.30%    1.56%
MEM_PRIVATE                            1252        3`8d479000 (  14.207 GB)   0.69%    0.01%
MEM_IMAGE                              1532        0`09f11000 ( 159.066 MB)   0.01%    0.00%--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE                                358     7dfc`67f60000 ( 125.986 TB)           98.43%
MEM_RESERVE                             749      200`28a9b000 (   2.001 TB)  99.33%    1.56%
MEM_COMMIT                             2218        3`6f5f5000 (  13.740 GB)   0.67%    0.01%0:000> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x00000026DA8DA928
generation 1 starts at 0x00000026DA7FC348
generation 2 starts at 0x00000024C4691000
ephemeral segment allocation context: nonesegment             begin         allocated              size
00000024C4690000  00000024C4691000  00000024D468FF28  0xfffef28(268431144)
00000024EECF0000  00000024EECF1000  00000024FECF0000  0xffff000(268431360)
000000248D6F0000  000000248D6F1000  000000249D6EFEF8  0xfffeef8(268431096)
...
00000026D66D0000  00000026D66D1000  00000026DBA3CA30  0x536ba30(87472688)
Large object heap starts at 0x00000024D4691000segment             begin         allocated              size
00000024D4690000  00000024D4691000  00000024DC67C318  0x7feb318(134132504)
00000024E60F0000  00000024E60F1000  00000024EE0637C8  0x7f727c8(133638088)
0000002482140000  0000002482141000  000000248A08F338  0x7f4e338(133489464)
00000024A6770000  00000024A6771000  00000024AE76F6C0  0x7ffe6c0(134211264)
...
000000278E6D0000  000000278E6D1000  000000279635F2D0  0x7c8e2d0(130605776)
00000029233E0000  00000029233E1000  000000292AF672F8  0x7b862f8(129524472)
000000292B3E0000  000000292B3E1000  0000002931A5ED60  0x667dd60(107470176)
000000299B3E0000  000000299B3E1000  00000029A20095B0  0x6c285b0(113411504)
000000281E6D0000  000000281E6D1000  0000002825CD3F58  0x7602f58(123744088)
00000028266D0000  00000028266D1000  000000282D5CAD50  0x6ef9d50(116366672)
000000282E6D0000  000000282E6D1000  0000002833CA0880  0x55cf880(89979008)
00000029A33E0000  00000029A33E1000  00000029A684D300  0x346c300(54969088)
Total Size:              Size: 0x353f96d88 (14293757320) bytes.
------------------------------
GC Heap Size:    Size: 0x353f96d88 (14293757320) bytes.

从输出看,当前进程占用 MEM_COMMIT=13.7G,托管堆内存占用 14293757320 = 13.3G,很明显这属于简单模式的 托管内存泄漏,根据经验,托管堆上可能有什么大对象,这里用 !dumpheap -stat 命令。

0:000> !dumpheap -stat
Statistics:MT    Count    TotalSize Class Name
00007ff9ed6ea268  3956842     94964208 System.Collections.Generic.Dictionary`2+KeyCollection[[System.String, System.Private.CoreLib],[Serilog.Events.LogEventPropertyValue, Serilog]]
00007ff9ed5e6d28  3842435    166405016 Serilog.Parsing.MessageTemplateToken[]
00007ff9ed5e5e28  3842434    184436832 Serilog.Events.MessageTemplate
00007ff9ecccf090  4011012    203304420 System.Int32[]
00007ff9ed647078  3956849    253238336 Serilog.Events.LogEvent
00007ff9ed6e7b48  3956849    284893128 System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[Serilog.Events.LogEventPropertyValue, Serilog]]
00007ff9ed5e74e8  9259598    296307136 Serilog.Parsing.TextToken
00007ff9ed6471b0 12551808    301243392 Serilog.Events.ScalarValue
00007ff9ed6e8308  3956849    729078048 System.Collections.Generic.Dictionary`2+Entry[[System.String, System.Private.CoreLib],[Serilog.Events.LogEventPropertyValue, Serilog]][]
00007ff9eccb1e18 16546412   3987811940 System.String
00000024c3b8faf0    82904   7382993568      Free

我去,托管堆最大的对象居然是 Free,大概占用 7.3G, 这就🐂👃了,不按套路出牌哈,为了更好的理解,先来简要解释下 free 对象。

2. 简单解释 free

其实简而言之,free对象是被gc标记成已回收的空闲块但并未提交给操作系统释放的对象,那怎么去证明呢? 可以先到托管堆上找一个free块。

0:000> !dumpheap -type FreeAddress               MT     Size
00000024c4691000 00000024c3b8faf0       24 Free
00000024c46a2448 00000024c3b8faf0       24 Free
00000024c46b26d8 00000024c3b8faf0       40 Free
00000024c47e4418 00000024c3b8faf0       40 Free
00000024c4925680 00000024c3b8faf0       40 Free
00000024c49284a8 00000024c3b8faf0       64 Free
00000024c4947a90 00000024c3b8faf0      192 Free
00000024c4951f70 00000024c3b8faf0       48 Free         
000000249d6ea3a8 00000024c3b8faf0      640 Free
  1. 用 !do 命令查看是否标记为free块

0:000> !do 000000249d6ea3a8
Free Object
Size:        640(0x280) bytes
  1. 用 dc 看一下这个 free 块的内容,是否有gc回收的痕迹。

0:000> dc 000000249d6ea3a8 000000249d6ea3a8+0x280
00000024`9d6ea3a8  c3b8faf0 00000024 00000268 00000000  ....$...h.......
00000024`9d6ea3b8  9d6ea6d0 00000024 00000000 00000000  ..n.$...........
00000024`9d6ea3c8  ed3ae2b8 00007ff9 9d6ea3a8 00000024  ..:.......n.$...
00000024`9d6ea3d8  00000000 00000000 edcc9118 00007ff9  ................
00000024`9d6ea3e8  00000000 00000000 00000000 00000000  ................
00000024`9d6ea3f8  00000000 00000000 00000000 00000000  ................
00000024`9d6ea408  eeb07a50 00007ff9 9d6ea3c8 00000024  Pz........n.$...
00000024`9d6ea418  00000000 00000000 ef292ee8 00007ff9  ..........).....
00000024`9d6ea428  9d6ea408 00000024 00000000 00000000  ..n.$...........
...
00000024`9d6ea4a8  eeb0a158 00007ff9 9d6ea420 00000024  X....... .n.$...
00000024`9d6ea4b8  00000000 00000000 00000000 00000000  ................
00000024`9d6ea4c8  ef293818 00007ff9 9d6ea4a8 00000024  .8).......n.$...
00000024`9d6ea4d8  00000000 00000000 ee8357e0 00007ff9  .........W......
...
00000024`9d6ea508  eed37b40 00007ff9 00000000 00000000  @{..............
00000024`9d6ea518  00000000 00000000 00000000 00000000  ................
00000024`9d6ea528  c4699b48 00000024 00000000 00000000  H.i.$...........
00000024`9d6ea538  00000000 07000440 00000001 00000000  ....@...........
00000024`9d6ea548  00000000 00000000 00000000 00000000  ................
00000024`9d6ea558  00000000 00000000 ef2af6e0 00007ff9  ..........*.....
00000024`9d6ea568  00000000 00000000 00000000 00000000  ................
00000024`9d6ea578  00000000 00000000 c4699b48 00000024  ........H.i.$...
00000024`9d6ea588  00000000 00000000 00000000 07000400  ................
...
00000024`9d6ea628  ef2afd08                             ..*.

可以看到,这个free块生前是有一些残留的内容字符,好了,对 free 块有基本了解后,接下来我们继续探究下。

3. 到底是什么阻止了free块的合并?

按照正常逻辑,大多free块会在gc回收完之后合并内存时,那些被清空后的segment会被操作系统释放的,但这个dump并没有,也就说明这里有什么东西阻止了free块的合并,那到底是什么呢? 有经验的朋友会说,可以观察下 gc 的句柄表,命令为 !gchandles -stat

0:000> !gchandles -stat
Statistics:MT    Count    TotalSize Class Name
...
00007ff9ed15c0f0     1008        72576 System.Reflection.Emit.DynamicResolver
00007ff9ecbf6618       38       409344 System.Object[]
Total 1784 objectsHandles:Strong Handles:       233Pinned Handles:       16Async Pinned Handles: 18Ref Count Handles:    1Weak Long Handles:    1327Weak Short Handles:   144Dependent Handles:    45

从输出看,这里并没有什么可疑的地方,那怎么办呢? 实操经验多的话,这里还是有一些经验值得分享的,比如观察 free 在 heap 上的布局特征,往往就有重大发现。

4. 查看 free 块的布局特征

为了简化输出结果,我把范围限定到 heap 上某一个 segment 上,比如这里的: 00000029233E0000 000000292AF672F8,所以命令就是 !dumpheap 00000029233E0000 000000292AF672F8

0:000> !dumpheap 00000029233E0000  000000292AF672F8Address               MT     Size
00000029233e1000 00000024c3b8faf0  8291896 Free
0000002923bc9638 00007ff9eccb1e18   108448     
0000002923be3dd8 00000024c3b8faf0 29931248 Free
000000292586f4c8 00007ff9eccb1e18   301328     
00000029258b8dd8 00000024c3b8faf0 41384784 Free
0000002928030928 00007ff9eccb1e18   301328     
000000292807a238 00000024c3b8faf0  2542664 Free
00000029282e6e80 00007ff9eccb1e18   108448     
0000002928301620 00000024c3b8faf0 29915032 Free
0000002929f88db8 00007ff9eccb1e18   301328     
0000002929fd26c8 00000024c3b8faf0  2746688 Free
000000292a271008 00007ff9eccb1e18   291304     
000000292a2b81f0 00000024c3b8faf0  1019600 Free
000000292a3b10c0 00007ff9eccb1e18   108448     
000000292a3cb860 00000024c3b8faf0 10601048 Free
000000292ade7ab8 00007ff9eccb1e18   301328     
000000292ae313c8 00000024c3b8faf0   280808 Free
000000292ae75cb0 00007ff9eccb1e18   280854     
000000292aeba5c8 00000024c3b8faf0   416584 Free
000000292af20110 00007ff9eccb1e18   291304     Statistics:MT    Count    TotalSize Class Name
00007ff9eccb1e18       10      2394118 System.String
00000024c3b8faf0       10    127130352      Free
Total 20 objects

真是一看吓一跳,free 和 object 呈交替状,这就是为什么free块不能被合并的真正原因,说实话这种教科书式的 内存碎片化 dump,真是可遇不可求,接下来就抽几个 free 之间的 object 对象,看看到底是被什么引用着导致gc回收不掉。

5. 寻找 object 的引用链

要想查看 object 到底被谁引用着,可以用 !gcroot 命令,这里我抽二个看看。

0:000> !gcroot 0000002923bc9638
Thread 1878:00000024C39BE4B0 00007FFA4C0B3522 System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken) [/_/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs @ 2922]rbp+10: 00000024c39be520->  00000024C48AD6E0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions+<RunAsync>d__4, Microsoft.Extensions.Hosting.Abstractions]]->  00000024C48AD200 Microsoft.Extensions.Hosting.Internal.Host->  00000024C48AC538 Microsoft.Extensions.Logging.Logger`1[[Microsoft.Extensions.Hosting.Internal.Host, Microsoft.Extensions.Hosting]]->  00000024C48AC658 Microsoft.Extensions.Logging.Logger->  00000024C48AC680 Microsoft.Extensions.Logging.LoggerInformation[]->  00000024C48AC6E0 Serilog.Extensions.Logging.SerilogLogger->  00000024C48AC808 Serilog.Core.Logger->  00000024C48AC760 Serilog.Core.Logger->  00000024C47AD468 Serilog.Core.Logger->  00000024C47ABF08 Serilog.Core.Sinks.SafeAggregateSink->  00000024C47ABF20 Serilog.Core.ILogEventSink[]->  00000024C479C548 Serilog.Sinks.Grafana.Loki.LokiSink->  00000024C479C778 Serilog.Sinks.Grafana.Loki.Infrastructure.BoundedQueue`1[[Serilog.Events.LogEvent, Serilog]]->  00000024C479C7B8 System.Collections.Generic.Queue`1[[Serilog.Events.LogEvent, Serilog]]->  00000026E8C1A800 Serilog.Events.LogEvent[]->  00000026148D3308 Serilog.Events.LogEvent->  00000026148D4EF0 Serilog.Events.MessageTemplate->  0000002923BC9638 System.StringFound 1 unique roots (run '!gcroot -all' to see all roots).0:000> !gcroot 000000292586f4c8
Thread 1878:00000024C39BE4B0 00007FFA4C0B3522 System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken) [/_/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs @ 2922]rbp+10: 00000024c39be520->  00000024C48AD6E0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[System.Threading.Tasks.VoidTaskResult, System.Private.CoreLib],[Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions+<RunAsync>d__4, Microsoft.Extensions.Hosting.Abstractions]]->  00000024C48AD200 Microsoft.Extensions.Hosting.Internal.Host->  00000024C48AC538 Microsoft.Extensions.Logging.Logger`1[[Microsoft.Extensions.Hosting.Internal.Host, Microsoft.Extensions.Hosting]]->  00000024C48AC658 Microsoft.Extensions.Logging.Logger->  00000024C48AC680 Microsoft.Extensions.Logging.LoggerInformation[]->  00000024C48AC6E0 Serilog.Extensions.Logging.SerilogLogger->  00000024C48AC808 Serilog.Core.Logger->  00000024C48AC760 Serilog.Core.Logger->  00000024C47AD468 Serilog.Core.Logger->  00000024C47ABF08 Serilog.Core.Sinks.SafeAggregateSink->  00000024C47ABF20 Serilog.Core.ILogEventSink[]->  00000024C479C548 Serilog.Sinks.Grafana.Loki.LokiSink->  00000024C479C778 Serilog.Sinks.Grafana.Loki.Infrastructure.BoundedQueue`1[[Serilog.Events.LogEvent, Serilog]]->  00000024C479C7B8 System.Collections.Generic.Queue`1[[Serilog.Events.LogEvent, Serilog]]->  00000026E8C1A800 Serilog.Events.LogEvent[]->  0000002614BB7AC8 Serilog.Events.LogEvent->  0000002616D3CC40 Serilog.Events.MessageTemplate->  000000292586F4C8 System.StringFound 1 unique roots (run '!gcroot -all' to see all roots).

从引用链看,这些 object 都是通过 Serilog 日志组件发送给 Grafana.Loki ,通过对引用链对象的追踪,我发现 System.Collections.Generic.Queue 有重大问题,截图如下:

808bd37e9e2761ab21f1a263be4a3d4a.png

对,这个 queue 居然有 395w 的积压,到底积压了什么东西,可以用 !wdo 看一下string内容。

2b6566543710f5ed9a722e7cf0a359db.png

看样子这是一个失败重试,分析到这里思路大概就清晰了,就是 Grafana.Loki 或者 Serilog 组件出了什么问题,导致日志发送不到 Loki 中或者发送速度过慢,然后不断的积压所致,接下来把分析到的这些信息和朋友做了一个沟通,截图如下:

5ad8b805e1236da7c4c2a6f11736b477.png

三:总结

本次内存碎片化的主要原因在于 Serilog 对接 Loki 的过程中产生的395w的queue积压所致,但我也只能分析到这里了,至于为什么有积压,这个还得朋友进一步调试分析,我相信这个问题很快就能得到解决💪💪💪

END

工作中的你,是否已遇到 ... 

1. CPU爆高

2. 内存暴涨

3. 资源泄漏

4. 崩溃死锁

5. 程序呆滞

等紧急事件,全公司都指望着你能解决...  危难时刻才能展现你的技术价值,作为专注于.NET高级调试的技术博主,欢迎微信搜索: 一线码农聊技术,免费协助你分析Dump文件,希望我能将你的踩坑经验分享给更多的人。

023ee6d43b5b88e0bef95708463a6cd6.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/297150.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php 合成图片 透明,2020-05-19 php实现透明png多图合成

图片合成的流程一般是&#xff0c;获取图像资源——合成——输出。png图片&#xff0c;一般就用imagecreatefrompng()获取资源。不过这个资源获取后是有白底的。所以需要用imagesavealpha()进行图像处理&#xff0c;得到包含有透明背景的图像。//原始图像$dst "img/1.png…

ArcEngine 没有Esri.ArcGis.GeoAnalyst 命名空间

http://bbs.esrichina-bj.cn/ESRI/viewthread.php?tid69977&extrapage%3D1&ordertype1 AE安装的时候分为Core和Extension. Esri.ArcGis.GeoAnalyst位于Extension里面. (1)确保安装的时候是完全安装 (2) 转载于:https://www.cnblogs.com/imihiroblog/archive/2012/04/1…

微信功能“拍一拍”,都有谁在“拍”你?

全世界只有3.14 % 的人关注了爆炸吧知识微信新功能总在悄咪咪更新&#xff0c;“拍一拍”一出&#xff0c;很多小伙伴都会收到各种群里面千奇百怪的“拍一拍”&#xff0c;到底都是谁在偷偷关注你&#xff1f;真正决定人与人之间的差距的&#xff0c;其实是我们对事物的见识与内…

sql 触发器_一键生成某个sql的html--记录执行计划、统计信息、触发器等

概述当你获得某个sql的sql_id时&#xff0c;怎么去一键获得这个sql的一些信息呢&#xff0c;例如列的情况、执行计划等等..脚本有点长&#xff0c;建议大家用电脑来看..下面用一个简单测试来演示下&#xff0c;附脚本领取方式。1、获取sql_idSQL> select a.* from (select S…

别等了,全面「远程办公」凉了

大家好&#xff0c;我是Z哥。这是一篇迟到的文章。具体原因是&#xff0c;昨天定时发送的时候没注意已经过了0点了&#xff0c;习惯性的选了明天11点45&#xff0c;然后才发现实际变成10月9日的11&#xff1a;45了。赶紧取消重新发一下。好了&#xff0c;回到正文。不知道你是否…

PHP做闹钟APP,8款超好用的闹钟APP,专治各种赖床

这是什么神仙APP&#xff0c;我再也不怕冬天起不了床&#xff01;有了它们&#xff0c;再也不怕懒床迟到了&#xff01;好用到爆&#xff01;可爱女生闹钟(超可爱的用户界面)这界面真是太可爱了&#xff0c;软萌妹子必备啊。推荐指数&#xff1a;★★★★怪物闹钟(玩游戏才能关…

easy html5 - Jquery mobile

今天看了下jquery mobile(http://jquerymobile.com/)&#xff0c;看了后自己很兴奋&#xff1b;jquery 在web js框架上的风暴还在继续却也随着移动终端走向了mobile&#xff1b;那么jquery mobile到底包括些什么呢 首先jquery mobile是基于html5的&#xff0c;因为html5已经被默…

太漂亮了!66个高颜值的矿物晶体,吸引到你的目光了吗

全世界只有3.14 % 的人关注了爆炸吧知识1“中国皇帝”菱锰矿“中国皇帝”产自广西梧州&#xff0c;最大晶体为22厘米&#xff0c;是目前中国发现的菱锰矿中体积最大、单晶最大、质量最好的一件标本&#xff0c;在世界范围内亦属罕见。2车轮矿晶簇世界罕见的车轮矿晶簇。3祖母绿…

oracle中sum和count可以嵌套吗_【分享吧】Oracle查询转换

前言“查询转换”是Oracle解析SQL语句中重要的步骤。其原理是Oracle在解析时通过对原有SQL的等价改写&#xff0c;以达到较高执行效率的方式。上图展示了SQL的执行过程&#xff0c;当客户提交的语句经过解析后&#xff0c;在提交给优化器之前会进行一个查询转换的步骤。在这个步…

如何正确地部署防火墙?

防火墙在实际的部署应用过程当中&#xff0c;经常部署在网关的位置&#xff0c;也就是经常部署在网内和网外的一个"中间分隔点"上&#xff0c;而就是在这样一个部署的环境中&#xff0c;也还存在着多种方式&#xff0c;且存在着许多"陷阱"&#xff0c;本文…

男人是大猪蹄子的证据找到了!

1 老师&#xff01;2 您倒也不必如此诚实3 哈哈哈哈哈哈这也太显眼了4 圆的面积其实可以这样算5 喵&#xff1a;进不去......好烦&#xff01;&#xff01;6 狗子&#xff1a;好好扔&#xff0c;砸我干嘛&#xff1f;你到底会不会玩&#xff1f;&#xff01;7 男人是大猪蹄子的…

set-cookie 和 cookie 的区别_Go Web 编程如何确保Cookie数据的安全传输

什么是CookieCookie(也叫Web Cookie或浏览器Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据&#xff0c;它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常&#xff0c;它用于告知服务端两个请求是否来自同一浏览器&#xff0c;如保持用户的登…

使用C#快速生成顺序GUID

前言通常&#xff0c;我们采用数值ID(long)/GUID作为全局唯一标识符。但是&#xff0c;在多线程、高并发情况下&#xff0c;由应用程序生成数值ID容易产生重复&#xff0c;而由数据库生成又会造成性能瓶颈。而使用Guid.NewGuid()生成的GUID虽然不会重复&#xff0c;但是它是无序…

带你见识世界的5部纪录片(免费领取)

全世界只有3.14 % 的人关注了爆炸吧知识纪录片一直都是增长见识又带给你力量的东西&#xff0c;你可能忙于学业、生活、工作而不能行万里路&#xff0c;但至少你还可以看纪录片&#xff0c;从一方屏幕看到整个世界。今天就为大家整理了5部高分纪录片&#xff0c;文末附领取方式…

Android简明开发教程二十一:访问Internet 绘制在线地图

在例子Android简明开发教程十七&#xff1a;Dialog 显示图像 中我们留了一个例子DrawMap()没有实现&#xff0c;这个例子显示在线地图&#xff0c;目前大部分地图服务器都是将地图以图片存储以提高响应速度。 一般大小为256X256个像素。具体可以参见离线地图下载方法解析 。 比…

url采集工具_大数据关键技术浅谈之大数据采集

在前几篇文章中&#xff0c;企通查为大家介绍了大数据处理的基本流程。从大数据的一系列处理过程中&#xff08;抽取、集成、分析、解释&#xff09;&#xff0c;我们可以发现这一整套流程中涵盖了数据存储、处理、应用等多方面的技术。大数据价值的完美体现需要多种技术的协同…

使用 WPF + Chrome 内核实现 在线客服系统 的复合客服端程序

本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程。本产品已经成熟稳定并投入商用。免费使用 & 私有化部署免费下载&#xff1a;https://docs.shengxunwei.com/Post/f7bc8496-14ee-4a53-07b4-08d8e3da6269视频实拍&#xff1a;演示升讯威在线…

abp框架java,【Net】ABP框架学习之正面硬钢

前言本文介绍另一种学习ABP框架的方法&#xff0c;该方法为正面硬钢学习法。。。我们不去官网下载模板&#xff0c;直接引用DLL&#xff0c;直接使用。WebApi项目创建首先创建一个WebApi项目&#xff0c;结构如下。然后Nuget搜索ABP&#xff0c;安装ABP框架。(我这里安装的是5.…

不同对象的通话是时长​

1 一个专门为某人打造的形容词2 当代人的手机铃声3 “可以吃宵夜吗”“不行” 4 好可爱&#xff01;&#xff01;&#xff01;5 这不是道具&#xff0c;是真的红酒杯里倒着红酒叠在硬币上&#xff01;6 这14个未接电话就很有灵性了&#xff01;7 你觉得以下哪个事件给你的痛苦感…

poj 1088 滑雪 详解

http://poj.org/problem?id1088 这是一道dp入门题&#xff0c;不过我一直没想明白应该怎么dp。今天&#xff0c;在做自己学校oj的算法基础题时看到这题&#xff0c;标注着dp的分类&#xff0c;加上我一直都比较喜欢做dp题&#xff0c;于是我就决心今晚要把这道入门题切了。 题…