主頁 > .NET開發 > 6. 堪比JMeter的.Net壓測工具 - Crank 實戰篇 - 收集診斷跟蹤資訊與如何分析瓶頸

6. 堪比JMeter的.Net壓測工具 - Crank 實戰篇 - 收集診斷跟蹤資訊與如何分析瓶頸

2022-04-21 06:06:27 .NET開發

1. 前言

上面我們已經做到了介面以及場景壓測,通過控制臺輸出結果,我們只需要將結果收集整理下來,最后匯總到excel上,此次壓測報告就可以完成了,但收集報告也挺麻煩的,交給誰呢……

找了一圈、沒找到愿意接手的人,該怎么辦呢……思考了會兒還是決定看看能否通程序式解決我們的難題吧,畢竟整理表格太累╯﹏╰

2. 收集結果

通過查閱官方檔案,我們發現官方提供了把資料保存成Json、csv、以及資料庫三種方式,甚至還有小伙伴積極的對接要把資料保存到Es中,那選個最簡單的吧!

要不選擇Json吧,不需要依賴外部存盤,很簡單,我覺得應該可試,試一下看看:輸入命令:

crank --config load.benchmarks.yml --scenario api --load.framework net5.0 --application.framework net5.0 --json 1.json --profile local --profile crankAgent1 --description "wrk2-獲取用戶詳情" --profile defaultParamLocal

最后得到結果:

{
  "returnCode": 0,
  "jobResults": {
    "jobs": {
      "load": {
        "results": {
          "http/firstrequest": 85.0,
          "wrk2/latency/mean": 1.81,
          "wrk2/latency/max": 1.81,
          "wrk2/requests": 2.0,
          "wrk2/errors/badresponses": 0.0,
          "wrk2/errors/socketerrors": 0.0,
          "wrk2/latency/50": 1.81,
          "wrk2/latency/distribution": [
            [
              {
                "latency_us": 1.812,
                "count": 1.0,
                "percentile": 0.0
              },
              {
                "latency_us": 1.812,
                "count": 1.0,
                "percentile": 1.0
              }
            ]
          ]
        }
      }
    }
  }
}

完整的匯出結果

好吧,資料有點少,好像資料不太夠吧,這些資訊怎么處理能做成報表呢,再說了資料不對吧,QPS、延遲呢?好吧,被看出來了,因為資訊太多,我刪了一點點(也就1000多行指標資訊吧),看來這個不行,用json的話還得配合個程式好難……

csv不用再試了,如果也是單個文本的話,也是這樣,還得配個程式,都不能單干,干啥都得搭伴,那試試資料庫如何

crank --config load.benchmarks.yml --scenario api --load.framework net5.0 --application.framework net5.0 --sql "Server=localhost;DataBase=crank;uid=sa;pwd=P@ssw0rd;" --table "local" --profile local --profile crankAgent1 --description "wrk2-獲取用戶詳情" --profile defaultParamLocal

我們根據壓測環境,把不同的壓測指標存盤到不同的資料庫的表中,當前是本地環境,即 table = local

最后我們把資料保存到了資料庫中,那這樣做回頭需要報告的時候,我查詢下資料庫搞出來就好了,終于松了一口氣,但好景不長,發現資料庫存盤也有個坑,之前json中看到的結果竟然在一個欄位中存盤,不過幸好SqlServer 2016之后支持了json,可以通過json決議搞定,但其中引數名有/等特殊字符,sql server處理不了,難道又得寫個網站才能展示這些資料了嗎??真的繞不開搭伴干活這個坑嗎?

微軟不會就做出個這么雞肋的東西,還必須要配個前端才能清楚的搞出來指標吧……還得用vue、好吧,我知道雖然現在有blazer,可以用C#開發,但還是希望不那么麻煩,又仔細查找了一番,發現Crank可以對結果做二次處理,可以通過script,不錯的東西,既然sql server資料庫無法支持特殊字符,那我加些新引數取消特殊字符不就好了,新建scripts.profiles.yml

scripts: 
  changeTarget: |
    benchmarks.jobs.load.results["cpu"] = benchmarks.jobs.load.results["benchmarks/cpu"]
    benchmarks.jobs.load.results["cpuRaw"] = benchmarks.jobs.load.results["benchmarks/cpu/raw"]
    benchmarks.jobs.load.results["workingSet"] = benchmarks.jobs.load.results["benchmarks/working-set"]
    benchmarks.jobs.load.results["privateMemory"] = benchmarks.jobs.load.results["benchmarks/private-memory"]
    benchmarks.jobs.load.results["totalRequests"] = benchmarks.jobs.load.results["bombardier/requests;http/requests"]
    benchmarks.jobs.load.results["badResponses"] = benchmarks.jobs.load.results["bombardier/badresponses;http/requests/badresponses"]
    benchmarks.jobs.load.results["requestSec"] = benchmarks.jobs.load.results["bombardier/rps/mean;http/rps/mean"]
    benchmarks.jobs.load.results["requestSecMax"] = benchmarks.jobs.load.results["bombardier/rps/max;http/rps/max"]
    benchmarks.jobs.load.results["latencyMean"] = benchmarks.jobs.load.results["bombardier/latency/mean;http/latency/mean"]
    benchmarks.jobs.load.results["latencyMax"] = benchmarks.jobs.load.results["bombardier/latency/max;http/latency/max"]
    benchmarks.jobs.load.results["bombardierRaw"] = benchmarks.jobs.load.results["bombardier/raw"]

以上處理的資料是基于bombardier的,同理大家可以完成對wrk或者其他的資料處理

通過以上操作,我們成功的把特殊字符的引數改成了沒有特殊字符的引數,那接下來執行查詢sql就可以了,

SELECT Description as '場景',
  JSON_VALUE (Document,'$.jobs.load.results.cpu') AS 'CPU使用率(%)',
  JSON_VALUE (Document,'$.jobs.load.results.cpuRaw') AS '多核CPU使用率(%)',
  JSON_VALUE (Document,'$.jobs.load.results.workingSet') AS '記憶體使用(MB)',
  JSON_VALUE (Document,'$.jobs.load.results.privateMemory') AS '行程使用的私有記憶體量(MB)',
  ROUND(JSON_VALUE (Document,'$.jobs.load.results.totalRequests'),0) AS '總發送請求數',
  ROUND(JSON_VALUE (Document,'$.jobs.load.results.badResponses'),0) AS '例外請求數',
  ROUND(JSON_VALUE (Document,'$.jobs.load.results.requestSec'),0) AS '每秒支持請求數',
  ROUND(JSON_VALUE (Document,'$.jobs.load.results.requestSecMax'),0) AS '每秒最大支持請求數',
  ROUND(JSON_VALUE (Document,'$.jobs.load.results.latencyMean'),0) AS '平均延遲時間(us)',
  ROUND(JSON_VALUE (Document,'$.jobs.load.results.latencyMax'),0) AS '最大延遲時間(us)',
  CONVERT(varchar(100),DATEADD(HOUR, 8, DateTimeUtc),20)  as '時間'
FROM dev;

3. 如何分析瓶頸

通過上面的操作,我們已經可以輕松的完成對場景的壓測,并能快速生成相對應的報表資訊,那正題來了,可以模擬高并發場景,那如何分析瓶頸呢?畢竟報告只是為了知曉當前的系統指標,而我們更希望的是知道當前系統的瓶頸是多少,怎么打破瓶頸,完成突破呢……

首先我們要先了解我們當前的應用的架構,比如我們現在使用的是微服務架構,那么

  • 應用拆分為幾個服務?了解清楚每個服務的作用
  • 服務之間的呼叫關系
  • 各服務依賴的基礎服務有哪些、基礎服務基本的資訊情況

舉例我們當前的微服務架構如下:

架構

通過架構圖可以快速了解到專案結構,我們可以看到用戶訪問web端,web端根據請求對應去查詢redis或者通過http、grpc呼叫服務獲取資料、各服務又通過redis、db獲取資料,

首先我們先通過crank把當前的資料指標保存入庫,調出其中不太理想的介面開始分析,

在這里我們拿兩個壓測介面舉例:

  • 獲取首頁Banner、QPS:3800 /s (Get)
  • 下單、QPS:8 /s (Post)

3.1. 獲取首頁Banner

通過單測首頁banner的介面,QPS是3800多不到4000這樣,雖然這個指標還不錯,但我們仍然覺得很慢,畢竟首頁banner就是很簡單幾個圖片+標題組合的資料,資料量不大,并且是直連Redis,僅在Redis不存在時才查詢對應服務獲取banner資料,這樣的QPS實在不應該,并且這個還是僅壓測單獨的banner,如果首頁同時壓測十幾個介面,那其性能會暴降十倍不止,這樣肯定是不行的

我們又壓測了一次首頁banner介面,發現有幾個疑點:

  • redis請求數徘徊在3800左右的樣子,網路帶寬占用1M的樣子,無法繼續上漲
  • 查看web服務,發現時不時的會有呼叫服務超時出錯的問題,Db的訪問量有上漲,但不明顯,很快就下去了

思考: Redis的請求數與最后的壓測結果差不多,最后倒也對上了,但為什么redis的請求數這么低呢?難道是帶寬限制!!

結構

雖然是單機redis,但4000也絕對不可能是它的瓶頸,懷疑是帶寬被限制了,應該就是帶寬被限制了,后來跟運維一番切磋后,得到結論是redis沒限制帶寬……

那為什么不行呢,這么奇怪,redis不可能就這么點并發就不行了,算了還是寫個程式試一下吧,看看是不是真的測驗環境不給力,redis配置太差了,一番操作后發現,同一個redis資料,redis讀可以到6萬8,不到7萬、帶寬占用10M,redis終于洗清了它的嫌疑,此介面的QPS不行與Redis無關,但這么簡單的一個結構為什么QPS就上不去呢……,如果不是redis的問題,那會不會是因為請求就沒到redis上,是因為壓測機的強度不夠,導致請求沒到redis……當時冒出來這個有點愚蠢的想法,那就增加壓測機的數量,通過更改負載壓測機配置,1臺壓測機升到了3臺,但可惜的是單臺壓測機的指標不升反降,最后所有壓測機的指標加到一起正好與之前一臺壓測機的壓測結果差不多一樣,那說明QPS低與壓測機無關,后來想到試試通過增加多副本來提升QPS,后來web副本由1臺提升到了3臺,之前提到的服務呼叫報錯的情況更加嚴重,之前只是偶爾有一個錯誤,但提升web副本后,看到一大片的錯誤

  • 提示Thread is busy,很多執行緒開始等待
  • 大量的服務呼叫超時,DB查詢緩慢

最后QPS 1000多一點,有幾千個失敗的錯誤,這盲目的提升副本貌似不大有效,之前盡管Qps不高,但起碼也在4000,DB也沒事,這波神操作后QPS直降4分之3,DB還差點崩了,思想滑坡了,做了負優化……

繼續思考,為何提升副本,QPS不升反降,為何出現大量的呼叫超時、為何DB會差點被干崩,我只是查詢個redis,跟DB有毛關系啊!奇了怪了,看看代碼怎么寫的吧……燒腦

public async Task<List<BannerResponse>> GetListAsync()
{
  List<BannerResponse> result = new List<BannerResponse>();
  try
  {
    var cacheKey = "banner_all";
    var cacheResult = await _redisClient.GetAsync<List<BannerResponse>>(cacheKey);
    if (cacheResult == null)
    {
      result = this.GetListServiceAsync().Result;
      _redisClient.SetAsync(cacheKey, result, new()
      {
        DistributedCacheEntryOptions = new()
        {
          AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(5)
        }
      }).Wait();
    }
    else
    {
      result = cacheResult;
    }
	}
  catch (Exception e)
  {
    result = await this.GetListServiceAsync();
  }

  return result;
}

看了代碼后發現,僅當Reids查詢不到的時候,會呼叫對應服務查詢資料,對應服務再查詢DB獲取資料,另外查詢例外時,會再次呼叫服務查詢結果,確保回傳結果一定是正確的,看似沒問題,但為何壓測會出現上面那些奇怪現象呢……

請求超時、大量等待,那就是正好redis不存在,穿透到對應的服務查詢DB了,然后壓測同一時刻資料量過大,同一時刻查詢到的Reids都是沒有資料,最后導致呼叫服務的數量急劇上升,導致回應緩慢,超時加劇,執行緒因超時釋放不及時,又導致可用執行緒較少,

這塊我們查找到對應的日志顯示以下資訊

System.TimeoutException: Timeout performing GET MyKey, inst: 2, mgr: Inactive, queue: 6, qu: 0, qs: 6, qc: 0, wr: 0, wq: 0, in: 0, ar: 0,
IOCP: (Busy=6,Free=994,Min=8,Max=1000), 
WORKER: (Busy=152,Free=816,Min=8,Max=32767)
  • 那么我們可以調整Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
  ThreadPool.GetMinThreads(out int workerThreads, out int completionPortThreads);
  ThreadPool.SetMinThreads(1000, completionPortThreads);//根據情況調整最小作業執行緒,避免因創建執行緒導致的耗時操作

  ……………………………………………………………此處省略…………………………………………………………………………………………………………
}

web服務呼叫底層服務太慢,那么提升底層服務的回應速度(優化代碼)或者提高處理能力(提升副本)

  • 防止高并發情況下全部穿透到下層,增加底層服務的壓力

前兩點也是一個好的辦法,但不是最好的解決辦法,最好還是不要穿透到底層服務,如果reids不存在,就放一個請求過去是最好的,拿到資料就持久化到redis,不要總穿透到下層服務,那么怎么做呢,最簡單的辦法就是使用加鎖,但加鎖會影響性能,但這個我們能接受,后來調整加鎖測驗,穿透到底層服務的情況沒有了,但很可惜,請求數確實會隨著副本的增加而增加,但是實在是有點不好看,后來又測驗了下另外一個獲取快取資料的結果,結果QPS:1000多一點,比banner還要低的多,兩邊明明都使用的是Reids,性能為何還有這么大的差別,為何我們寫的redis的demo就能到6萬多的QPS,兩邊都是拿的一個快取,差距有這么大?難道是封裝redis的sdk有問題?后來仔細對比了后來寫的redis的demo與banner呼叫redis的介面發現,一個是直接查詢的redis的字串,一個是封裝redis的sdk,多了一個反序列化的程序,最后經過測驗,反序列化之后性能降低了十幾倍,好吧看來只能提升副本了……但為何另外的介面也是從redis獲取,性能跟banner的介面不一樣呢!!

經過仔細對比發現,差別是資訊量,QPS更低的介面的資料量更大,那結果就有了,隨著資料量的增加,QPS會進一步降低,那這樣一來的話,增加副本的作用不大啊,誰知道會不會有一個介面的資料量很大,那性能豈不是差的要死,那還怎么玩,能不能提升反序列化的性能或者不反序列化呢,經過認真思考,想到了二級快取,如果用到了二級快取,記憶體中有就不需要查詢redis,也不需要再反序列化,那么性能應該有所提升,最后的結構如下圖:

結構

最后經過壓測發現,單副本QPS接近50000,比最開始提升12倍,并且也不會出現服務呼叫超時,DB崩潰等問題、且記憶體使用平穩

此次壓測發現其banner這類場景的性能瓶頸在反序列化,而非Redis、DB,如果按照一開始不清楚其作業原理、盲目的調整副本數,可能最后會加劇系統的雪崩,而如果我們把DB資源、Redis資源盲目上調、并不會對最后的結果有太大幫助,最多也只是延緩崩潰的時間而已

3.2. 下單

下單的QPS是8,這樣的QPS已經無法忍受了,每秒只有十個請求可以下單成功,如果中間再出現一個庫存不足、賬戶余額不足、活動資格不夠等等,實際能下單的人用一個手可以數過來,真的就這么慘……雖然下單確實很費性能,不過確實不至于這么低吧,先看下下單流程吧

下單

簡化后的下單流程就這么簡單,web通過dapr的actor服務呼叫order service,然后就是漫長的查詢db、操作redis操作,因涉及業務代碼、具體代碼就不再放出,但可以簡單說一下其中做的事情,檢查賬戶余額、反復的增加redis庫存確保庫存安全、檢查是否滿足活動、為推薦人計算待結算傭金等等一系列操作,整個看下來把人看懵了,常常是剛看了上面的,看下面代碼的時候忘記上面具體干了什么事,代碼太多了,一個方法數千行,其中再呼叫一些數百行的代碼,真的吐血了,不免感嘆我司的開發小哥哥是真的強大,這么復雜的業務居然能這么"順暢"的跑起來,后面還有N個需求等待加到下單上,果然不是一般人

不過話說回來,雖然是業務是真的多,也真的亂,不過這樣搞也不至于QPS才只有8這么可憐吧,服務器的處理能力可不是二十幾年前的電腦可以比擬的,單副本8核16G的配置不支持這么拉胯吧,再看一下究竟誰才是真正的幕后黑手……

但究竟哪里性能瓶頸在哪里,這塊就要出殺手锏了

Tracing

通過Tracing可以很清楚的看到各節點的耗時情況,這將對我們分析瓶頸提供了非常大的幫助、我們看到了雖然有幾十次的查詢DB操作,但DB還挺給力,基本也再很短時間內就給出了回應,那剩余時間耗費到了哪里呢?我們看到整體耗時11s、但查詢Db加起來也僅僅不到1s,那么剩余操作都在哪里?要知道哪怕我們優化DB查詢性能,減少DB查詢,那提升的性能對現在的結果也是微乎其微

結合Tracing以及下單流程圖,我們發現從Web到Order Service是通過actor來實作的,那會不是這里耗時影響的呢?

但dapr是個新知識、開發的小哥哥速度真快,這么快就用上dapr了(ˇ?ˇ)不知道小哥哥的頭發還有多少……

快速去找到下單使用actor的地方,如下:

[HttpPost]
[Authorize]
public async Task<CreateOrderResponse> CreeateOrder([FromBody] CreateOrderModel request)
{
    string actionType = "SalesOrderActor";
    var salesOrderActor = ActorProxy.Create<ISalesOrderActor>(new ActorId(request.SkuList.OrderBy(sku => sku.Sku).FirstOrDefault().Sku), actionType);
    request.AccountId = Account.Id;
    var result = await salesOrderActor.CreateOrderAsync(request);
    return new Mapping<ParentSalesOrderListViewModel, CreateOrderResponse>().Map(result);
}

我們看到了這邊代碼十分簡單,獲取商品資訊的第一個sku編號作為actor的actorid使用,然后得到下單的actor,之后呼叫actor中的創建訂單方法最后得到下單結果,這邊的代碼太簡單了,讓人心情愉快,那這塊會不會有可能影響下單速度呢?它是不是那個性能瓶頸最大的幕后黑手?

首先這塊我們就需要了解下什么是Dapr、Actor又是什么,不了解這些知識我們只能靠抓鬮來猜這塊是不是瓶頸了……

Dapr 全稱是Distributed Application Runtime,分布式應用運行時,并于今年加入了 CNCF 的范訓專案,目前Github的star高達16k,相關的學習檔案在檔案底部可以找到,我也是看著下面的檔案了解dapr

通過了解actor,我們發現用sku作為actorid是極不明智的選擇,像秒殺這類商品不就是搶的指定規格的商品嗎?如果這樣一來,這不是在壓測actor嗎?這塊我們跟對應的開發小哥哥溝通了下,通過調整actorid順利將Qps提升到了60作用,后面又通過優化減少db查詢、調整業務規則的順序等操作順利將QPS提升到了不到一倍,雖然還是很低,不過接下來的優化作業就需要再深層次的調整業務代碼了……

4. 總結

通過實戰我們總結出分析瓶頸從以下幾步走:

  1. 通過第一輪的壓測獲取性能差的介面以及指標
  2. 通過與開發溝通或者自己查看原始碼的方式梳理介面流程
  3. 通過分析其專案所占用資源情況、依賴第三方基礎占用資源情況以及Tracing更進一步的確定瓶頸大概的點在哪幾塊
  4. 通過反復測驗調整確定性能瓶頸的最大黑手
  5. 將最后的結論與相關開發、運維人員溝通,確保都知曉瓶頸在哪里,最后優化瓶頸

知識點:

  • Dapr
    • 手把手教你學Dapr系列
  • Tracing
    • OpenTracing 簡介、關于OpenTracing后續我們也會開源,可以提前關注我們的開源專案
      • Masa.BuildingBlocks
      • Masa.Contrib

開源地址

MASA.BuildingBlocks:https://github.com/masastack/MASA.BuildingBlocks

MASA.Contrib:https://github.com/masastack/MASA.Contrib

MASA.Utils:https://github.com/masastack/MASA.Utils

MASA.EShop:https://github.com/masalabs/MASA.EShop

MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor

如果你對我們的 MASA Framework 感興趣,無論是代碼貢獻、使用、提 Issue,歡迎聯系我們

16373211753064.png

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

標籤:C#

上一篇:設備管理系統CNC管理系統機床管理系統CNC設備點檢系統CNC機床設備報修系統機床報修系統

下一篇:OrchardCore Headless建站拾遺

標籤雲
其他(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