自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一篇帶給你網(wǎng)絡(luò)請(qǐng)求與I/O雜談

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
本篇文章談?wù)勛约簩?duì)XHR及相關(guān)標(biāo)準(zhǔn),然后談?wù)劜僮飨到y(tǒng)的I/0及Node的異步I/0。希望對(duì)你有所幫助!

[[399853]]

前言

我始終覺(jué)得博客不是想什么就寫什么的,一定是有某一個(gè)契機(jī),使得我們對(duì)某一個(gè)點(diǎn)或者方向有深度探索繼續(xù)學(xué)習(xí)或者加深印象的過(guò)程,并有體系的將這個(gè)過(guò)程記錄下來(lái),昨天其實(shí)就在寫博客了,寫的點(diǎn)是關(guān)于XMLHttpRequest的,是因?yàn)橹案粋€(gè)同學(xué)談及到了它,以及相關(guān)的網(wǎng)絡(luò)請(qǐng)求標(biāo)準(zhǔn)AJAX、Fetch、axios等,最近,因?yàn)樵诘却撐拿彽倪^(guò)程中,有了寫書(shū)的想法,于是便匆匆開(kāi)始了寫書(shū)之旅,一本關(guān)于Node的原理及實(shí)踐應(yīng)用的書(shū),暫取名《Node雜談》,目前已經(jīng)寫了61頁(yè)了,但我是個(gè)善變的人,說(shuō)不定過(guò)幾天我就不想寫了😄,但希望自己能堅(jiān)持用半年到一年的時(shí)間完成這本可能沒(méi)啥用的書(shū)。接下來(lái)開(kāi)始自己的博客,先談?wù)勛约簩?duì)XHR及相關(guān)標(biāo)準(zhǔn),然后談?wù)劜僮飨到y(tǒng)的I/0及Node的異步I/0。

網(wǎng)絡(luò)請(qǐng)求

XHR背景

網(wǎng)絡(luò)請(qǐng)求的這幾個(gè)標(biāo)準(zhǔn)和庫(kù),其實(shí)沒(méi)有必要開(kāi)一片博客來(lái)記錄下自己的想法和理解的,偶然和和同學(xué)說(shuō)道這些網(wǎng)絡(luò)交互的標(biāo)準(zhǔn)或者是庫(kù),有些歧義,我又去網(wǎng)上看看了一些人的博客想著是否可以糾正自己可能會(huì)是錯(cuò)誤的理解,然后我就在網(wǎng)上不斷翻閱,按照我自己對(duì)自己寫的博客的標(biāo)準(zhǔn)來(lái)定義,我查閱到的這些博客都是一些不能入眼的內(nèi)容,只是互聯(lián)網(wǎng)沒(méi)有自動(dòng)垃圾回收的機(jī)制,無(wú)可厚非,我的理解或者我的博客一樣也會(huì)被別人理解為www的設(shè)計(jì)缺陷,但至少我愿意把一件事講清楚,給自己講清楚。最近開(kāi)始籌劃并著手寫一本自己對(duì)于Node的理解及相關(guān)實(shí)戰(zhàn)項(xiàng)目的書(shū),談及ajax時(shí)候,我寫了這樣一段話:

我在這段話中大肆吐槽了所謂的模塊或者框架用的很六的使用者。如果你沒(méi)有看過(guò)fetch的源碼實(shí)現(xiàn),或者說(shuō)你并沒(méi)有看過(guò)axios的源碼實(shí)現(xiàn),你連攔截器是怎么定義的都不知道,你用的再六又能怎么樣尼?希望這段話在勉勵(lì)我自己的同時(shí),也能觸及到看見(jiàn)我博客的志同道合的朋友。接下來(lái)我談一談我自己對(duì)于ajax、fetch、axios的個(gè)人理解。

ajax

ajax全稱是啥,看到這你能在腦海中反應(yīng)出來(lái)么?異步的javascript和xml,英文:Asynchronous JavaScript and XML,是利用瀏覽器已有標(biāo)準(zhǔn)重新組合后的新技術(shù)標(biāo)準(zhǔn),應(yīng)該可以說(shuō)ajax是web1.0到web2.0跨越的重大功臣之一。為什么這么說(shuō),ajax最直觀的特點(diǎn)就是通過(guò)請(qǐng)求與響應(yīng)來(lái)局部刷新頁(yè)面,而不是說(shuō)之前的必須通過(guò)表單進(jìn)行一次整體的請(qǐng)求與響應(yīng),刷新整個(gè)頁(yè)面,浪費(fèi)網(wǎng)絡(luò)資源,用戶體驗(yàn)也極差。ajax有缺點(diǎn)么?或者說(shuō)有哪些在以前全局刷新情況下能夠很容易實(shí)現(xiàn)的功能但是使用ajax后就變得比較繁雜尼?以下4點(diǎn)是我在網(wǎng)上尋到并深有同感的幾點(diǎn),如下:

a. AJAX干掉了Back和History功能,即對(duì)瀏覽器機(jī)制的破壞

b. AJAX的安全問(wèn)題

c. 對(duì)搜索引擎支持較弱

d. 違背URL和資源定位的初衷

現(xiàn)代瀏覽器的實(shí)現(xiàn)主要依靠XMLHttpRequest對(duì)象,因?yàn)闉g覽器的版本不同,帶來(lái)不對(duì)于XHR的兼容問(wèn)題,那,看到這里,你可以立馬動(dòng)手實(shí)現(xiàn)一個(gè)最原始的AJAX么?

  1. function loadXMLDoc() 
  2.  var xmlhttp; 
  3.  if (window.XMLHttpRequest) 
  4.  { 
  5.   //  IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執(zhí)行代碼 
  6.   xmlhttp=new XMLHttpRequest(); 
  7.  } 
  8.  else 
  9.  { 
  10.   // IE6, IE5 瀏覽器執(zhí)行代碼 
  11.   xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); 
  12.  } 
  13.  xmlhttp.onreadystatechange=function() 
  14.  { 
  15.   if (xmlhttp.readyState==4 && xmlhttp.status==200) 
  16.   { 
  17.    // 返回?cái)?shù)據(jù)處理 
  18.    document.getElementById("myDiv").innerHTML=xmlhttp.responseText; 
  19.   } 
  20.  } 
  21.  
  22.  // 請(qǐng)求發(fā)送 true 異步,肯定異步啊,你要同步??? 
  23.  xmlhttp.open("GET","/try/ajax/ajax_info.txt",true); 
  24.  xmlhttp.send(); 

代碼我肯定不會(huì)一行一行講解的,這沒(méi)啥,就很簡(jiǎn)單,但是onreadystatechange中的readyState以及status是值得關(guān)注的,其記錄著ajax的運(yùn)行狀態(tài)以及響應(yīng)狀態(tài)。onreadystatechange:每當(dāng) readyState 屬性改變時(shí),就會(huì)調(diào)用該函數(shù)。readyState:存有XMLHttpRequest的狀態(tài)。從 0 到 4 發(fā)生變化,值對(duì)應(yīng)的狀態(tài)如下:

0: 請(qǐng)求未初始化

1: 服務(wù)器連接已建立

2: 請(qǐng)求已接收

3: 請(qǐng)求處理中

4: 請(qǐng)求已完成,且響應(yīng)已就緒

status:記錄著響應(yīng)的狀態(tài) 200: "OK"、404: 未找到頁(yè)面等等

promise

接下來(lái)談?wù)刾romise這個(gè)對(duì)象,用來(lái)干啥的,簡(jiǎn)單說(shuō)就是對(duì)JS異步編程的一種能力加持,讓異步代碼的編寫及閱讀不再那么的惡心人。我寫一段惡心人的簡(jiǎn)單實(shí)例:

  1. setTimeout(()=>{ 
  2.  setTimeout(()=>{ 
  3.   setTimroiut(()=>{ 
  4.    ...... 
  5.   },1000) 
  6.     },1000) 
  7. },1000) 

你可能會(huì)說(shuō),啊這還好呀,這有啥。這只是我的一個(gè)簡(jiǎn)單舉例,當(dāng)在真實(shí)場(chǎng)景下無(wú)論前后端,不斷的異步嵌套的時(shí)候,你定會(huì)抓狂。那么,Promise是如何改善這種問(wèn)題的尼?

將Promise理解為狀態(tài)扭轉(zhuǎn)機(jī),類似于我們?cè)趯W(xué)習(xí)編譯原理里面的有限狀態(tài)自動(dòng)機(jī),會(huì)由一個(gè)狀態(tài)過(guò)渡到另一個(gè)狀態(tài),并且狀態(tài)是會(huì)結(jié)束的,有終點(diǎn)的。promise具有三種狀態(tài),pending、resolve、reject。狀態(tài)的扭轉(zhuǎn)跟隨著兩過(guò)程:

pending ----> resolve

pending ----> reject

也就是從處理開(kāi)始等待到成功處理或者從處理開(kāi)始等待待處理失敗的過(guò)程。來(lái)看我直接markdown手?jǐn)]把上面的嵌套promise化,讓代碼看起來(lái)更加直觀,流程更加清晰,讓其順序執(zhí)行

  1. console.time(); 
  2. new Promise((resolve,reject)=>{ 
  3.  setTimeout(()=>{ 
  4.   if(Math.random() > 0.5){ 
  5.    resolve("timer1"); 
  6.   }else
  7.    reject("timer1 error"); 
  8.   } 
  9.    
  10.  },1000) 
  11. }).then((data)=>{ 
  12.  console.log(data); 
  13.  return new Promise((resolve, reject)=>{ 
  14.   setTimeout(()=>{ 
  15.    if(Math.random() > 0.5){ 
  16.     resolve("timer2"); 
  17.    }else
  18.     reject("timer2 error"); 
  19.    } 
  20.   },2000) 
  21.  }) 
  22.   
  23. }).then((data)=>{ 
  24.  console.log(data); 
  25.  return new Promise((resolve, reject)=>{ 
  26.   setTimeout(()=>{ 
  27.    if(Math.random() > 0.5){ 
  28.     resolve("timer3"); 
  29.    }else
  30.     reject("timer3 error"); 
  31.    } 
  32.   },2000) 
  33.  }) 
  34. }).catch((err)=>{ 
  35.  console.log(err); 
  36. }) 
  37. console.timeEnd() 

如果你的運(yùn)氣夠好,每次都能random在0.5以下,那你就能看到 timer1,timer2,運(yùn)氣不好直接就timer1 error了。為什么我在每個(gè)then里面都new了promise???感到奇怪?那就去看看mdn,then需要返回一個(gè)peomise對(duì)象。

promise還提供了race、all等靜態(tài)方法,用于串行或者并行執(zhí)行,需要的自己下來(lái)看看,你也可以試試手?jǐn)]一個(gè)promise,那你就很牛了。

fetch

講到了fetch,我說(shuō)fetch其實(shí)就是ajax加一層promise的封裝,你贊同么?如果你贊同并且說(shuō)這是一種polyfill,那我覺(jué)得你是完全懂fetch的使用方法并且明了其實(shí)現(xiàn)過(guò)程的,與其說(shuō)fetch是promise對(duì)ajax進(jìn)行了封裝,說(shuō)的更準(zhǔn)確一些的就是fetch是和ajax一樣同樣使用XMLHTTPRequest對(duì)象實(shí)現(xiàn)的各種http請(qǐng)求,然后使用promise進(jìn)行了包裝使用.then.catch實(shí)現(xiàn)調(diào)用,但是其又與ajax稍有不同,為什么尼?因?yàn)槠溆袑儆谧约旱膶?shí)現(xiàn)方案,fetch的源碼,一共500多行,重點(diǎn)在其實(shí)現(xiàn)的幾個(gè)對(duì)象:Headers, Body, Request, Response,根據(jù)這幾個(gè)對(duì)象的命名就可以知道是對(duì)http結(jié)構(gòu)及請(qǐng)求響應(yīng)過(guò)程中的數(shù)據(jù)及方法的封裝,最后進(jìn)行fetch方法的封裝。網(wǎng)上看到一個(gè)博主放了一段簡(jiǎn)化的代碼,如下:

  1. (function (self) { 
  2.   'use strict'
  3.   if (self.fetch) { 
  4.      return 
  5.   } 
  6.   
  7.   // 封裝的 Headers,支持的方法參考https://developer.mozilla.org/en-US/docs/Web/API/Headers 
  8.   function Headers(headers) { 
  9.     ...... 
  10.   }   
  11.   
  12.   //方法參考:https://developer.mozilla.org/en-US/docs/Web/API/Body 
  13.   function Body() { 
  14.     ...... 
  15.   } 
  16.   
  17.   // 請(qǐng)求的Request對(duì)象 ,https://developer.mozilla.org/en-US/docs/Web/API/Request 
  18.   // cache,context,integrity,redirect,referrerPolicy 在MDN定義中是存在的 
  19.   function Request(input, options) { 
  20.      ...... 
  21.   } 
  22.   
  23.   Body.call(Request.prototype)  //把Body方法屬性綁到 Reques.prototype 
  24.   
  25.   function Response(bodyInit, options) { 
  26.   } 
  27.   
  28.   Body.call(Response.prototype) //把Body方法屬性綁到 Reques.prototype 
  29.   
  30.   self.Headers = Headers  //暴露Headers 
  31.   self.Request = Request //暴露Request 
  32.   self.Response = Response //暴露Response 
  33.   
  34.   self.fetch = function (input, init) { 
  35.     return new Promise(function (resolve, reject) { 
  36.       var request = new Request(input, init)  //初始化request對(duì)象 
  37.       var xhr = new XMLHttpRequest()  // 初始化 xhr 
  38.   
  39.       xhr.onload = function () { //請(qǐng)求成功,構(gòu)建Response,并resolve進(jìn)入下一階段 
  40.         var options = { 
  41.           status: xhr.status, 
  42.           statusText: xhr.statusText, 
  43.           headers: parseHeaders(xhr.getAllResponseHeaders() || ''
  44.         } 
  45.         options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL'
  46.         var body = 'response' in xhr ? xhr.response : xhr.responseText 
  47.         resolve(new Response(body, options)) 
  48.       } 
  49.   
  50.       //請(qǐng)求失敗,構(gòu)建Error,并reject進(jìn)入下一階段 
  51.       xhr.onerror = function () { 
  52.         reject(new TypeError('Network request failed')) 
  53.       } 
  54.   
  55.       //請(qǐng)求超時(shí),構(gòu)建Error,并reject進(jìn)入下一階段 
  56.       xhr.ontimeout = function () { 
  57.         reject(new TypeError('Network request failed')) 
  58.       } 
  59.   
  60.       // 設(shè)置xhr參數(shù) 
  61.       xhr.open(request.method, request.url, true
  62.   
  63.       // 設(shè)置 credentials 
  64.       if (request.credentials === 'include') { 
  65.         xhr.withCredentials = true 
  66.       } else if (request.credentials === 'omit') { 
  67.         xhr.withCredentials = false 
  68.       } 
  69.   
  70.       // 設(shè)置 responseType 
  71.       if ('responseType' in xhr && support.blob) { 
  72.         xhr.responseType = 'blob' 
  73.       } 
  74.   
  75.       // 設(shè)置Header 
  76.       request.headers.forEach(function (value, name) { 
  77.         xhr.setRequestHeader(name, value) 
  78.       }) 
  79.       // 發(fā)送請(qǐng)求 
  80.       xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit) 
  81.     }) 
  82.   } 
  83.   //標(biāo)記是fetch是polyfill的,而不是原生的 
  84.   self.fetch.polyfill = true 
  85. })(typeof self !== 'undefined' ? self : this); // IIFE函數(shù)的參數(shù),不用window,web worker, service worker里面也可以使用 

fetch本質(zhì)意義上還是對(duì)XMLHttpRequest的請(qǐng)求封裝。

axios

談到axios時(shí),這是我們經(jīng)常會(huì)使用的一個(gè)網(wǎng)絡(luò)請(qǐng)求工具,易用且強(qiáng)大,提供了多種框架的版本,真是好,我還是貼一下axios的特性

1.從瀏覽器中創(chuàng)建XMLHttpRequests

2.從node.js創(chuàng)建http請(qǐng)求

3.支持PromiseAPI

4.攔截請(qǐng)求和響應(yīng)

5.轉(zhuǎn)換請(qǐng)求數(shù)據(jù)和響應(yīng)數(shù)據(jù)

6.取消請(qǐng)求

7.自動(dòng)轉(zhuǎn)換JSON數(shù)據(jù)

8.客戶端支持防御XSRF

axios的源碼我還沒(méi)看完,沒(méi)有資格評(píng)論源碼級(jí)別的實(shí)現(xiàn),但其就是promise對(duì)ajax的封裝,利用promise的能力來(lái)實(shí)現(xiàn)并行與串行的請(qǐng)求等,攔截器是一個(gè)很好的特性,允許我們?cè)谡?qǐng)求開(kāi)始之前或者響應(yīng)開(kāi)始之前做一些我們想做的操作,這給業(yè)務(wù)層面的實(shí)現(xiàn)又多了其他的實(shí)現(xiàn)方案,說(shuō)實(shí)話,我一開(kāi)始一直覺(jué)得axios攔截器的實(shí)現(xiàn)是通過(guò)捕捉ajax的幾種狀態(tài)值并做響應(yīng)的方法處理實(shí)現(xiàn)的,但是在閱讀部分源碼后我發(fā)現(xiàn)不是,原理是axios維護(hù)了一個(gè)攔截器方法數(shù)組,其實(shí)就是自定義方法,并使用use方法依次將攔截器數(shù)組里面的自定方法放在請(qǐng)求之前,利用promise形成鏈?zhǔn)秸{(diào)用,也就是順序調(diào)用來(lái)實(shí)現(xiàn)的。

I/O

I/O 背景

為啥又要講I/O了,事情是這樣的,上午時(shí)候跟一個(gè)自己尊敬的老師好友對(duì)一款桌面軟件的實(shí)現(xiàn)方案進(jìn)行了討論,大致就是一款圖形處理兼AI推理的windows桌面應(yīng)用,業(yè)務(wù)方要求必須使用c++完成所有的前后端開(kāi)發(fā)工作,并且算子服務(wù)必須函數(shù)化在本地,于是我就開(kāi)始了思考,給出了兩個(gè)實(shí)現(xiàn)方案,如下:

方案的思考過(guò)程中,我比較關(guān)注的兩個(gè)點(diǎn)是實(shí)現(xiàn)成本及軟件性能,之前寫過(guò)一篇對(duì)于端側(cè)性能的思考,尤其是這類需要做圖像處理,AI推理的應(yīng)用,性能要求是極高的,當(dāng)然,畢竟跑在windows上,而不是一些手機(jī)等終端上,GPU的調(diào)用十分的方便,性能也不會(huì)差到哪兒去,然后又基于實(shí)現(xiàn)方案的成本及可維護(hù)性做了思考,才給出了以上的兩種方案,談及到了I/O,這激起了我對(duì)異步I/O的思考。

異步I/O

說(shuō)到異步編程,我相信這對(duì)于除開(kāi)javascript以外的眾多語(yǔ)言都是比較陌生的,而且在絕大多數(shù)高級(jí)編程語(yǔ)言中,異步貌似不太被采納,大多數(shù)都喜歡利用從頭到腳同步阻塞的方式來(lái)執(zhí)行,例如:PHP(哈哈哈,天下最好的語(yǔ)言),當(dāng)然這樣利于邏輯的理解與實(shí)現(xiàn),但是在復(fù)雜的應(yīng)用中,阻塞那是不能想象的,可能你會(huì)說(shuō),我多線程啊,再進(jìn)行線程通信不就好了,繼續(xù)看,看到這篇博客的人,一定是用過(guò)nginx的,為什么nginx會(huì)有如此高的性能表現(xiàn),這得益于事件驅(qū)動(dòng),異步I/O的架構(gòu)設(shè)計(jì),在進(jìn)行I/O的過(guò)程中,不用等待著上一個(gè)I/O執(zhí)行完成才進(jìn)行下一個(gè)步驟的執(zhí)行。而Node的設(shè)計(jì)就與Nginx的事件驅(qū)動(dòng)、異步I/O架構(gòu)不能說(shuō)一模一樣,但也90%一樣了。

前面我在吐槽PHP沒(méi)有異步I/O不能承載高并發(fā)應(yīng)用時(shí),PHPer會(huì)說(shuō),我為什么不能多線程并行執(zhí)行來(lái)提高并發(fā)的能力,為什么非要異步I/O尼,無(wú)可厚非,如果創(chuàng)建多線程的開(kāi)銷小于并行執(zhí)行的開(kāi)銷,那肯定多線程是首選,但是多線程就意味著你需要?jiǎng)?chuàng)建多個(gè)線程并且在多個(gè)線程之間來(lái)回切換會(huì)帶來(lái)巨大的開(kāi)銷,通常來(lái)說(shuō),遇見(jiàn)比較復(fù)雜的應(yīng)用,你還需要做到鎖的應(yīng)用,以及狀態(tài)同步等問(wèn)題,那么,異步I/O就能很好的解決這樣的問(wèn)題,利用單線程,遠(yuǎn)離多線層死鎖、狀態(tài)同步等問(wèn)題,遠(yuǎn)離阻塞,更好的利用CPU等。

異步I/O的執(zhí)行過(guò)程

畫(huà)了張圖如下:

如上圖,異步I/O的精髓在于,單線程進(jìn)行I/O處理時(shí),并不會(huì)阻塞其它指令的執(zhí)行,在完成處理后,通過(guò)callback完成數(shù)據(jù)返回。雖然上文一直在說(shuō)異步與同步,但是對(duì)于操作系統(tǒng)內(nèi)核來(lái)說(shuō),處理I/O只有阻塞與非阻塞之分,阻塞I/O就是調(diào)用I/O處理之后一定要等到系統(tǒng)內(nèi)核層面完成操作后,調(diào)用才結(jié)束,才能往下執(zhí)行,這就會(huì)造成CPU等待I/O執(zhí)行完成,造成CPU使用空余,效率低下,而操作系統(tǒng)利用輪詢實(shí)現(xiàn)的非阻塞I/O能夠通過(guò)一系列機(jī)制來(lái)改善阻塞I/O,提升CPU使用效率及性能,這里我畫(huà)圖總結(jié)一下。應(yīng)該來(lái)的更明顯直觀:

操作系統(tǒng)通過(guò)輪詢實(shí)現(xiàn)的非阻塞調(diào)用,能夠在貌似異步的情況下取的完整的I/O數(shù)據(jù),但是對(duì)于應(yīng)用程序而言,依然是同步的,因?yàn)镃PU還是需要等待I/O的完全返回。理想的非阻塞異步I/O應(yīng)該是應(yīng)用程序發(fā)起非阻塞調(diào)用,而不是通過(guò)一些輪詢,遍歷機(jī)制來(lái)實(shí)現(xiàn)一種偽異步,現(xiàn)實(shí)中,實(shí)現(xiàn)真正的應(yīng)用程序調(diào)用異步,使用了線層池方案,通過(guò)讓部分線程進(jìn)行阻塞I/O或者非阻塞I/O加輪詢完成數(shù)據(jù)的獲取,讓一個(gè)線程來(lái)進(jìn)行計(jì)算處理,通過(guò)線程間通信將I/O線程獲取的數(shù)據(jù)進(jìn)行傳遞,實(shí)現(xiàn)異步I/O。這也是Node實(shí)現(xiàn)的異步I/O的底層方案。

Node 異步I/O

當(dāng)然,Node實(shí)現(xiàn)了跨平臺(tái)的異步I/O,開(kāi)發(fā)者在*nix及windwos異步I/O之上實(shí)現(xiàn)了Libuv來(lái)實(shí)現(xiàn)跨平臺(tái),linux平臺(tái)自己實(shí)現(xiàn)了異步I/O,windows則采用了iocp實(shí)現(xiàn),所以,我總說(shuō)Node是機(jī)制創(chuàng)新,底層還是得益于C++的線程池異步I/O帶來(lái)的高性能

本文轉(zhuǎn)載自公眾號(hào)【QC的黑板報(bào)】,如需轉(zhuǎn)載請(qǐng)聯(lián)系作者!

 

責(zé)任編輯:姜華 來(lái)源: QC的黑板報(bào)
相關(guān)推薦

2021-07-12 06:11:14

SkyWalking 儀表板UI篇

2021-07-21 09:48:20

etcd-wal模塊解析數(shù)據(jù)庫(kù)

2022-03-22 09:09:17

HookReact前端

2021-06-21 14:36:46

Vite 前端工程化工具

2021-01-28 08:55:48

Elasticsear數(shù)據(jù)庫(kù)數(shù)據(jù)存儲(chǔ)

2021-04-01 10:51:55

MySQL鎖機(jī)制數(shù)據(jù)庫(kù)

2021-04-14 14:16:58

HttpHttp協(xié)議網(wǎng)絡(luò)協(xié)議

2022-04-29 14:38:49

class文件結(jié)構(gòu)分析

2023-03-29 07:45:58

VS編輯區(qū)編程工具

2021-03-12 09:21:31

MySQL數(shù)據(jù)庫(kù)邏輯架構(gòu)

2024-06-13 08:34:48

2022-02-17 08:53:38

ElasticSea集群部署

2021-04-08 11:00:56

CountDownLaJava進(jìn)階開(kāi)發(fā)

2022-02-25 15:50:05

OpenHarmonToggle組件鴻蒙

2021-04-14 07:55:45

Swift 協(xié)議Protocol

2021-07-08 07:30:13

Webpack 前端Tree shakin

2023-03-13 09:31:04

2021-05-08 08:36:40

ObjectString前端

2021-10-28 08:51:53

GPIO軟件框架 Linux

2021-04-23 08:59:35

ClickHouse集群搭建數(shù)據(jù)庫(kù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)