Tomcat 是什么開源的 Java Web 應(yīng)用服務(wù)器,實現(xiàn)了 Java EE(Java Platform Enterprise Edition)的部分技術(shù)規(guī)范,比如 Java Servlet、Java Server Page、JSTL、Java WebSocket。Java EE 是 Sun 公 司為企業(yè)級應(yīng)用推出的標準平臺,定義了一系列用于企業(yè)級開發(fā)的技術(shù)規(guī)范,除了上述的之外,還有 EJB、Java Mail、JPA、JTA、JMS 等,而這些都依賴具體容器的實現(xiàn)。
上圖對比了 Java EE 容器的實現(xiàn)情況,Tomcat 和 Jetty 都只提供了 Java Web 容器必需的 Servlet 和 JSP 規(guī)范,開發(fā)者要想實現(xiàn)其他的功能,需要自己依賴其他開源實現(xiàn)。
Glassfish 是由 Sun 公司推出,Java EE 最新規(guī)范出來之后,首先會在 Glassfish 上進行實 現(xiàn),所以是研究 Java EE 最新技術(shù)的首選。
最常見的情況是使用 Tomcat 作為 Java Web 服務(wù)器,使用 Spring 提供的開箱即用的強大 的功能,并依賴其他開源庫來完成負責的業(yè)務(wù)功能實現(xiàn)。
Servlet 容器Tomcat 組成如下圖:主要有 Container 和 Connector 以及相關(guān)組件構(gòu)成。
Server:指的就是整個 Tomcat 服 務(wù)器,包含多組服務(wù),負責管理和 啟動各個 Service,同時監(jiān)聽 8005 端口發(fā)過來的 shutdown 命令,用于關(guān)閉整個容器;
Service:Tomcat 封裝的、對外提供完整的、基于組件的 Web 服務(wù), 包含 Connectors、Container 兩個核心組件,以及多個功能組件,各個 Service 之間是獨立的,但是共享 同一 JVM 的資源;
Connector:Tomcat 與外部世界的連接器,監(jiān)聽固定端口接收外部請求,傳遞給 Container,并將 Container 處理的結(jié)果返回給外部;
Container:Catalina,Servlet 容器,內(nèi)部有多層容器組成,用于管理 Servlet 生命周期,調(diào)用 servlet 相關(guān)方法;
Loader:封裝了 Java ClassLoader,用于 Container 加載類文件;
Realm:Tomcat 中為 Web 應(yīng)用程序提供訪問認證和角色管理的機制;
JMX:Java SE 中定義技術(shù)規(guī)范,是一個為應(yīng)用程序、設(shè)備、系統(tǒng)等植入管理功能的框架,通過 JMX 可以遠程監(jiān)控 Tomcat 的運行狀態(tài);
Jasper:Tomcat 的 JSP 解析引擎,用于將 JSP 轉(zhuǎn)換成 Java 文件,并編譯成 class 文件。
Session:負責管理和創(chuàng)建 Session,以及 Session 的持久化(可自定義),支持 Session 的集 群。
Pipeline:在容器中充當管道的作用,管道中可以設(shè)置各種 valve(閥門),請求和響應(yīng)在經(jīng)由管道中各個閥門處理,提供了一種靈活可配置的處理請求和響應(yīng)的機制。
Naming:命名服務(wù),JNDI, Java 命名和目錄接口,是一組在 Java 應(yīng)用中訪問命名和目錄服務(wù)的 API。命名服務(wù)將名稱和對象聯(lián)系起來,使得我們可以用名稱訪問對象,目錄服務(wù)也是一種命名 服務(wù),對象不但有名稱,還有屬性。Tomcat 中可以使用 JNDI 定義數(shù)據(jù)源、配置信息,用于開發(fā)與部署的分離。
Container 組成
Engine:Servlet 的頂層容器,包含一 個或多個 Host 子容器;
Host:虛擬主機,負責 Web 應(yīng)用的部 署和 Context 的創(chuàng)建;
Context:Web 應(yīng)用上下文,包含多個 Wrapper,負責 Web 配置的解析、管 理所有的 Web 資源;
Wrapper:最底層的容器,是對 Servlet 的封裝,負責 Servlet 實例的創(chuàng) 建、執(zhí)行和銷毀。
生命周期管理
Tomcat 為了方便管理組件和容器的生命周期,定義了從創(chuàng)建、啟動、到停止、銷毀共 12 中狀態(tài),Tomcat 生命周期管理了內(nèi)部狀態(tài)變化的規(guī)則控制,組件和容器只需實現(xiàn)相應(yīng)的生命周期 方法即可完成各生命周期內(nèi)的操作(initInternal、startInternal、stopInternal、 destroyInternal)。
比如執(zhí)行初始化操作時,會判斷當前狀態(tài)是否 New,如果不是,則拋出生命周期異常;如果是,則設(shè)置當前狀態(tài)為 Initializing,并執(zhí)行 initInternal 方法,由子類實現(xiàn),方法執(zhí)行成功則設(shè)置當 前狀態(tài)為 Initialized,執(zhí)行失敗則設(shè)置為 Failed 狀態(tài)。
Tomcat 的生命周期管理引入了事件機制,在組件或容器的生命周期狀態(tài)發(fā)生變化時會通知事件監(jiān)聽器,監(jiān)聽器通過判斷事件的類型來進行相應(yīng)的操作。事件監(jiān)聽器的添加可以在 server.xml 文件中進行配置。
Tomcat 各類容器的配置過程就是通過添加 listener 的方式來進行的,從而達到配置邏輯與容器的解耦。如 EngineConfig、HostConfig、ContextConfig。
EngineConfig:主要打印啟動和停止日志
HostConfig:主要處理部署應(yīng)用,解析應(yīng)用 META-INF/context.xml 并創(chuàng)建應(yīng)用的 Context
ContextConfig:主要解析并合并 web.xml,掃描應(yīng)用的各類 Eeb 資源(filter、servlet、listener)
Tomcat 的啟動過程
啟動從 Tomcat 提供的 start.sh 腳本開始,Shell 腳本會調(diào)用 Bootstrap 的 main 方法,實際調(diào)用了 Catalina 相應(yīng)的 load、start 方法。
load 方法會通過 Digester 進行 config/server.xml 的解析,在解析的過程中會根據(jù) xml 中的關(guān)系和配置信息來創(chuàng)建容器,并設(shè)置相關(guān)的屬性。接著 Catalina 會調(diào)用 StandardServer 的 init 和 start 方法進行容器的初始化和啟動。
按照 xml 的配置關(guān)系,server 的子元素是 service,service 的子元素是頂層容器 Engine,每層容器有持有自己的子容器,而這些元素都實現(xiàn)了生命周期管理 的各個方法,因此就很容易的完成整個容器的啟動、關(guān)閉等生命周期的管理。
StandardServer 完成 init 和 start 方法調(diào)用后,會一直監(jiān)聽來自 8005 端口(可配置),如果接收到 shutdown 命令,則會退出循環(huán)監(jiān)聽,執(zhí)行后續(xù)的 stop 和 destroy 方法,完成 Tomcat 容器的關(guān)閉。同時也會調(diào)用 JVM 的 Runtime.getRuntime()?.addShutdownHook 方法,在虛擬機意外退出的時候來關(guān)閉容器。
所有容器都是繼承自 ContainerBase,基類中封裝了容器中的重復工作,負責啟動容器相關(guān)的組 件 Loader、Logger、Manager、Cluster、Pipeline,啟動子容器(線程池并發(fā)啟動子容器,通過線程池 submit 多個線程,調(diào)用后返回 Future 對象,線程內(nèi)部啟動子容器,接著調(diào)用 Future 對象的 get 方法來等待執(zhí)行結(jié)果)。
List《Future《Void》》 results = new ArrayList《Future《Void》》(); for (int i = 0; i 《 children.length; i++) { results.add(startStopExecutor.submit(new StartChild(children[i]))); } boolean fail = false; for (Future《Void》 result :results) { try { result.get(); } catch (Exception e) { log.error(sm.getString(“containerBase.threadedStartFailed”), e); fail = true; } }
Web 應(yīng)用的部署方式注:
catalina.home:安裝目錄
catalina.base:工作目錄
默認值:user.dirServer.xml 配置 Host 元素,指定 appBase 屬性,默認 $catalina.base/webapps/
Server.xml 配置 Context 元素,指定 docBase,元素,指定 Web 應(yīng)用的路徑
自定義配置在 $catalina.base/EngineName/HostName/XXX.xml 配置 Context 元素
HostConfig 監(jiān)聽了 StandardHost 容器的事件,在 start 方法中解析上述配置文件:
掃描 appbase 路徑下的所有文件夾和 war 包,解析各個應(yīng)用的 META-INF/context.xml,并創(chuàng)建 StandardContext,并將 Context 加入到 Host 的子容器中。
解析 $catalina.base/EngineName/HostName/ 下的所有 Context 配置,找到相應(yīng) Web 應(yīng)用的位置,解析各個應(yīng)用的 META-INF/context.xml,并創(chuàng)建 StandardContext,并將 Context 加入到 Host 的子容器中。
注:
HostConfig 并沒有實際解析 Context.xml,而是在 ContextConfig 中進行的。
HostConfig 中會定期檢查 watched 資源文件(context.xml 配置文件)
ContextConfig 解析 context.xml 順序:
先解析全局的配置 config/context.xml
然后解析 Host 的默認配置 EngineName/HostName/context.xml.default
最后解析應(yīng)用的 META-INF/context.xml
ContextConfig 解析 web.xml 順序:
先解析全局的配置 config/web.xml
然后解析 Host 的默認配置 EngineName/HostName/web.xml.default 接著解析應(yīng)用的 MEB-INF/web.xml
掃描應(yīng)用 WEB-INF/lib/ 下的 jar 文件,解析其中的 META-INF/web-fragment.xml 最后合并 xml 封裝成 WebXml,并設(shè)置 Context
注:
掃描 Web 應(yīng)用和 jar 中的注解(Filter、Listener、Servlet)就是上述步驟中進行的。
容器的定期執(zhí)行:backgroundProcess,由 ContainerBase 來實現(xiàn)的,并且只有在頂層容器中才會開啟線程。(backgroundProcessorDelay=10 標志位來控制)
Servlet 生命周期
Servlet 是用 Java 編寫的服務(wù)器端程序。其主要功能在于交互式地瀏覽和修改數(shù)據(jù),生成動態(tài) Web 內(nèi)容。
請求到達 server 端,server 根據(jù) url 映射到相應(yīng)的 Servlet
判斷 Servlet 實例是否存在,不存在則加載和實例化 Servlet 并調(diào)用 init 方法
Server 分別創(chuàng)建 Request 和 Response 對象,調(diào)用 Servlet 實例的 service 方法(service 方法內(nèi)部會根據(jù) http 請求方法類型調(diào)用相應(yīng)的 doXXX 方法)
doXXX 方法內(nèi)為業(yè)務(wù)邏輯實現(xiàn),從 Request 對象獲取請求參數(shù),處理完畢之后將結(jié)果通過 response 對象返回給調(diào)用方
當 Server 不再需要 Servlet 時(一般當 Server 關(guān)閉時),Server 調(diào)用 Servlet 的 destroy() 方法。
load on startup
當值為 0 或者大于 0 時,表示容器在應(yīng)用啟動時就加載這個 servlet;當是一個負數(shù)或者沒有指定時,則指示容器在該 servlet 被選擇時才加載;正數(shù)的值越小,啟動該 servlet 的優(yōu)先級越高。
single thread model
每次訪問 servlet,新建 servlet 實體對象,但并不能保證線程安全,同時 Tomcat 會限制 servlet 的實例數(shù)目。最佳實踐:不要使用該模型,servlet 中不要有全局變量。
請求處理過程
根據(jù) server.xml 配置的指定的 connector 以及端口監(jiān)聽 http、或者 ajp 請求
請求到來時建立連接,解析請求參數(shù),創(chuàng)建 Request 和 Response 對象,調(diào)用頂層容器 Pipeline 的 invoke 方法
容器之間層層調(diào)用,最終調(diào)用業(yè)務(wù) servlet 的 service 方法
Connector 將 response 流中的數(shù)據(jù)寫到 socket 中
Pipeline 與 Valve
Pipeline 可以理解為現(xiàn)實中的管道,Valve 為管道中的閥門,Request 和 Response 對象在管道中經(jīng)過各個閥門的處理和控制。
每個容器的管道中都有一個必不可少的 basic valve,其他的都是可選的,basic valve 在管道中最后調(diào)用,同時負責調(diào)用子容器的第一個 valve。
Valve 中主要的三個方法:setNext、getNext、invoke。Valve 之間的關(guān)系是單向鏈式結(jié)構(gòu),本身 invoke 方法中會調(diào)用下一個 Valve 的 invoke 方法。
各層容器對應(yīng)的 basic valve 分別是 StandardEngineValve、StandardHostValve、StandardContextValve、StandardWrapperValve。
JSP引擎
JSP 生命周期
編譯階段:servlet 容器編譯 servlet 源文件,生成 servlet 類
初始化階段:加載與 JSP 對應(yīng)的 servlet 類,創(chuàng)建其實例,并調(diào)用它的初始化方法
執(zhí)行階段:調(diào)用與 JSP 對應(yīng)的 servlet 實例的服務(wù)方法
銷毀階段:調(diào)用與 JSP 對應(yīng)的 servlet 實例的銷毀方法,然后銷毀 servlet 實例
JSP元素
代碼片段:《% 代碼片段 %》
JSP聲明:《%! declaration; [ declaration; ]+ 。.. %》
JSP表達式:《%= 表達式 %》
JSP注釋:《%-- 注釋 --%》
JSP指令:《%@ directive attribute=“value” %》
JSP行為:《jsp:action_name attribute=“value” /》
HTML元素:html/head/body/div/p/……
JSP隱式對象:request、response、out、session、application、config、 pageContext、page、Exception
JSP 元素說明
代碼片段:包含任意量的 Java 語句、變量、方法或表達式
JSP 聲明:一個聲明語句可以聲明一個或多個變量、方法,供后面的 Java 代碼使用
JSP 表達式:輸出 Java 表達式的值,String 形式;
JSP 注釋:為代碼作注釋以及將某段代碼注釋掉
JSP 指令:用來設(shè)置與整個 JSP 頁面相關(guān)的屬性:
《%@ page 。.. %》 定義頁面的依賴屬性,比如 language、contentType、errorPage、 isErrorPage、import、isThreadSafe、session 等等
《%@ include 。.. %》 包含其他的 JSP 文件、HTML 文件或文本文件,是該 JSP 文件的一部分,會被同時編譯執(zhí)行
《%@ taglib 。.. %》 引入標簽庫的定義,可以是自定義標簽
JSP 行為:jsp:include、jsp:useBean、jsp:setProperty、jsp:getProperty、jsp:forward
JSP 解析過程
代碼片段:在 _jspService() 方法內(nèi)直接輸出
JSP 聲明:在 servlet 類中進行輸出
JSP 表達式:在 _jspService() 方法內(nèi)直接輸出
JSP 注釋:直接忽略,不輸出
JSP 指令:根據(jù)不同指令進行區(qū)分,include:對引入的文件進行解析;page 相關(guān)的屬性會做為 JSP 的屬性,影響的是解析和請求處理時的行為
JSP 行為:不同的行為有不同的處理方式,jsp:useBean 為例,會從 pageContext 根據(jù) scope 的 類別獲取 bean 對象,如果沒有會創(chuàng)建 bean,同時存到相應(yīng) scope 的 pageContext 中
HTML:在 _jspService() 方法內(nèi)直接輸出
JSP 隱式對象:在 _jspService() 方法會進行聲明,只能在方法中使用
Connector
HTTP,HTTP 是超文本傳輸協(xié)議,是客戶端瀏覽器或其他程序與 Web 服務(wù)器之間的應(yīng)用層通信協(xié)議
AJP,Apache JServ 協(xié)議(AJP)是一種二進制協(xié)議,專門代理從 Web 服務(wù)器到位于后端的應(yīng)用程序服務(wù)器的入站請求阻塞 IO
非阻塞 IO
IO 多路復用
阻塞與非阻塞的區(qū)別在于進行讀操作和寫操作的系統(tǒng)調(diào)用時,如果此時內(nèi)核態(tài)沒有數(shù)據(jù)可讀或者沒有緩沖空間可寫時,是否阻塞。
IO 多路復用的好處在于可同時監(jiān)聽多個 socket 的可讀和可寫事件,這樣就能使得應(yīng)用可以同時監(jiān)聽多個 socket,釋放了應(yīng)用線程資源。
Tomcat 各類 Connector 對比
Connector 的實現(xiàn)模式有三種,分別是 BIO、NIO、APR,可以在 server.xml 中指定。
JIO:用 java.io 編寫的 TCP 模塊,阻塞IO
NIO:用 java.nio 編寫的 TCP 模塊,非阻塞 IO,(IO 多路復用)
APR:全稱 Apache Portable Runtime,使用 JNI 的方式來進行讀取文件以及進行網(wǎng)絡(luò)傳輸
Apache Portable Runtime 是一個高度可移植的庫,它是 Apache HTTP Server 2.x 的核心。APR 具有許多用途,包括訪問高級 IO 功能(如 sendfile,epoll 和 OpenSSL),操作系統(tǒng)級功能(隨機數(shù)生成,系統(tǒng)狀態(tài)等)和本地進程處理(共享內(nèi)存,NT 管道和 Unix 套接字)。
表格中字段含義說明:
Support Polling:是否支持基于 IO 多路復用的 socket 事件輪詢
Polling Size:輪詢的最大連接數(shù)
Wait for next Request:在等待下一個請求時,處理線程是否釋放,BIO 是沒有釋放的,所以在 keep-alive=true 的情況下處理的并發(fā)連接數(shù)有限
Read Request Headers:由于 request header 數(shù)據(jù)較少,可以由容器提前解析完畢,不需要阻塞
Read Request Body:讀取 request body 的數(shù)據(jù)是應(yīng)用業(yè)務(wù)邏輯的事情,同時 Servlet 的限制,是需要阻塞讀取的
Write Response:跟讀取 request body 的邏輯類似,同樣需要阻塞寫
NIO處理相關(guān)類
Acceptor 線程負責接收連接,調(diào)用 accept 方法阻塞接收建立的連接,并對 socket 進行封裝成 PollerEvent,指定注冊的事件為 op_read,并放入到 EventQueue 隊列中,PollerEvent 的 run 方法邏輯的是將 Selector 注冊到 socket 的指定事件。
Poller 線程從 EventQueue 獲取 PollerEvent,并執(zhí)行 PollerEvent 的 run 方法,調(diào)用 Selector 的 select 方法,如果有可讀的 Socket 則創(chuàng)建 Http11NioProcessor,放入到線程池中執(zhí)行。
CoyoteAdapter 是 Connector 到 Container 的適配器,Http11NioProcessor 調(diào)用其提供的 service 方法,內(nèi)部創(chuàng)建 Request 和 Response 對象,并調(diào)用最頂層容器的 Pipeline 中的第一個 Valve 的 invoke 方法。
Mapper 主要處理 http url 到 servlet 的映射規(guī)則的解析,對外提供 map 方法。
NIO Connector主要參數(shù)
Comet
Comet 是一種用于 Web 的推送技術(shù),能使服務(wù)器實時地將更新的信息傳送到客戶端,而無須客戶端發(fā)出請求,在 WebSocket 出來之前,如果不使用 comet,只能通過瀏覽器端輪詢 Server 來模擬實現(xiàn)服務(wù)器端推送。Comet 支持 servlet 異步處理 IO,當連接上數(shù)據(jù)可讀時觸發(fā)事件,并異步寫數(shù)據(jù)(阻塞)。
Tomcat 要實現(xiàn) Comet,只需繼承 HttpServlet 同時,實現(xiàn) CometProcessor 接口。
Begin:新的請求連接接入調(diào)用,可進行與 Request 和 Response 相關(guān)的對象初始化操作,并保存 response 對象,用于后續(xù)寫入數(shù)據(jù)
Read:請求連接有數(shù)據(jù)可讀時調(diào)用
End:當數(shù)據(jù)可用時,如果讀取到文件結(jié)束或者 response 被關(guān)閉時則被調(diào)用
Error:在連接上發(fā)生異常時調(diào)用,數(shù)據(jù)讀取異常、連接斷開、處理異常、socket 超時
Note:
Read:在 post 請求有數(shù)據(jù),但在begin事件中沒有處理,則會調(diào)用read,如果read沒有讀取數(shù)據(jù),在會觸發(fā)Error回調(diào),關(guān)閉socket
End:當socket超時,并且response被關(guān)閉時也會調(diào)用;server被關(guān)閉時調(diào)用
Error:除了socket超時不會關(guān)閉socket,其他都會關(guān)閉socket
End和Error時間觸發(fā)時應(yīng)關(guān)閉當前comet會話,即調(diào)用CometEvent的close方法 Note:在事件觸發(fā)時要做好線程安全的操作
異步 Servlet
傳統(tǒng)流程:
首先,Servlet 接收到請求之后,request 數(shù)據(jù)解析;
接著,調(diào)用業(yè)務(wù)接口的某些方法,以完成業(yè)務(wù)處理;
最后,根據(jù)處理的結(jié)果提交響應(yīng),Servlet 線程結(jié)束。
異步處理流程:
客戶端發(fā)送一個請求
Servlet 容器分配一個線程來處理容器中的一個 Servlet
Servlet 調(diào)用 request.startAsync(),保存 AsyncContext,然后返回
任何方式存在的容器線程都將退出,但是 response 仍然保持開放
業(yè)務(wù)線程使用保存的 AsyncContext 來完成響應(yīng)(線程池)
客戶端收到響應(yīng)
Servlet 線程將請求轉(zhuǎn)交給一個異步線程來執(zhí)行業(yè)務(wù)處理,線程本身返回至容器,此時 Servlet 還沒有生成響應(yīng)數(shù)據(jù),異步線程處理完業(yè)務(wù)以后,可以直接生成響應(yīng)數(shù)據(jù)(異步線程擁有 ServletRequest 和 ServletResponse 對象的引用)
為什么 Web 應(yīng)用中支持異步?
推出異步,主要是針對那些比較耗時的請求:比如一次緩慢的數(shù)據(jù)庫查詢,一次外部 REST API 調(diào)用,或者是其他一些 I/O 密集型操作。這種耗時的請求會很快的耗光 Servlet 容器的線程池,繼而影響可擴展性。
Note:從客戶端的角度來看,request 仍然像任何其他的 HTTP 的 request-response 交互一樣,只是耗費了更長的時間而已。
異步事件監(jiān)聽
onStartAsync:Request 調(diào)用 startAsync 方法時觸發(fā)
onComplete:syncContext 調(diào)用 complete 方法時觸發(fā)
onError:處理請求的過程出現(xiàn)異常時觸發(fā)
onTimeout:socket 超時觸發(fā)
Note:onError/onTimeout 觸發(fā)后,會緊接著回調(diào) onComplete,onComplete 執(zhí)行后,就不可再操作 request 和 response。
原文鏈接:https://juejin.cn/post/6844903473482317837
責任編輯:haq
-
服務(wù)器
+關(guān)注
關(guān)注
12文章
9338瀏覽量
86160 -
開源
+關(guān)注
關(guān)注
3文章
3415瀏覽量
42752 -
tomcat
+關(guān)注
關(guān)注
0文章
30瀏覽量
4873
原文標題:萬字詳解 Tomcat 組成與工作原理
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
ftp服務(wù)器怎么搭建
Flexus 云服務(wù)器 X 實例實踐:安裝 Dashdot 開源服務(wù)器儀表板
![Flexus 云<b class='flag-5'>服務(wù)器</b> X 實例實踐:安裝 Dashdot <b class='flag-5'>開源</b><b class='flag-5'>服務(wù)器</b>儀表板](https://file1.elecfans.com//web3/M00/05/C7/wKgZPGeExheAJ1f4AAEJcgSbShg457.png)
Flexus?X 實例與華為云 EulerOS 的 Tomcat 安裝指南
![Flexus?X 實例與華為云 EulerOS 的 <b class='flag-5'>Tomcat</b> 安裝指南](https://file1.elecfans.com//web3/M00/03/A6/wKgZO2dqgDyAQEjfAAD0oFhITPA170.png)
Tomcat開放源代碼的Web應(yīng)用服務(wù)器
![<b class='flag-5'>Tomcat</b>開放源代碼的Web應(yīng)用<b class='flag-5'>服務(wù)器</b>](https://file1.elecfans.com/web3/M00/03/67/wKgZPGdo2FSAH3IuAAAnuPRPJuY054.png)
如何測試SMTP服務(wù)器功能
SMTP服務(wù)器配置教程
獨立服務(wù)器與云服務(wù)器的區(qū)別
常見的服務(wù)器容器和漏洞類型匯總
串口服務(wù)器的定義和功能
tcp方式連接不了服務(wù)器了,服務(wù)器代碼還能開源嗎?
云服務(wù)器和虛擬服務(wù)器的區(qū)別是什么
京準電子、NTP網(wǎng)絡(luò)授時服務(wù)器工作原理及應(yīng)用領(lǐng)域分析
![京準電子、NTP網(wǎng)絡(luò)授時<b class='flag-5'>服務(wù)器</b><b class='flag-5'>工作原理</b>及應(yīng)用領(lǐng)域分析](https://file1.elecfans.com//web2/M00/E8/8A/wKgaomZMTYSAY0HNAABHJs8GfLc17.jpeg)
高防美國云服務(wù)器的工作原理是什么?
超云信創(chuàng)服務(wù)器與openEuler開源操作系統(tǒng)完成互認證
![超云信創(chuàng)<b class='flag-5'>服務(wù)器</b>與openEuler<b class='flag-5'>開源</b>操作系統(tǒng)完成互認證](https://file1.elecfans.com//web2/M00/C4/EC/wKgaomXwDXCASWQlAATR_zI94qU426.png)
評論