主頁 > .NET開發 > 記一次 .NET 某公交卡扣費系統 程式卡死分析

記一次 .NET 某公交卡扣費系統 程式卡死分析

2021-11-16 06:09:39 .NET開發

一:背景

1. 講故事

上個月底,有位朋友微信找到我,說他的程式 多執行緒處理 RabbitMQ 時過慢,幫忙分析下什么原因,截圖如下:

這問題拋出來,有點懵逼,沒說CPU爆高,也沒說記憶體泄漏,也沒說程式卡死,,,鬼知道為啥 Rabbitmq 處理過慢哈?????? ,

既然沒有一個緣由,那就往 freeze 這個方向去找吧,上 windbg 說話,

二:Windbg 分析

1. 尋找 freeze 原因

處理過慢原因有很多,可能是干活的人少了,也可能這些人摸魚去了,總之作業不飽和,接下來看看這幫人有沒有摸魚,從 執行緒池 看起,


0:000> !tp
CPU utilization: 81%
Worker Thread: Total: 187 Running: 172 Idle: 0 MaxLimit: 32767 MinLimit: 8
Work Request in Queue: 0
--------------------------------------
Number of Timers: 0
--------------------------------------
Completion Port Thread:Total: 1 Free: 1 MaxFree: 16 CurrentLimit: 1 MaxLimit: 1000 MinLimit: 8

從輸出中看,當前的 CPU=81%, 大概率是這個程式引起的,既然 CPU 過高,可能是某些計算密集型操作,可能是大量鎖導致的背景關系切換,也可能是 GC 頻繁觸發所致,

2. 是 GC 觸發嗎?

本系列到這里,我相信有很多朋友應該知道如何從執行緒堆疊上看是否為 GC 觸發所致,用命令 ~*e !dumpstack 經過一通尋找,發現是 214 號執行緒觸發了 GC,如下圖所示:

!dumpstack 輸出的資訊太多,為了讓資訊更加簡化,改用 !clrstack


0:214> !clrstack 
OS Thread Id: 0x290c (214)
        Child SP               IP Call Site
000000bb2983c7d0 00007ffed8c3e335 System.Text.UTF8Encoding.GetString(Byte[], Int32, Int32)
000000bb2983c810 00007ffe7aaecee9 StackExchange.Redis.RedisValue.op_Implicit(StackExchange.Redis.RedisValue)
000000bb2983c860 00007ffe7aaecd92 xxxx.Util.Helper.RedisHelper.ConvertObj[[System.__Canon, mscorlib]](StackExchange.Redis.RedisValue)
000000bb2983c8f0 00007ffe7abc3997 xxxx.Util.Helper.RedisHelper+c__DisplayClass29_0`1[[System.__Canon, mscorlib]].b__0(StackExchange.Redis.IDatabase)
000000bb2983ca20 00007ffe7aaeaca0 xxxx.Util.Helper.RedisHelper.Do[[System.__Canon, mscorlib]](System.Func`2<StackExchange.Redis.IDatabase,System.__Canon>)
000000bb2983caa0 00007ffe7abc3762 xxxx.Util.Helper.RedisHelper.HashGet[[System.__Canon, mscorlib]](System.String, System.String)
000000bb2983cb40 00007ffe7abc2f3d xxxx.Implementation.xxx.GetCompany(System.String)
...
000000bb2983e170 00007ffe7ad2fadf xxx.xxx.MQ.xxx+c__DisplayClass21_0`1[[System.__Canon, mscorlib]].b__1()
000000bb2983e1c0 00007ffed8c11862 System.Threading.Tasks.Task`1[[System.__Canon, mscorlib]].InnerInvoke()
000000bb2983e220 00007ffed8c10937 System.Threading.Tasks.Task.Execute()
000000bb2983e260 00007ffed8bc674e System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
000000bb2983e330 00007ffed8bc65e7 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
000000bb2983e360 00007ffed8c10bdd System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef)
000000bb2983e410 00007ffed8c10303 System.Threading.Tasks.Task.ExecuteEntry(Boolean)
000000bb2983e450 00007ffed8bcfa10 System.Threading.ThreadPoolWorkQueue.Dispatch()
000000bb2983e8e8 00007ffed9d465d3 [DebuggerU2MCatchHandlerFrame: 000000bb2983e8e8] 

從卦中資訊看,程式在 RedisHelper.HashGet 操作的程序中觸發了 GC,我去,難道是從 redis 中讀了什么大資料?接下來用 !clrstack -a 看看到底從redis中讀了個啥?


0:214> !clrstack -a
OS Thread Id: 0x290c (214)
        Child SP               IP Call Site
000000bb2983c860 00007ffe7aaecd92 xxx.Util.Helper.RedisHelper.ConvertObj[[System.__Canon, mscorlib]](StackExchange.Redis.RedisValue)
    PARAMETERS:
        this (0x000000bb2983c8f0) = 0x000000bb182da3d0
        value (0x000000bb2983c960) = 0x000000bb18440778
    LOCALS:
        0x000000bb2983c8c4 = 0x0000000000000000
        0x000000bb2983c8a0 = 0x0000000000000000
        0x000000bb2983c898 = 0x0000000000000000

0:214> !do 0x000000bb18440778
Name:        System.Byte[]
MethodTable: 00007ffed8db93d0
EEClass:     00007ffed87f4dc8
Size:        6679(0x1a17) bytes
Array:       Rank 1, Number of elements 6655, Type Byte (Print Array)
Content:     {"ID":104x,"Code":"130x","xxx":"1304","xxx":"8888","Name":"...............","xxx":"...............","MqConnStr"

可以看到,redis 讀了大概 6.6 k 的資料,才這么點資料,我還以為 幾十M 呢 ??????, 要說這點東西就能觸發GC,我是不相信的 ,

3. 到底是什么誘使了 GC 觸發 ?

那這個 罪魁禍首 到底是誰呢? 其實仔細想一想,GC觸發無非就是將物件從 gen0 推到 gen1,然后由 gen1 推到 gen2,那朋友的這個 RabbitMQ 處理慢,肯定是觸發了多次GC,才有了這個肉眼可見的處理慢,

這里就有一個突破點,既然觸發多次GC,那gen2上肯定有很多帶根的物件,所以從這里入手比較好,用 !dumpgen 命令查看,


0:214> !dumpgen 2 -stat
       Count      Total Size      Type
-------------------------------------------------
      87,738     24,925,316   System.Int32[]
     509,643     56,399,716   System.String
      83,077     65,760,888   System.Reflection.Emit.__FixupData[]
   2,158,346     69,067,072   System.Reflection.Emit.GenericMethodInfo
      92,388    172,765,392   System.Object[]
     796,870    179,587,796   **** FREE ****
  14,030,441    336,730,584   System.RuntimeMethodHandle
     428,376    348,743,274   System.Byte[]

我去,gen2 上居然有 1.4 kw 的物件,這太讓人好奇了,接下來隨便抽幾個 address ,看看它的參考根是個啥?


0:214> !dumpgen 2 -type System.RuntimeMethodHandle
Object             MT                    Size   Name
-------------------------------------------------------------------
000000bac9f8fe68   00007FFED8DB9978        24   System.RuntimeMethodHandle
000000bac9f8fe80   00007FFED8DB9978        24   System.RuntimeMethodHandle
000000bac9f8fe98   00007FFED8DB9978        24   System.RuntimeMethodHandle
000000bac9f8feb0   00007FFED8DB9978        24   System.RuntimeMethodHandle
000000bac9f8fec8   00007FFED8DB9978        24   System.RuntimeMethodHandle
...
000000baca1af510   00007FFED8DB9978        24   System.RuntimeMethodHandle
000000baca1af548   00007FFED8DB9978        24   System.RuntimeMethodHandle
000000baca1af560   00007FFED8DB9978        24   System.RuntimeMethodHandle
000000baca1afd90   00007FFED8DB9978        24   System.RuntimeMethodHandle
000000baca1afde0   00007FFED8DB9978        24   System.RuntimeMethodHandle

0:214> !gcroot 000000baca1afde0
Thread 187c0:
    000000baeeb5cb30 00007ffed8ba9c60 System.Collections.Generic.Dictionary`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].FindEntry(System.__Canon)
        rsi: 
            ->  000000baca4c6ef0 System.Collections.Generic.Dictionary`2[[System.Tuple`4[[System.String, mscorlib],[System.String, mscorlib],[System.Int32, mscorlib],[System.Int32, mscorlib]], mscorlib],[System.Delegate, mscorlib]]
            ->  000000badab3b8a0 System.Collections.Generic.Dictionary`2+Entry[[System.Tuple`4[[System.String, mscorlib],[System.String, mscorlib],[System.Int32, mscorlib],[System.Int32, mscorlib]], mscorlib],[System.Delegate, mscorlib]][]
            ->  000000baca1b5210 System.Func`2[[System.Data.IDataReader, System.Data],[xxx.BAR_AccountDC, xxxx]]
            ->  000000baca1ae8b0 System.Reflection.Emit.DynamicMethod+RTDynamicMethod
            ->  000000baca1ae7f8 System.Reflection.Emit.DynamicMethod
            ->  000000baca1b51b0 System.RuntimeMethodInfoStub
            ->  000000baca1b4a18 System.Reflection.Emit.DynamicResolver
            ->  000000baca1aea60 System.Reflection.Emit.DynamicScope
            ->  000000baca1aea78 System.Collections.Generic.List`1[[System.Object, mscorlib]]
            ->  000000baca1b3b20 System.Object[]
            ->  000000baca1afde0 System.RuntimeMethodHandle

從參考鏈看,它是被 Dictionary 所持有,那我們就 dump 一下這個 dictionary,看看是個啥,


0:214> !do 000000baca4c6ef0
Name:        System.Collections.Generic.Dictionary`2[[System.Tuple`4[[System.String, mscorlib],[System.String, mscorlib],[System.Int32, mscorlib],[System.Int32, mscorlib]], mscorlib],[System.Delegate, mscorlib]]
MethodTable: 00007ffe7a937f18
EEClass:     00007ffed87f7cb8
Size:        80(0x50) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
00007ffed8dc3e30  400182a        8       System.Int32[]  0 instance 000000badaaa2c10 buckets
00007ffed9874d38  400182b       10 ...non, mscorlib]][]  0 instance 000000badab3b8a0 entries
00007ffed8dc3e98  400182c       38         System.Int32  1 instance            83000 count
00007ffed8dc3e98  400182d       3c         System.Int32  1 instance            83000 version
00007ffed8dc3e98  400182e       40         System.Int32  1 instance               -1 freeList
00007ffed8dc3e98  400182f       44         System.Int32  1 instance                0 freeCount
00007ffed8d9a430  4001830       18 ...Canon, mscorlib]]  0 instance 000000baca2ec958 comparer
00007ffed8d9c550  4001831       20 ...Canon, mscorlib]]  0 instance 0000000000000000 keys
00007ffed8dcef28  4001832       28 ...Canon, mscorlib]]  0 instance 0000000000000000 values
00007ffed8dc1c98  4001833       30        System.Object  0 instance 0000000000000000 _syncRoot

0:214> !objsize 000000baca4c6ef0
sizeof(000000baca4c6ef0) = 1116325152 (0x4289c520) bytes (System.Collections.Generic.Dictionary`2[[System.Tuple`4[[System.String, mscorlib],[System.String, mscorlib],[System.Int32, mscorlib],[System.Int32, mscorlib]], mscorlib],[System.Delegate, mscorlib]])


可以看到,當前dict 的 size= 8.3w,總大小為 1.1G, 然后用 !mdt 抽查一下字典內容,

可以看出,字典中的item大概都是 key= select * from xxx where AccountNo= xxxxvalue = https://www.cnblogs.com/huangxincheng/p/Func

4. 查看原始碼

!gcroot 中知道當前根在 187c0 號執行緒,然后我們通過執行緒堆疊去尋找下原始碼,


0:089> ~~[187c0]s
ntdll!NtWaitForSingleObject+0xa:
00007ffe`e9ea06fa c3              ret
0:089> !clrstack 
OS Thread Id: 0x187c0 (89)
        Child SP               IP Call Site
000000baeeb5caa0 00007ffed9718dfe System.Tuple`4[[System.__Canon, mscorlib],[System.__Canon, mscorlib],[System.Int32, mscorlib],[System.Int32, mscorlib]].System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer)
000000baeeb5cb00 00007ffed8ba90a7 System.Collections.Generic.ObjectEqualityComparer`1[[System.__Canon, mscorlib]].GetHashCode(System.__Canon)
000000baeeb5cb30 00007ffed8ba9c60 System.Collections.Generic.Dictionary`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].FindEntry(System.__Canon)
000000baeeb5cba0 00007ffed8bc53a4 System.Collections.Generic.Dictionary`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].TryGetValue(System.__Canon, System.__Canon ByRef)
000000baeeb5cbe0 00007ffe7abd8069 xxx.Internal.Cache`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].Get(System.__Canon, System.Func`1<System.__Canon>)
000000baeeb5cc50 00007ffe7abd6d52 xxx.Database+d__49`1[[System.__Canon, mscorlib]].MoveNext()
000000baeeb5ccd0 00007ffed733768e System.Linq.Enumerable.FirstOrDefault[[System.__Canon, mscorlib]](System.Collections.Generic.IEnumerable`1<System.__Canon>)
000000baeeb5cd40 00007ffe7af5489e xxx.xxx.ParsePapPayDebitRecord(xxx, xxx.BAR_AccountDC ByRef, System.String ByRef, xxx ByRef, Boolean, xxx, Boolean)
...

從執行緒堆疊看,程式做了一個 db 查詢的操作,原始碼大概如下:


public static InvalidTxnCode ParsePapPayDebitRecord(xxx)
{
    sql = "select * FROM  [dbo].[xxx]  where AccountNO = '" + transRecord.AccountNO + "'";
	IEnumerable<BAR_AccountDC> enumerable3 = new YiBll<BAR_AccountDC>(transRecord.AccountNO).QuerySql(sql);
}

問題就出現在這個 sql 拼接上,底層的框架為了提高 mapping 速度,將 sql 和與之對應的 Func<DataReader,Data> 做了快取處理,由于每次sql都不一樣,這就導致底層的 dict越來越大,直到目前的 1.1 G,

三:總結

總的來說,本次事故是由于不斷增長的 dict 在不斷的擠壓小物件堆,加之程式多執行緒火力全開分配物件導致gc在小物件堆上的頻繁回收造成的 rabbitmq 處理過慢,

修改辦法就是將 sql 引數化,


 sql = "select * FROM  [dbo].[xxx]  where AccountNO = '" + transRecord.AccountNO + "'";

改成


 sql = "select * FROM  [dbo].[xxx]  where AccountNO = @AccountNO";

最后提一下,這個dump有一定的迷惑性,因為觸發GC的執行緒并不是罪魁禍首,它只不過是壓死駱駝的那最后一根稻草罷了,

圖片名稱

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/357278.html

標籤:C#

上一篇:Linxu+Docker+Gitee+Jenkins自動化部署.NET Core服務

下一篇:C# 獲取PDF中的數字簽名證書

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more