摘要:什么是在開始打造自己的服務(wù)器之前我們首先明確一下服務(wù)器的定義一個(gè)管理資源并為用戶提供服務(wù)的計(jì)算機(jī)軟件。如何實(shí)現(xiàn)一個(gè)自己的服務(wù)器在實(shí)現(xiàn)自己的服務(wù)器之前首先我們明確一下的本質(zhì)屬于應(yīng)用層的協(xié)議基于的封裝而的應(yīng)用實(shí)現(xiàn)是基于無論是還是都有的封裝。
什么是server
在開始打造自己的服務(wù)器之前,我們首先明確一下服務(wù)器的定義:一個(gè)管理資源并為用戶提供服務(wù)的計(jì)算機(jī)軟件。
根據(jù)功能服務(wù)器分為兩類動(dòng)靜態(tài)服務(wù)器區(qū)別static web server,例如常見的nginx apache等等
dynamic web server,例如常見的tomcat,jboss,resin等等
對于靜態(tài)服務(wù)器來說一般就是讀取資源然后返回給browser;動(dòng)態(tài)服務(wù)器意味著返回給browser的文件是經(jīng)過邏輯處理動(dòng)態(tài)產(chǎn)生的。
服務(wù)器具有的功能特性nginx nginx特點(diǎn)nginx,tomcat這個(gè)兩個(gè)之前用過,也研究過,所以拿這兩個(gè)舉一下示例,不過現(xiàn)在很少用了,現(xiàn)在基本上都是使用node相關(guān)的,所以最后構(gòu)建的serve會基于node。
nginx應(yīng)用場景 靜態(tài)服務(wù)器(圖片,js,css等等)配置簡單,靈活(只有一個(gè)主配置文件nginx.conf)
支持高并發(fā)(靜態(tài)小文件)
占用資源相對較少(2w并發(fā),開啟10個(gè)線程,內(nèi)存消耗只有幾百M(fèi))
功能種類多(例如proxy,cache,Log,Gzip等等)
server { listen 8080; server_name localhost; location / { root html; index index.html index.htm; } }
說明 上面是nginx配置,指定訪問根目錄和默認(rèn)主頁,以及監(jiān)聽端口
? ~ clear ? ~ curl -i http://127.0.0.1:8080 HTTP/1.1 200 OK Server: nginx/1.12.2 //服務(wù)器類型和版本 Date: Fri, 02 Mar 2018 08:49:44 GMT Content-Type: text/html Content-Length: 11 Last-Modified: Fri, 02 Mar 2018 08:46:27 GMT //支持Last-Modified緩存機(jī)制 Connection: keep-alive //支持持久連接 ETag: "5a990f63-b" //支持ETag緩存機(jī)制 Accept-Ranges: bytes // 支持?jǐn)帱c(diǎn)續(xù)傳 hello jsdt% //響應(yīng)體
說明 上面是本地測試請求,從響應(yīng)頭中可以看到支持很多功能
反向代理,負(fù)載均衡
說明 上面是試驗(yàn)效果
upstream jsdt.com { server 127.0.0.1:8083 max_fails=3 fail_timeout=30s weight=1; server 47.97.xxx.xxx:8084 max_fails=3 fail_timeout=30s weight=2; //為了安全 隱藏真實(shí)ip地址 } server { listen 8080; server_name localhost; location / { root html; # index index.html index.htm; proxy_pass http://jsdt.com; proxy_redirect default; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; }}
說明 上面我摘取了關(guān)鍵的部分配置,采用了輪訓(xùn)+weight算法,其它還有ip_hash、url_hash等算法。真實(shí)的應(yīng)用情況,還需要考慮很多問題,例如集群的session同步,記得大學(xué)實(shí)習(xí)期間,當(dāng)時(shí)公司用的是cookie+memcache集群的方案。
tomcat tomcat特點(diǎn)tomcat運(yùn)行在jvm上,跨平臺,是一個(gè)Servlet容器(可以運(yùn)行Servlet,編譯jsp),實(shí)現(xiàn)了在http請求響應(yīng)處理中所需要的http接口相關(guān)實(shí)現(xiàn)類。除此之外也支持虛擬主機(jī),session共享,靜態(tài)文件處理等等,只不過沒那么專業(yè)而已。tomcat應(yīng)用場景
說明 如上所示,我們可以在頁面中添加動(dòng)態(tài)的處理邏輯,返回的數(shù)據(jù)根據(jù)用戶可定制化(相比靜態(tài)服務(wù)器優(yōu)點(diǎn)),最終.jsp被tomcat編譯為.java,然后被javac編譯為通用字節(jié)碼文件,最終運(yùn)行在jvm上。
在實(shí)現(xiàn)自己的服務(wù)器之前,首先我們明確一下server的本質(zhì),server屬于應(yīng)用層的協(xié)議,基于tcp的封裝, 而tcp的應(yīng)用實(shí)現(xiàn)是基于socket(無論是node,還是java都有socket)的封裝。接下來實(shí)現(xiàn)自己的靜態(tài)server
socket監(jiān)聽某個(gè)端口,獲取面向流的數(shù)據(jù)data,我們的server所要做的就是對data進(jìn)行解析封裝,以使其符合http的規(guī)范。
因?yàn)橛衕ttp模塊,所以node當(dāng)中實(shí)現(xiàn)一個(gè)基礎(chǔ)server很簡單。但是如果附加額外的功能,例如壓縮,緩存,斷點(diǎn)續(xù)傳,反向代理什么的就需要自己添加了。
接下來首先看一下項(xiàng)目結(jié)構(gòu),bin目錄主要是放啟動(dòng)腳本相關(guān)的,主邏輯在app.js中,然后根據(jù)功能將代碼拆分成不同的模塊。templatet目錄放置編譯的原始模板。
|____bin | |____.DS_Store | |____deamon.js | |____start | |____yargsConfig.js |____node_modules |____package-lock.json |____package.json |____readme.md |____src | |____.DS_Store | |____app.js | |____asset | |____cacheSupport.js | |____config.js | |____picGuard.js | |____template | |____util.js
在server運(yùn)行前,首先我們通過yargs模塊獲取解析好的命令行參數(shù)。如下所示
if(argv.D){ let sp = cp.spawn(process.execPath, ["deamon.js"],{ cwd: __dirname, stdio: ["ignore","ignore","ignore"], env: argv, detached: true //http://nodejs.cn/api/child_process.html#child_process_child_process_spawn_command_args_options } ) sp.unref() } else { let config = Object.assign({}, defautConfig, argv) let server = new Server(config); server.start(); console.log("server already started") }
說明 如果開啟deamon模式,則通過子進(jìn)程的方式讓服務(wù)在后臺運(yùn)行,反之則直接啟動(dòng)server實(shí)例
在啟動(dòng)server之后,開始接受并處理請求,下面以斷點(diǎn)續(xù)傳功能模塊作為示例
function byteRangeStream(req, res, filepath, statObj) { let start = 0 let end = statObj.size-1 let range = req.headers["range"] if (range){ res.setHeader("Accept-Range","bytes") res.statusCode = 206 //a part of content let result = range.match(/bytes=(d*)-(d*)/); if (result) { start = isNaN(result[1]) ? start : parseInt(result[1]); end = isNaN(result[2]) ? end : parseInt(result[2]) - 1; } } return fs.createReadStream(filepath,{ start, end }) } module.exports ={ byteRangeStream }
說明 在主模塊app.js中,導(dǎo)入上述模塊,如代碼中所示首先判斷客戶端是否支持?jǐn)帱c(diǎn)續(xù)傳,依據(jù)range請求頭,如果有請求范圍,直接返回請求范圍內(nèi)的數(shù)據(jù),否則全部讀取返回,靠的是browser和server的協(xié)商機(jī)制,需要雙方都支持才能完成整個(gè)過程。
更多功能模塊可以參考我的github, 歡迎star。
寫這篇文章,總結(jié)了下server的相關(guān)知識,參考了之前大學(xué)時(shí)做的筆記,看到之前做的記錄,回憶當(dāng)時(shí)在學(xué)校學(xué)習(xí)和公司實(shí)習(xí)的經(jīng)歷,感慨萬千。時(shí)光易逝,做好當(dāng)下的自己。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/93095.html
摘要:優(yōu)化刪除自帶的不必要的文件是有必要的,最大限度保證系統(tǒng)安全。所以我們要對進(jìn)行必要的修改,讓等待數(shù)據(jù)庫啟動(dòng)完畢再啟動(dòng)。 showImg(https://segmentfault.com/img/remote/1460000014711637?w=1010&h=276); 本文是鋼哥的Oracle APEX系列文章中的第五篇,完整 Oracle APEX 系列文章如下: Oracle A...
閱讀 2305·2021-09-27 13:35
閱讀 586·2019-08-30 15:55
閱讀 838·2019-08-30 15:53
閱讀 581·2019-08-30 15:52
閱讀 2176·2019-08-30 12:59
閱讀 2300·2019-08-29 16:42
閱讀 1485·2019-08-26 18:26
閱讀 2498·2019-08-26 13:48