摘要:是一個(gè)典型的模式架構(gòu),用戶通過終端將字符流傳遞給。仿照的工作原理,我們在協(xié)議之上設(shè)計(jì)了,見下圖真實(shí)實(shí)現(xiàn)中,是應(yīng)用層的通訊協(xié)議。僵尸進(jìn)程問題我們知道由于缺少而導(dǎo)致僵尸進(jìn)程無法回收的問題迄今存在。進(jìn)入構(gòu)建環(huán)境執(zhí)行命令。
Coding WebIDE 做個(gè)國內(nèi)首個(gè)基于 Docker 技術(shù)的云端開發(fā)平臺(tái)于4月1日正式上線。本文主要和大家分享和探討 Docker 在 Web IDE 中運(yùn)用的一些經(jīng)驗(yàn)。
隨著云計(jì)算技術(shù)的日新月異,云端的代碼倉庫,分工協(xié)作,演示運(yùn)行已經(jīng)被人們廣為接受。云端開發(fā)的出現(xiàn)也正是順應(yīng)了這一趨勢。Docker 作為一個(gè)輕量級(jí)的隔離環(huán)境,無疑是云端開發(fā)解決資源和效率問題的秘藥良方。
記得4月份的杭州 Docker Meetup 有一與會(huì)者提問,“作為一個(gè)云主機(jī)的租戶,向主機(jī)商購買的計(jì)算資源,其獲得的配額不是真實(shí)值而只是上限,覺得不值?!边@個(gè)問題似乎揭露了商家的生意經(jīng),但是本人卻有不同的看法。正是因?yàn)楣蚕砑夹g(shù)的發(fā)展,才讓云計(jì)算資源變得廉潔而被廣為接受,Docker 最大的價(jià)值也在這里。
從技術(shù)特性上看,VM 和 Docker 有些重合點(diǎn)。但是Virtual Machines 是基于 Hypervisor 技術(shù)的,而 Docker 是基于Container 技術(shù)的。Hypervisor 要比 Container 更底層,不是同一層面的競爭關(guān)系,真實(shí)的場景多是先 Hypervisor 再 Container,通俗的說法就是在 VM 里跑Container。
Hypervisor 技術(shù)讓多個(gè)操作系統(tǒng)共享一個(gè)CPU硬件,這些操作系統(tǒng)獨(dú)立運(yùn)行,并不知道彼此的存在,仿佛獨(dú)占了所有的硬件資源。
Container 技術(shù)讓多個(gè)用戶空間共享一個(gè)操作系統(tǒng),這些用戶空間彼此隔絕,仿佛獨(dú)占整個(gè)操作系統(tǒng)。
我們都知道,文件是對 I/O 設(shè)備的抽象表示,虛擬存儲(chǔ)器是對主存和磁盤 I/O 設(shè)備的抽象表示,進(jìn)程則是對處理器、主存和 I/O 設(shè)備的抽象表示。相比之下,虛擬化將操作系統(tǒng)從硬件中抽象出來,容器技術(shù)將應(yīng)用從操作系統(tǒng)抽象出來。
一個(gè)正在執(zhí)行的進(jìn)程,由于虛擬內(nèi)存技術(shù),就其視角來看,仿佛擁有了整個(gè)操作系統(tǒng)的計(jì)算資源。但是 Container 的抽象和進(jìn)程抽象不是在一個(gè)層面的。簡單說,一臺(tái)物理設(shè)備可以借助于 Hypervisor 技術(shù),運(yùn)行多個(gè) VM;而個(gè)操作系統(tǒng)可以借助 Container 技術(shù),運(yùn)行多個(gè) Container;而 Container 里可以有多個(gè)進(jìn)程。
上面簡單的介紹了一些 Docker 技術(shù)的背景,言歸正傳。
為什么選用 Docker 而不是更成熟的 VM實(shí)現(xiàn) WebIDE 首先解決的就是環(huán)境隔離,多個(gè)用戶之間不會(huì)相互干擾。物理機(jī)是相互隔離的,但是為每一個(gè)用戶分配一臺(tái)真實(shí)的物理機(jī),顯然是不合現(xiàn)實(shí)的。
VM 可以提供和物理機(jī)一樣的隔離效果,由于 VM 共享硬件,所以更省資源。一個(gè)可行的方案是借助 IaaS 平臺(tái)商提供的 OpenAPI 來操作 VM。這樣對物理主機(jī)和宿主操作系統(tǒng)的維護(hù)工作可以完全委托給IaaS平臺(tái)商。
相比 Docker Container,VM 有一個(gè)很大的技術(shù)優(yōu)勢是支持休眠。操作系統(tǒng)在系統(tǒng)級(jí)實(shí)現(xiàn)了休眠,這樣用戶的工作狀態(tài),內(nèi)存中的數(shù)據(jù)可以完整的持久化。作為一個(gè)常年不關(guān)機(jī)的開發(fā)者,個(gè)人覺得這個(gè)功能非常實(shí)用。可惜Docker 只提供了睡眠(類似于進(jìn)程級(jí)別的掛起),而做不到休眠。隨著CRIU技術(shù)的發(fā)展,相信 Docker 很快會(huì)支持的。
另外 VM 在不同宿主機(jī)之間的遷移問題,經(jīng)過多年社區(qū)的積累越來越成熟。如果選擇向 IaaS 平臺(tái)商購買 VM 服務(wù),這部分工作也不用關(guān)心。Docker Container 數(shù)據(jù)的遷移,面臨著自制。目前Docker 官方提供遷移Container(非image)的命令,只能遷移文件,無法保留狀態(tài)(比如外部mount的目錄)。
考慮到架構(gòu)的微服務(wù)化,如文件服務(wù),Git 服務(wù),Terminal 服務(wù),Runtime 服務(wù)。有些服務(wù)是單例的,另一些則會(huì)隨著用戶會(huì)話狀態(tài)而動(dòng)態(tài)地創(chuàng)建和銷毀。當(dāng)應(yīng)用實(shí)例很多的時(shí)候,虛擬化技術(shù)的 Overhead 是需要考慮的因素。為了某個(gè)服務(wù)而啟動(dòng)整個(gè)操作系統(tǒng)有些負(fù)擔(dān)不起。除了過度的內(nèi)存消耗,啟動(dòng)耗時(shí)也存在差異,Container 只是用戶空間的一個(gè)或者一組進(jìn)程,所以啟動(dòng)耗時(shí)基本是毫秒級(jí)別,而 VM 至少是秒級(jí),有的甚至是分鐘級(jí)(休眠還原的時(shí)候)。
做比較的時(shí)候總是各有優(yōu)劣,但最終打動(dòng)我們的除了 Docker 的輕量,還有其生機(jī)勃勃。我們相信備受社區(qū)關(guān)注的技術(shù),許多顧慮的問題終究會(huì)有解決方案的。
基于 Container 的 Web Terminal一個(gè)完整的 IDE 需要具備很多功能,文件管理,版本管理,編輯器(語法高亮,自動(dòng)補(bǔ)全),編譯器,執(zhí)行環(huán)境等等。Rome was not built in a day。初次上線的最小功能集合里,我們認(rèn)為 Web IDE 區(qū)別于 Web Editor 的一個(gè)功能亮點(diǎn)就是 Web Terminal。
Web Terminal 和 SSH 的工作原理類似,通過架設(shè)在 TCP 之上的應(yīng)用層協(xié)議實(shí)現(xiàn)對主機(jī)的遠(yuǎn)程控制。相信大多數(shù)開發(fā)者都有 SSH 的使用經(jīng)驗(yàn),理解其工作原理的僅占少數(shù)。開始研究之初,我們也和大多數(shù)人一樣搞不清楚terminal, tty, pty, shell, bash 之間的區(qū)別,所以先來理理概念。
什么是 Terminal?從用戶的角度來看,Terminal 是鍵盤和顯示器的組合,也稱為TTY(TeleTYpewriter,電傳打字機(jī)的縮寫)。鍵盤輸入字符,顯示器顯示字符。從進(jìn)程的角度來看,終端是字符設(shè)備,可以通過 read,write,ioctrl 等系統(tǒng)調(diào)用來讀寫和控制該設(shè)備。
TTY 早已進(jìn)入了博物館,桌面系統(tǒng)上字符界面基本被 GUI 界面替代。取而代之是一個(gè)稱之為 Terminal Emulator(終端模擬器)的窗口程序,該程序顯示的字符界面就是曾經(jīng)物理顯示器里的完整內(nèi)容。
Terminal 作為真實(shí)的物理設(shè)備已經(jīng)不復(fù)存在了,但是為了和面向終端的程序(比如 Bash)進(jìn)行通信,于是就了發(fā)明了 pty(Pseudoterminal,偽終端)。pty 是一對 master-slave 設(shè)備,master 設(shè)備表現(xiàn)得像一個(gè)文件,slave 設(shè)備表現(xiàn)得像一個(gè)終端設(shè)備,當(dāng) Terminal Emulator 作為一個(gè)非面向終端的程序不直接與 pty slave 通訊,而是通過文件讀寫流與 pty master 通訊,pty master 再將字符輸入經(jīng)過線路規(guī)程的轉(zhuǎn)換傳送給 slave ,slave 進(jìn)一步傳遞給 bash。
Bash 一個(gè)命令行的解釋器,通常也是進(jìn)程會(huì)話的主進(jìn)程,其職責(zé)是解釋執(zhí)行終端設(shè)備(或者偽終端的 slave 設(shè)備)傳遞過來的字符串和控制字符,執(zhí)行命令。
Web Terminal 的工作原理理解了上面背景知識(shí)之后,再看 SSH 的原理圖。
SSH 是一個(gè)典型的 server-client 模式架構(gòu),用戶通過終端將字符流傳遞給SSH client。SSH client 和 SSH server 之間通過 TCP/IP 協(xié)議進(jìn)行通訊。遠(yuǎn)端的 server 創(chuàng)建一對 pty,并且 fork+exec 一個(gè) bash 進(jìn)程,server 進(jìn)程通過 pty 對與 bash 進(jìn)行交互。
仿照 SSH 的工作原理,我們在 HTTP 協(xié)議之上設(shè)計(jì)了 Web Terminal,見下圖
真實(shí)實(shí)現(xiàn)中,socket.io 是應(yīng)用層的通訊協(xié)議。Terminal Emulator 是一個(gè)純JS的實(shí)現(xiàn),nodejs 后端使用 pty.js 模塊來創(chuàng)建 pty 對。
當(dāng)解決了 Web Terminal 的整體架構(gòu)以后,嵌入 Docker Container 已是水到渠成。
僵尸進(jìn)程問題我們知道 Docker 由于缺少 init 0 而導(dǎo)致僵尸進(jìn)程無法回收的問題迄今存在。Terminal 作為控制終端,會(huì)在使用過程中執(zhí)行若干命令,這些命令對應(yīng)進(jìn)程如果與其父進(jìn)程脫離父子關(guān)系,那僵尸進(jìn)程問題就來了。
Docker 官方推薦的一個(gè) Container 只跑一個(gè)進(jìn)程。如果 Container 與進(jìn)程同生共死,僵尸進(jìn)程的問題基本不會(huì)遇到。但是 Web Terminal 所在 Container 里啟動(dòng)了bash,而 bash 可以隨意執(zhí)行命令啟動(dòng)進(jìn)程,僵尸進(jìn)程問題很難避免。好在社區(qū)提供了更好的解決方案:phusion/baseimage。在Dockerfile里將的 FROM ubuntu改為FROM phusion/baseimage,再按照文檔說明做些調(diào)整基本就好了。
Container 作為構(gòu)建和管理工具通常,我們都是把 App 部署到 Docker 里去。大致步驟就是編寫 Dockerfile ,再構(gòu)建成 image,然后借助 private registry 在分布式的集群中分發(fā)。由于開發(fā)環(huán)境、測試環(huán)境和生產(chǎn)環(huán)境存在差異,往往構(gòu)建交付物涉及到大量參數(shù)和環(huán)境變量的設(shè)定,過程非常繁瑣,一般都會(huì)腳本化。所以IDE項(xiàng)目基本都是 Dockerfile 旁邊放置了一個(gè) Gemfile 和 Rakefile。通過 Ruby Rake 來驅(qū)動(dòng)整個(gè)構(gòu)建過程。
作為腳本語言與 Shell 相比,Ruby 的好處是
隔絕了 Darwin,Linux 平臺(tái)之間某些命令的細(xì)微差異;
對于 Shell 擅長的部分,可以通過"`"符號(hào)方便的嵌入調(diào)用;
具備完備正則等字符串處理功能;
方便調(diào)用 Docker api 的
可以集成 Capistrano 等分布式管理工具
但 Ruby 不像 Shell 那樣信手拈來,需要進(jìn)行適當(dāng)?shù)呐渲?,比如,RVM 安裝指定版本,修改 gem source 之類的。
從前配置這些基礎(chǔ)環(huán)境,都是記錄成 Markdown 文檔,一堆 apt-get,sed 指令。但是引入 Docker 以后,有更好的選擇。
我們的方式如下:
編寫一個(gè)配置構(gòu)建環(huán)境的 Dockerfile,構(gòu)建成 image。
docker build --rm -t="ide-docker-registry.coding.local/ide-builder:0.0.5" .
push 到 registry 里。
docker push ide-docker-registry.coding.local/ide-builder
在構(gòu)建服務(wù)器創(chuàng)建構(gòu)建所需的builder,通過mount外部目錄的方式,構(gòu)建環(huán)境和外部環(huán)境交互文件。
docker run --name coding_ide_builder -d -t -v $CODING_IDE_HOME:/data/coding-ide-home --net=host --restart=always ide-docker-registry.coding.local/ide-builder
進(jìn)入構(gòu)建環(huán)境執(zhí)行命令。
docker exec -i -t coding_ide_builder bash
或者直接構(gòu)建。
docker exec -i -t coding_ide_builder rakeContainer 環(huán)境的資源限制問題
資源限制主要針對CPU、內(nèi)存、磁盤和網(wǎng)絡(luò)帶寬等共享資源的限制。一方面,我們提倡共享,事實(shí)上不是所有的用戶都需要長時(shí)間的占滿所需的資源配額,不需要的時(shí)候可以釋放出來分享給其他用戶,因?yàn)楣蚕聿艜?huì)更便宜。另一方面,也需要對可共享資源設(shè)定一個(gè)最大的限制配額,以防止某些用戶過度占用而影響其他用戶的使用體驗(yàn)。
CPU 限制Docker 提供了兩個(gè)參數(shù)來控制 cpu 的分配策略,--cpuset 和 --cpu-shares 。
--cpuset="0" [...] 將Container限定于某幾個(gè)CPU核心上。針對這一特性,我們制定的策略是將重要的 Container 服務(wù)分配在獨(dú)立的核心上,以保證服務(wù)的質(zhì)量。
--cpu-shares 可以調(diào)節(jié)Container獲得的時(shí)間片。我們通過這個(gè)配置來調(diào)節(jié) Web Terminal 所創(chuàng)建進(jìn)程對CPU的占用率。
內(nèi)存限制Web Terminal 里用戶的自由度是很大的,對內(nèi)存限制可以減少惡意破壞。Docker 配置內(nèi)存限制相對簡單。另外,我們禁用了swap分區(qū),以減少對磁盤的壓力。
磁盤限制由于用戶可以完全自由的訪問磁盤,我們最希望 Container 磁盤鏡像文件具備 thin provisioning 特性,不需要預(yù)分配所有空間也可以限定其大小。
對于 Container 的磁盤限制分為兩部分,對最上層可寫 layer 的限制和對被 mount 的可寫目錄的限制。
Docker Daemon 提供了四種 storage-driver: aufs, devicemapper, btrfs, overlay。aufs 在其被支持的 linux 發(fā)行版上,是默認(rèn)的 storage-driver。否則 Docker 會(huì)啟用 devicemapper。aufs 最早被 Docker 支持,而且支持共享二級(jí)制文件和動(dòng)態(tài)庫文件所占用的內(nèi)存,btrfs 和 overlay 不支持此特性,但是比aufs速度更快。devicemapper 的特點(diǎn)是支持 thin provisioning 和 copy on write。
限制 layer 的大小,devicemapper 是目前唯一的選擇。啟動(dòng) devicemapper 后,Docker 會(huì)為所有的 Container 創(chuàng)建一個(gè)共享存儲(chǔ)池,其實(shí)質(zhì)上是一個(gè)大文件,另外也會(huì)限定每個(gè) Container 的大小。這兩個(gè)數(shù)字的制定需要慎重,因?yàn)榭紤]到數(shù)據(jù)遷移,修改很不容易。
Docker run 的時(shí)候 mount 進(jìn) Container 的可寫目錄是不受 devicemapper 的限制,所以需要額外處理。WebIDE 場景中 workspace 目錄是被多個(gè) Container 實(shí)例中共享讀寫的,作為用戶工作目錄,需要設(shè)定一個(gè)最大的空間限制。
談到 linux 磁盤空間限制,最先想到 quota。quota 常用于ftp服務(wù),限定用戶最大可用空間。但 quota 有一個(gè)技術(shù)限制,僅僅適用于整個(gè)文件系統(tǒng)而無法針對單個(gè)目錄。所以 quota 方案在共享目錄的場景不可行。
linux 支持將一個(gè)磁盤鏡像文件 mount 成目錄,磁盤鏡像文件可以限定大小。當(dāng)鏡像文件撐滿的時(shí)候,目錄就不可寫了。這是我們目前找到最靠譜的方案。
限制網(wǎng)絡(luò)帶寬Docker 沒有直接提供限制網(wǎng)絡(luò)帶寬的命令行參數(shù),但借助 Docker 的底層技術(shù) cgroup 可以實(shí)現(xiàn)。創(chuàng)建一個(gè) Network classifier group,對 cgroup 進(jìn)行帶寬限制的設(shè)定,將 Container 都指定到該組里去。Traffic Controller(tc) 和 Netfilter(iptables) 都支持針對 cgroup 指定規(guī)則。
關(guān)于 Dockerize 的程度與思考base 在 Docker 之上,更容易實(shí)現(xiàn)架構(gòu)的微服務(wù)化。借助于 Docker 的 link 特性和 fig 工具,Container 可以像樂高積木一樣把所有的組件都組合起來。Nginx,Jetty,MySQL,Redis 等一系列服務(wù)可以封裝到獨(dú)立的Container 里去。
全面 Dockerize 的最大好處是整個(gè)體系都是一致的,所有的組件都是Container。WebIDE 在架構(gòu)初期,考慮全面 Dockerize 的方案,比如把 MySQL 分成兩個(gè) Container ,一個(gè)存放安裝文件,另一個(gè)存放數(shù)據(jù)文件。應(yīng)用服務(wù)器自不必說也在 Container 里。但是當(dāng)考慮 Nginx 是否也要放進(jìn) Container 里,大家想法有些分歧,Container 的好處在 Nginx 上是否明顯值得探討。也正因?yàn)榇嬖诓煌穆曇?,我們放棄了全?Dockerize。個(gè)人的覺得已有的經(jīng)驗(yàn)和腳本不應(yīng)該放棄,節(jié)省出更多的精力來做更重要和緊迫的事情。
參考閱讀Hypervisor - Wikipedia
Operating-system-level virtualization - Wikipedia
User space - Wikipedia
Basics – Docker, Containers, Hypervisors, CoreOS
devicemapper - a storage backend based on Device Mapper
Resizing Docker Containers with the Device Mapper plugin
Network classifier cgroup
Vangie Du將來的你,一定會(huì)感謝現(xiàn)在拼命努力的自己!
本文出自 Coding 官方技術(shù)博客,如需轉(zhuǎn)載請注明作者與出處。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/26424.html
摘要:啟動(dòng)后在瀏覽器中導(dǎo)航到。這時(shí)清空一下瀏覽器緩存再運(yùn)行就可以了。當(dāng)然我們也看到,目前在瀏覽器中運(yùn)行仍然存在一些有待解決的技術(shù)問題,因此還不適合廣泛采用。 摘要: WEB IDE新時(shí)代! 作者:SHUHARI 的博客 原文:有趣的項(xiàng)目 - 在瀏覽器中運(yùn)行 Visual Studio Code Fundebug按照原文要求轉(zhuǎn)載,版權(quán)歸原作者所有。 眾所周知,Visual Studio...
摘要:剛才聽了謝樂冰的演講我覺得很多東西和我們的思路非常像,從我回國到現(xiàn)在大概有一年多的時(shí)間。在看來,一個(gè)業(yè)務(wù)應(yīng)用應(yīng)該是分層的,每一層都是一個(gè)所謂的服務(wù),剛才謝樂冰講的所謂服務(wù)化和異步化,不會(huì)把這些東西從前到頭攪在一起,這樣非常難以擴(kuò)展。 本文是數(shù)人云深圳技術(shù)分享課上Coding CTO 孫宇聰?shù)难葜v實(shí)錄,小數(shù)帶你走近這位詼諧幽默的大牛,領(lǐng)略他深入的見解和豐富的實(shí)踐經(jīng)驗(yàn)。 非常感謝今天有這個(gè)...
摘要:一直是我掛在嘴邊的話題。今年月也曾展望過,那時(shí)候是考慮用高版本的來重構(gòu),然后逐步遷移到上面去,然而最大的問題還是沒人,沒時(shí)間的問題。關(guān)于作者彭博前端工程師新的體驗(yàn)總是好的原文鏈接 Coding 2.0 一直是我掛在嘴邊的話題。 老板說了,等我們有錢,有人,有時(shí)間了就有機(jī)會(huì)弄了。 但是我從他第一次說就沒當(dāng)真,這種 有錢,有人,有時(shí)間 的情況,在創(chuàng)業(yè)公司里應(yīng)該是不太可能出現(xiàn)的。 今年...
摘要:訪問在里進(jìn)行項(xiàng)目操作選擇完畢的項(xiàng)目,點(diǎn)擊選擇在項(xiàng)目根目錄下添加一個(gè)文件之后即可成功運(yùn)行的源代碼要獲取更多的原創(chuàng)技術(shù)文章,請關(guān)注公眾號(hào)汪子熙 (1) 訪問Web IDE url 在Web IDE里進(jìn)行項(xiàng)目clone操作: https://:8080/#/admin/projects/fnf/customer/cus.crm.opportunity showImg(https://segm...
摘要:訪問在里進(jìn)行項(xiàng)目操作選擇完畢的項(xiàng)目,點(diǎn)擊選擇在項(xiàng)目根目錄下添加一個(gè)文件之后即可成功運(yùn)行的源代碼要獲取更多的原創(chuàng)技術(shù)文章,請關(guān)注公眾號(hào)汪子熙 (1) 訪問Web IDE url 在Web IDE里進(jìn)行項(xiàng)目clone操作: https://:8080/#/admin/projects/fnf/customer/cus.crm.opportunity showImg(https://segm...
閱讀 2059·2023-04-25 17:48
閱讀 3577·2021-09-22 15:37
閱讀 2931·2021-09-22 15:36
閱讀 5860·2021-09-22 15:06
閱讀 1634·2019-08-30 15:53
閱讀 1422·2019-08-30 15:52
閱讀 706·2019-08-30 13:48
閱讀 1115·2019-08-30 12:44