深入理解 Tomcat (二) 從宏觀上理解 Tomcat 組件及架構(gòu)

這是我們自編譯源碼以來(lái)第一次總結(jié) tomcat, 雖然不知從何說(shuō)起, 但這筆不能停下來(lái), 看了很多的文章和源碼, 腦子里從最初的混混沌沌到現(xiàn)在的稍有頭緒, 樓主想說(shuō), 不容易.

tomcat 異常復(fù)雜, 組件巨多. 我認(rèn)為, 作為初學(xué)者, 我們不能直接進(jìn)入源碼, 過多的實(shí)現(xiàn)細(xì)節(jié)會(huì)掩蓋抽象概念, 容易一葉障目不見泰山. 我個(gè)人認(rèn)為<<How Tomcat Works>>這本書寫的很好, 而我也想和這本書的角度一樣, 盡力(注意:是盡力)去描述我所理解的 tomcat.

而我學(xué)習(xí)tomcat 的路線是:

  1. 宏觀上理解 tomcat 組件及架構(gòu)設(shè)計(jì).
  2. 從一個(gè)簡(jiǎn)單的例子來(lái)理解tomcat的底層設(shè)計(jì), 到底是怎么做的.
  3. 從 tomcat 的各個(gè)組件各個(gè)擊破, 理解每個(gè)組件的設(shè)計(jì).
  4. 從2條路線去 debug, 驗(yàn)證之前的理論是否正確, 并深刻理解代碼. 第一條路線是啟動(dòng)過程. 第二條路線是一個(gè) http 請(qǐng)求到 Servlet 的 service() 方法的過程.
  5. 總結(jié) tomcat 的設(shè)計(jì).

大概是這個(gè)樣子, 所以按照我們的研究路線, 大概會(huì)有5到6篇文章來(lái)詳細(xì)講述.

我們的文章會(huì)配上源碼, 所以, 如果同學(xué)們沒有下載源碼, 可以去樓主關(guān)于 tomcat 的第一篇文章去下載源碼, 最好將2份源碼都下載, 因?yàn)槲覀儠?huì)將2分源碼混合的分析.

so, 這是第一篇(雖然標(biāo)題是二).

這篇文章我們主要講什么?
1. 什么是 tomcat?
  1. tomcat 的歷史
  2. 和 tomcat 高度相關(guān)的 Servlet 是什么?是如何工作的?
2. tomcat 是如何設(shè)計(jì)的? 有哪些所謂的組件?
  1.  tomcat 源碼目錄的解釋
  2.  tomcat 整體框架的層次結(jié)構(gòu)和架構(gòu)圖
  3. 分析每個(gè)組件, 包括 Connector, Container, Component
  4. 從接口和類的角度(UML 類圖)看架構(gòu).
3. 總結(jié)

什么是 tomcat ?

我們還是引用一下維基百科:

Tomcat是由Apache軟件基金會(huì)下屬的Jakarta項(xiàng)目開發(fā)的一個(gè)Servlet容器,按照Sun Microsystems提供的技術(shù)規(guī)范,實(shí)現(xiàn)了對(duì)ServletJavaServer PageJSP)的支持,并提供了作為Web服務(wù)器的一些特有功能,如Tomcat管理和控制平臺(tái)、安全域管理和Tomcat閥等。由于Tomcat本身也內(nèi)含了一個(gè)HTTP服務(wù)器,它也可以被視作一個(gè)單獨(dú)的Web服務(wù)器。但是,不能將Tomcat和Apache HTTP服務(wù)器混淆,Apache HTTP服務(wù)器是一個(gè)用C語(yǔ)言實(shí)現(xiàn)的HTTPWeb服務(wù)器;這兩個(gè)HTTP web server不是捆綁在一起的。Apache Tomcat包含了一個(gè)配置管理工具,也可以通過編輯XML格式的配置文件來(lái)進(jìn)行配置。

簡(jiǎn)而言之: tomcat 是一個(gè)接受 http 請(qǐng)求并解析 http 請(qǐng)求并反饋客戶端的一個(gè)應(yīng)用程序.

tomcat 可以說(shuō)是 sun Servlet 的一個(gè)官方參考實(shí)現(xiàn), 因?yàn)?tomcat 剛開始就是 sun 開發(fā)的,后來(lái)捐獻(xiàn)給了 apache 基金會(huì).

在我們理解 tomcat 之前, 我們得了解一下tomcat 所實(shí)現(xiàn)的 Servlet 是什么東東?

那要從互聯(lián)網(wǎng)大潮興起開始講起, 我們知道, 網(wǎng)頁(yè)不止有靜態(tài)的還有動(dòng)態(tài)的, 而在剛開始的時(shí)候, 常見的實(shí)現(xiàn)動(dòng)態(tài)網(wǎng)頁(yè)的技術(shù)就是 CGI, 但是作為 Java 的發(fā)明人, SUN|肯定要搞一個(gè)超級(jí)大風(fēng)頭, 讓整個(gè)世界一下子認(rèn)識(shí)了 Java, 不過很快悲催的發(fā)現(xiàn) Applet 其實(shí)用途不大, 眼看著互聯(lián)網(wǎng)開始流行, 一定要搭上千載難逢的快車啊.

于是, Servlet 就誕生了, Servlet 其實(shí)就是 SUN 為了讓 Java 能實(shí)現(xiàn)動(dòng)態(tài)的可交互的網(wǎng)頁(yè), 從而進(jìn)入 web 編程的領(lǐng)域而定義的一套標(biāo)準(zhǔn).

這套標(biāo)準(zhǔn)是這么說(shuō)的: 你想用 Java 開發(fā)動(dòng)態(tài)網(wǎng)頁(yè), 可以定義一個(gè)自己的" Servlet", 但一定要實(shí)現(xiàn)我的 HTTPServlet 接口, 然后重載 doGet(), doPost()方法. 用戶從流浪器 GET 的時(shí)候, 調(diào)用 doGet 方法, 從流浪器向服務(wù)器發(fā)送表單數(shù)據(jù)的時(shí)候, 調(diào)用 doPost 方法, 如果你想訪問用戶從瀏覽器傳遞過來(lái)的參數(shù), 用 HttpServletRequest 對(duì)象就好了, 里面有 getParameter, getQueryString 方法, 如果你處理完了, 想向?yàn)g覽器返回?cái)?shù)據(jù), 用 HttpServletResponse 對(duì)象調(diào)用 getPrintWriter 方法就可以輸出數(shù)據(jù)了.

如果你想實(shí)現(xiàn)一個(gè)購(gòu)物車, 需要 session, 很簡(jiǎn)單, 從 HttpServletRequest 調(diào)用 getSession 方法就可以了.

那么..... Servlet 是如何工作的

servlet 是一個(gè)復(fù)雜的系統(tǒng), 但是他有三個(gè)基本任務(wù), 對(duì)每個(gè)請(qǐng)求, servlet 容器會(huì)為其完成以下3個(gè)操作:

  1. 創(chuàng)建一個(gè) Request 對(duì)象, 用可能會(huì)在調(diào)用的 Servlet 中使用到的信息填充該 Request 對(duì)象, 如參數(shù), 頭, cookie, 查詢字符串, URI 等, Request 對(duì)象是 javax.servlet.ServletRequest 接口或 javax.servlet.ServletRequest 接口的一個(gè)實(shí)例.
  2. 創(chuàng)建一個(gè)調(diào)用 Servlet 的 Response 對(duì)象, 用來(lái)向 Web 客戶端發(fā)送響應(yīng). response 對(duì)象是 javax.servlet.http.ServletResponse 接口或 javax.servlet.ServletResponse 接口的一個(gè)實(shí)例;
  3. 調(diào)用 Servlet 的 service 方法, 將 request 對(duì)象和 response 對(duì)象作為參數(shù)傳入, Servlet 從 request 對(duì)象中讀取信息, 并通過 response 對(duì)象發(fā)送響應(yīng)信息.

你寫了一個(gè)" Servlet", 接下來(lái)要運(yùn)行, 你就發(fā)現(xiàn)沒法通過 java 直接運(yùn)行了, 你需要一個(gè)能夠運(yùn)行 Servlet 的容器, 這個(gè)容器 Sun 最早實(shí)現(xiàn)了一個(gè), 叫 Java Web Server, 1999年捐給了 Apache Software foundation, 就改名叫 Tomcat. 這就是 Tomcat 的由來(lái).

所以, Tomcat 就是一個(gè) Servlet 容器, 能接收用戶從瀏覽器發(fā)來(lái)的請(qǐng)求, 然后轉(zhuǎn)發(fā)給 Servlet 處理, 把處理完的響應(yīng)數(shù)據(jù)發(fā)回瀏覽器.

但是 Servlet 輸出 Html, 還是采用了老的 CGI 方式 , 是一句一句輸出, 所以,編寫和修改 html 非常不方便, 于是, Java Server Pages(JSP) 就來(lái)救急了, JSP 并沒有增加任何本質(zhì)上不能用 Servlet 實(shí)現(xiàn)的功能, 實(shí)際上 JSP 在運(yùn)行之前, 需要先編譯成 Servlet, 然后才執(zhí)行的.

但是, 在 JSP 中編寫靜態(tài) HTML 更加方便, 不必再用 println 語(yǔ)句來(lái)輸出每一行HTML 代碼, 更重要的是, 借助內(nèi)容和外觀的分離,頁(yè)面制作中不同性質(zhì)的任務(wù)可以方便的分開: 比如, 有頁(yè)面設(shè)計(jì)者進(jìn)行 HTML 設(shè)計(jì), 同時(shí)流出供 Java 程序插入動(dòng)態(tài)內(nèi)容的空間.

Tomcat 能運(yùn)行 Servlet, 當(dāng)然能運(yùn)行 JSP 了.

既然是 Web 服務(wù)器, tomcat 除了能運(yùn)行 Servlet 和 JSP 之外, 也能像 Apache/nginx 一樣, 支持靜態(tài) html, 圖片, 文檔的訪問, 只是性能差一點(diǎn),在實(shí)際的應(yīng)用中, 一般是 Apache/nginx 作為負(fù)載均衡服務(wù)器和靜態(tài)資源服務(wù)器放在最前端, 后面是 tomcat 組成的集群.

如果用戶請(qǐng)求的是靜態(tài)資源, nginx 直接搞定, 如果是動(dòng)態(tài)資源(如xxx.jsp), nginx 就會(huì)按照一定的算法轉(zhuǎn)發(fā)的某個(gè) tomcat 上, 達(dá)到負(fù)載均衡的目的.


Tomcat 是如何設(shè)計(jì)的? 有哪些所謂的組件?

tomcat 的主體是 Catalina, catalina 是一個(gè)成熟的軟件, 設(shè)計(jì)和開發(fā)的十分優(yōu)雅, 功能結(jié)構(gòu)也是模塊化的. 我們之前說(shuō) Servlet 是如何工作的?中提到了 Servlet 容器的任務(wù), 基于這些任務(wù)可以將 Catalina 劃分為兩個(gè)模塊: 連接器(connector)和容器(container).

注意: 連接器和 Servlet 容器是一對(duì)多的關(guān)系.

連接器負(fù)責(zé)將一個(gè)請(qǐng)求與容器相關(guān)聯(lián), 他的工作為它接收到的每個(gè) http 請(qǐng)求創(chuàng)建一個(gè) Request 對(duì)象和一個(gè) Response 對(duì)象, 然后, 他將處理過程交給容器. 容器從連接器中接收到 Request 對(duì)象和 Response 對(duì)象, 并負(fù)責(zé)調(diào)用相應(yīng)的 service 方法.

但是請(qǐng)記住, 上面所描述的處理過程只是 Catalina 容器處理請(qǐng)求的的整個(gè)過程的一小部分, 猶如冰山的一角, 在容器中還包括很多其他的事情要做, 例如, 在容器調(diào)用相應(yīng)的 Servlet 的 service 方法之前, 他必須先載入該 Servlet 類, 對(duì)用戶進(jìn)行身份驗(yàn)證(如果有必要的話), 為用戶更新會(huì)話信息等, 因此, 當(dāng)你發(fā)現(xiàn)容器使用了很多不同的模塊來(lái)處理這些事情時(shí), 請(qǐng)不要它驚訝, 例如, 管理器模塊用來(lái)處理用戶會(huì)話信息, 類載入器模塊用來(lái)載入所需的 Servlet 類.

那么我們來(lái)看看 Tomcat 源碼的目錄結(jié)構(gòu)和每個(gè)目錄是起什么作用的:
dir

Tomcat 整體的框架層次:4個(gè)層次, 其中 Connector 和 Container 是最重要的.

  1. Server 和 Service
  2. Connector
    • HTTP
    • AJP (apache 私有協(xié)議,用于tomcat和apache靜態(tài)服務(wù)器通信)
  3. Container
    • Engine
    • Host
    • Context
    • Wrapper
  4. Component
    • Manager (管理器)
    • logger (日志管理)
    • loader (載入器)
    • pipeline (管道)
    • valve (管道中的閥)
下面我們來(lái)看一張有名的關(guān)于 tomcat 的結(jié)構(gòu)圖:
tomcat 結(jié)構(gòu)圖

注意: Server是整個(gè)Tomcat組件的容器,包含一個(gè)或多個(gè)Service。 Service:Service是包含Connector和Container的集合,Service用適當(dāng)?shù)腃onnector接收用戶的請(qǐng)求,再發(fā)給相應(yīng)的Container來(lái)處理。

從這張圖中可以看到,Tomcat的核心組件就兩個(gè)Connector和Container(后面還有詳細(xì)說(shuō)明),多個(gè)Connector+一個(gè)Container構(gòu)成一個(gè)Service,Service就是對(duì)外提供服務(wù)的組件,有了Service組件Tomcat就可以對(duì)外提供服務(wù)了,但是光有服務(wù)還不行,還得有環(huán)境讓你提供服務(wù)才行,所以最外層的Server就為Service提供了生存的土壤。那么這些個(gè)組件到底是干嘛用的呢?Connector是一個(gè)連接器,主要負(fù)責(zé)接收請(qǐng)求并把請(qǐng)求交給Container,Container就是一個(gè)容器,主要裝的是具體處理請(qǐng)求的組件。Service主要是為了關(guān)聯(lián)Container與Connector,一個(gè)單獨(dú)的Container或者一個(gè)單獨(dú)的Connector都不能完整處理一個(gè)請(qǐng)求,只有兩個(gè)結(jié)合在一起才能完成一個(gè)請(qǐng)求的處理。Server這是負(fù)責(zé)管理Service集合,從圖中我們看到一個(gè)Tomcat可以提供多種服務(wù),那么這些Serice就是由Server來(lái)管理的,具體的工作包括:對(duì)外提供一個(gè)接口訪問Service,對(duì)內(nèi)維護(hù)Service集合,維護(hù)Service集合又包括管理Service的生命周期、尋找一個(gè)請(qǐng)求的Service、結(jié)束一個(gè)Service等


Connector 組件:

Tomcat都是在容器里面處理問題的, 而容器又到哪里去取得輸入信息呢? Connector就是專干這個(gè)的。 他會(huì)把從socket傳遞過來(lái)的數(shù)據(jù), 封裝成Request, 傳遞給容器來(lái)處理。 通常我們會(huì)用到兩種Connector,一種叫http connectoer, 用來(lái)傳遞http需求的。 另一種叫AJP, 在我們整合apache與tomcat工作的時(shí)候,apache與tomcat之間就是通過這個(gè)協(xié)議來(lái)互動(dòng)的。 (說(shuō)到apache與tomcat的整合工作, 通常我們的目的是為了讓apache 獲取靜態(tài)資源, 而讓tomcat來(lái)解析動(dòng)態(tài)的jsp或者servlet。)

總的來(lái)說(shuō),Connector就是解析Http或Ajp請(qǐng)求的。


Container 組件:

我們剛剛看到, 容器從大到小分別是 Engine, Host, Context, Wrapper, 從左到右每個(gè)容器都是一對(duì)多關(guān)系, 也就是說(shuō), Engine 容器可以有多個(gè) Host 容器, Host 容器可以有多個(gè) Context 容器. Context 容器可以有多個(gè) Wrapper 容器.
我們來(lái)看看每個(gè)組件的解釋:

  1. Container:可以理解為處理某類型請(qǐng)求的容器,處理的方式一般為把處理請(qǐng)求的處理器包裝為Valve(閥門)對(duì)象,并按一定順序放入類型為Pipeline(管道)的管道里。Container有多種子類型:Engine、Host、Context和Wrapper,這幾種子類型Container依次包含,處理不同粒度的請(qǐng)求。另外Container里包含一些基礎(chǔ)服務(wù),如Loader、Manager和Realm。
  2. Engine:Engine包含Host和Context,接到請(qǐng)求后仍給相應(yīng)的Host在相應(yīng)的Context里處理。
  3. Host:就是我們所理解的虛擬主機(jī)。
  4. Context:就是我們所部屬的具體Web應(yīng)用的上下文,每個(gè)請(qǐng)求都在是相應(yīng)的上下文里處理的。
  5. Wrapper:Wrapper是針對(duì)每個(gè)Servlet的Container,每個(gè)Servlet都有相應(yīng)的Wrapper來(lái)管理。 可以看出Server、Service、Connector、Container、Engine、Host、Context和Wrapper這些核心組件的作用范圍是逐層遞減,并逐層包含。 下面就是些被Container所用的基礎(chǔ)組件:
    • Loader:是被Container用來(lái)載入各種所需的Class。
    • Manager:是被Container用來(lái)管理Session池。
    • Realm:是用來(lái)處理安全里授權(quán)與認(rèn)證。

Component 組件:

需求被傳遞到了容器里面, 在合適的時(shí)候, 會(huì)傳遞給下一個(gè)容器處理。而容器里面又盛裝著各種各樣的組件, 我們可以理解為提供各種各樣的增值服務(wù)。比如:

  1. manager: 當(dāng)一個(gè)容器里面裝了manager組件后,這個(gè)容器就支持session管理了, 事實(shí)上在tomcat里面的session管理, 就是靠的在context里面裝的manager component.

  2. logger: 當(dāng)一個(gè)容器里面裝了logger組件后, 這個(gè)容器里所發(fā)生的事情, 就被該組件記錄下來(lái), 我們通常會(huì)在logs/ 這個(gè)目錄下看見catalina_log.time.txt 以及l(fā)ocalhost.time.txt和localhost_examples_log.time.txt。 這就是因?yàn)槲覀兎謩e為:engin, host以及context(examples)這三個(gè)容器安裝了logger組件, 這也是默認(rèn)安裝, 又叫做標(biāo)配 .

  3. loader: loader這個(gè)組件通常只會(huì)給我們的context容器使用,loader是用來(lái)啟動(dòng)context以及管理這個(gè)context的classloader用的。

  4. pipline: pipeline是這樣一個(gè)東西,使用的責(zé)任鏈模式. 當(dāng)一個(gè)容器決定了要把從上級(jí)傳遞過來(lái)的需求交給子容器的時(shí)候, 他就把這個(gè)需求放進(jìn)容器的管道(pipeline)里面去。 而需求傻呼呼得在管道里面流動(dòng)的時(shí)候, 就會(huì)被管道里面的各個(gè)閥門攔截下來(lái)。 比如管道里面放了兩個(gè)閥門。 第一個(gè)閥門叫做“access_allow_vavle”, 也就是說(shuō)需求流過來(lái)的時(shí)候,它會(huì)看這個(gè)需求是哪個(gè)IP過來(lái)的, 如果這個(gè)IP已經(jīng)在黑名單里面了,sure, 殺! 第二個(gè)閥門叫做“defaul_access_valve”它會(huì)做例行的檢查, 如果通過的話,OK, 把需求傳遞給當(dāng)前容器的子容器。 就是通過這種方式, 需求就在各個(gè)容器里面?zhèn)鬟f,流動(dòng), 最后抵達(dá)目的地的了。

  5. valve: 就是上面所說(shuō)的閥門。

Tomcat里面大概就是這么些東西, 我們可以簡(jiǎn)單地這么理解tomcat的框架,它是一種自上而下, 容器里又包含子容器的這樣一種結(jié)構(gòu)。

換個(gè)角度再來(lái)看看 Tomcat 的總體架構(gòu):

  • 面向組件架構(gòu)
  • 基于JMX
  • 事件偵聽
  1. 面向組件架構(gòu) tomcat代碼看似很龐大,但從結(jié)構(gòu)上看卻很清晰和簡(jiǎn)單,它主要由一堆組件組成,如Server、Service、Connector等,并基于JMX管理這些組件,另外實(shí)現(xiàn)以上接口的組件也實(shí)現(xiàn)了代表生存期的接口Lifecycle,使其組件履行固定的生存期,在其整個(gè)生存期的過程中通過事件偵聽LifecycleEvent實(shí)現(xiàn)擴(kuò)展。Tomcat的核心類圖如下所示:
    核心類圖

上面我們已經(jīng)對(duì)每個(gè)類的功能進(jìn)行了一些描述.包括 Catalina 類和 Server 類的作用, Service 類是如何關(guān)聯(lián) Connector 和 Container 的. 還有各個(gè)容器是上面關(guān)系. 包括容器中數(shù)據(jù)是如何從從管道( pipeline) 中傳遞, 還有一些組件, 比如類載入器, 管理器, 安全主體( realm);

  1. 基于JMX Tomcat會(huì)為每個(gè)組件進(jìn)行注冊(cè)過程,通過Registry管理起來(lái),而Registry是基于JMX來(lái)實(shí)現(xiàn)的,因此在看組件的init和start過程實(shí)際上就是初始化MBean和觸發(fā)MBean的start方法,會(huì)大量看到形如: Registry.getRegistry(null, null).invoke(mbeans, "init", false); Registry.getRegistry(null, null).invoke(mbeans, "start", false); 這樣的代碼,這實(shí)際上就是通過JMX管理各種組件的行為和生命期。

那么, 什么是 JMX 呢?

JMX 即 Java Management Extensions(JMX 規(guī)范), 是用來(lái)對(duì) tomcat 進(jìn)行管理的. tomcat 中的實(shí)現(xiàn)是 commons modeler 庫(kù), Catalina 使用這個(gè)庫(kù)來(lái)見哈編寫托管 Bean 的工作. 托管 Bean 就是用來(lái)管理 Catalina 中其他對(duì)象的 Bean.

  1. 事件偵聽(觀察者模式/事件驅(qū)動(dòng)) 各個(gè)組件在其生命期中會(huì)有各種各樣行為,而這些行為都有觸發(fā)相應(yīng)的事件,Tomcat就是通過偵聽這些時(shí)間達(dá)到對(duì)這些行為進(jìn)行擴(kuò)展的目的。在看組件的init和start過程中會(huì)看到大量如: lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);這樣的代碼,這就是對(duì)某一類型事件的觸發(fā),如果你想在其中加入自己的行為,就只用注冊(cè)相應(yīng)類型的事件即可。

最后:

我們已經(jīng)從宏觀上詳細(xì)分析了 Tomcat 的架構(gòu)和組件等一些抽象的概念, 可能大家還比較懵逼, 因?yàn)槲覀兺耆羌埳险劚? 沒有真刀真槍實(shí)戰(zhàn)源碼, 所以, 接下來(lái), 讓我們帶著我們準(zhǔn)備好的源碼一起撕開 Tomcat 的衣服, 看看她到底是什么樣子的.

還是像剛開始說(shuō)的:

  1. 宏觀上理解 tomcat 組件及架構(gòu)設(shè)計(jì).
  2. 從一個(gè)簡(jiǎn)單的例子來(lái)理解tomcat的底層設(shè)計(jì), 到底是怎么做的.
  3. 從 tomcat 的各個(gè)組件各個(gè)擊破, 理解每個(gè)組件的設(shè)計(jì).
  4. 從2條路線去 debug, 驗(yàn)證之前的理論是否正確, 并深刻理解代碼. 第一條路線是啟動(dòng)過程. 第二條路線是一個(gè) http 請(qǐng)求到 Servlet 的 service() 方法的過程.
  5. 總結(jié) tomcat 的設(shè)計(jì).

現(xiàn)在我們已經(jīng)完成了第一步, 宏觀上理解了有哪些組件和他的架構(gòu)設(shè)計(jì). 后面的學(xué)習(xí)我們按照計(jì)劃來(lái)執(zhí)行, 不要操之過急, 看源碼最重要的就是沉的下心. 我們會(huì)
先從組件和接口分析, 比如 Connector 和 Container 接口, 還有4大容器接口和管道閥門, 還有 生命周期接口.他們分別使用了什么設(shè)計(jì)模式,還有tomcat 鉤子的使用, 包括tomcat著名的類加載機(jī)制, 為什么違背雙親委任模型等等. 這些內(nèi)容都將是什么重點(diǎn)關(guān)注的.

好了, 今天就到這里, good luck !!!!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 0 系列目錄# WEB請(qǐng)求處理 WEB請(qǐng)求處理一:瀏覽器請(qǐng)求發(fā)起處理 WEB請(qǐng)求處理二:Nginx請(qǐng)求反向代理 本...
    七寸知架構(gòu)閱讀 14,233評(píng)論 22 189
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,755評(píng)論 11 349
  • 轉(zhuǎn)自陳明乾的博客,可能有一定更新。 轉(zhuǎn)原文聲明:原創(chuàng)作品,允許轉(zhuǎn)載,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必以超鏈接形式標(biāo)明文章 原始出處 、...
    C86guli閱讀 4,865評(píng)論 6 72
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • 蘭之味,非可逼而取也。蓋在有無(wú)近遠(yuǎn)續(xù)斷之間,純以情韻勝。氳氳無(wú)所,故稱瑞耳。體兼彩,而不極于色,令人覽之有余,而名...
    淺笑一盈盈閱讀 716評(píng)論 0 1

友情鏈接更多精彩內(nèi)容