主題:如何讓多個程序搭建在一個服務(wù)器上,搭建一個適合于架構(gòu)師使用的開發(fā)與實現(xiàn)環(huán)境(linux)
課程主要解決的編程中遇到的問題:
- 當(dāng)項目越來越大的時候,項目的設(shè)計越來越復(fù)雜,一個線上的項目往往可能會涉及到多種語言,比如php+node.js,ruby+node.js,java/python等
- 即使同一種語言從版本的升級語法上會有一些變化,甚至連程序設(shè)計思想與原則可能都會發(fā)生變化.
- 類似:python和ruby這兩個語言在linux運維中使用非常廣泛,很多自動化運維腳本都是用python2.x與ruby1.x編寫的,然而現(xiàn)在社區(qū)中活躍的新版本卻是python3.x與ruby2.x
那么本節(jié)課就是為了解決這些問題的...
當(dāng)然有這些問題也有相對成熟的解決方案
- 現(xiàn)在很多云計算廠商,利用虛擬化技術(shù),容器技術(shù),采用服務(wù)器化方式進(jìn)行開發(fā),比如現(xiàn)在流行的docker+微服務(wù)架構(gòu)就是其中的佼佼者.
- 要完成這種規(guī)模的商業(yè)項目架構(gòu)設(shè)計,架構(gòu)師經(jīng)常需要進(jìn)行程序的測試和驗證設(shè)計,可要在筆記本上完成這樣的部署,無論是利用虛擬化技術(shù)還是容器技術(shù),都顯得太笨重了,架構(gòu)師需要的是一個全能的開發(fā),部署與運維環(huán)境,環(huán)境需要與產(chǎn)品環(huán)境高度一致,而且還應(yīng)該更輕便,節(jié)省性能,方便管理
我們?nèi)绾巫屢慌_服務(wù)器同時支持多種的web服務(wù)器,比如如何同時讓我們的測試機(jī)上面能跑起php,nodejs,ruby on rails,如果有必要的話再加一個tomcat來跑jsp也是可以的
通常情況下,如果在一臺服務(wù)器上啟動多個http服務(wù),我們必須給這些服務(wù)分配不同的端口,否則就會端口沖突,然而標(biāo)準(zhǔn)的網(wǎng)頁服務(wù)走的是80端口,在瀏覽器中輸入一個網(wǎng)址,不指定端口那么默認(rèn)請求就會發(fā)送到80端口.
這樣說來,如果同時在多個端口開啟web服務(wù)器基本不需要做太多額外的事情,只要去各個服務(wù)器軟件中修改配置文件,把端口調(diào)整為其它大于1000且不重復(fù)的端口號,這樣web服務(wù)器就能跑起來了.
接著需要解決一個棘手的問題,通常我們設(shè)計的restfulAPI接口以及默認(rèn)的用戶訪問,都是直接把http請求發(fā)送至80端口的,80端口只有一個,自然是只能有一個程序去監(jiān)聽這個端口的,不過這個解決起來也簡單,之所以說簡單是因為很多http服務(wù)器程序都支持http代理功能.我們這里即將介紹利用nginx反向代理實現(xiàn)多個web服務(wù)器共享80端口:
具體實現(xiàn)步驟:
- 先讓nginx在80端口啟動,nginx啟動成功后再讓其他服務(wù)器在別的端口啟動服務(wù).為了保險起見,自己可以先測試下,各個服務(wù)在不同的端口是否正常工作.
- 然后我們就需要為各個服務(wù)創(chuàng)建虛擬主機(jī),由于多個服務(wù)跑在一臺機(jī)器上,所以為了能有所區(qū)分,我們得給這些服務(wù)分別綁定不同的域名,如果是在本機(jī)測試,域名綁定的工作可以選擇在自己筆記本的宿主機(jī)操作系統(tǒng)里面修改hosts文件.
這一步完成以后逻炊,我們在nginx的配置中增加虛擬主機(jī)配置贫贝,為了方便管理,每一個虛擬主機(jī)的配置最好是能有一個獨立的文件存放 - 虛擬主機(jī)反向代理配置:
server {
listen 80;
server_name test.ydma.cn;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxy true;
proxy_pass http://127.0.0.1:9001;
}
}
# 如果是在ubuntu中晨缴,這個文件應(yīng)該放在/etc/nginx/sites-available里面驹愚,然后再通過ln -s
# 做一個軟連接放在sites-enabled文件夾中
# 之所以nginx能找到這個配置文件是因為在nginx.conf主配置文件中有這么兩行配置
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
我們可以看到上面的配置文件中 由nginx監(jiān)聽主機(jī)名為 server_name test.ydma.cn 远搪,
端口號 listen 80;
location設(shè)置為 proxy_pass http://127.0.0.1:9001;
也就是說把訪問test.ydma.cn:80的請求交給127.0.0.1的9001端口去處理
proxy_set_header的配置是為了將http請求的頭部信息做相應(yīng)的改寫,如果沒有這些設(shè)置逢捺,轉(zhuǎn)發(fā)后的請求得到的請求信息就
是nginx服務(wù)的信息谁鳍,而不是外部用戶的信息
把這個文件復(fù)制幾分,只需要改寫server_name以及proxy_pass后的端口號劫瞳,那么我們就可以讓nodes 倘潜、ruby on rails 、apache志于、
等多個web服務(wù)同時共用80端口跑起來了窍荧。
多個web服務(wù)跑起來了,共用80端口了恨憎,這樣服務(wù)與服務(wù)之間就可以通過標(biāo)準(zhǔn)的http協(xié)議做webservice調(diào)用了
可現(xiàn)在還不是高興的時候蕊退,因為麻煩的還在后頭,在項目開發(fā)過程中憔恳,我們用到的各種工具和軟件瓤荔,通常會有依賴,比如hadoop钥组,我們以hadoop2.x為例输硝,它依賴jdk7,我們制作的一款機(jī)器學(xué)習(xí)軟件大量使用java函數(shù)式編程程梦,需要jdk8点把,那么我們怎么樣解決這個問題呢
通常解決方案
同時安裝兩個版本到不同路徑橘荠,比如/opt/java/jdk/1.7.x/目錄下安裝java7,/opt/java/jdk/1.8.x/下安裝java8郎逃,然后可以在linux中配置用戶級別環(huán)境變量JAVA_HOME哥童,通常環(huán)境變量應(yīng)該寫在文件 ~./bashrc 或者~/.bash_profile中,然后再修改系統(tǒng)的PATH變量,指向JAVA_HOME下的bin目錄褒翰,這樣我希望用戶默認(rèn)環(huán)境下是
java8那么我就把環(huán)境變量JAVA_HOME切換到j(luò)ava8的安裝目錄就可以了贮懈,這樣我們自己寫的機(jī)器學(xué)習(xí)工具就能在我的用戶權(quán)限下跑起來了。
如果我的機(jī)器學(xué)習(xí)程序需要訪問hadoop中的數(shù)據(jù)怎么辦优训?hadoop2.x需要的是jdk7朵你,而且要和我的java8程序一起在同一臺機(jī)器中使用。是不是依葫蘆畫瓢揣非,然后其它語言多版本的問題都可以這樣結(jié)局呢抡医?事情遠(yuǎn)遠(yuǎn)比我們想象中復(fù)雜,比如python早敬,我們?yōu)榱耸褂矛F(xiàn)在社區(qū)中一些新的python工具忌傻,必須把python升級到3.x版本,但操作系統(tǒng)中有些操作也需要python搁嗓,比如當(dāng)前ubuntu中用的是2.7,如果我們升級了python箱靴,系統(tǒng)的有些功能會無法正常使用腺逛。ruby情況與python類似,由于ruby項目高度活躍衡怀,我們很可能需要同時使用3個以上甚至更多的ruby版本在一個系統(tǒng)中棍矛,不止如此,還需要能靈活的管理我們的環(huán)境和版本抛杨。
更好的解決思路
有一個很好的設(shè)計思路能解決這個問題够委,無論你希望有多少個版本并存在操作系統(tǒng)且無沖突。
原理如下:
首先怖现,我們需要能把語言各個版本環(huán)境統(tǒng)一管理茁帽,也就是說把所有我們需要的版本都下載下來,集中存放
然后我們建立一個該語言環(huán)境的目錄加入PATH屈嗤,為語言環(huán)境以及bing中的命令建立替身潘拨,所有敲的命令以及執(zhí)行的腳本默認(rèn)都指向替身而不是命令本身,比如正常情況下如果敲python命令饶号,系統(tǒng)會去path中查找python文件铁追,然后執(zhí)行,由于通過path找到的python是替身而不是命令本身茫船,我們可以利用替身幫我們做一些事情琅束,我們可以指明某個文件夾必須使用某個版本的python扭屁,這樣替身接到命令調(diào)用時就會先判斷,這個文件夾是否有指明版本涩禀,如果有指定料滥,就再去調(diào)用指定版本的python去執(zhí)行命令,當(dāng)然如果沒有指定文件夾埋泵,那么python就判斷幔欧,當(dāng)前登陸的用戶有沒有指定python版本,如果沒有指定就再判斷丽声,有沒有指定默認(rèn)全局python版本礁蔗,這樣一來,我可以精確的去控制每一個文件夾雁社,每一個用戶浴井,以及整個操作系統(tǒng)應(yīng)該是用的python版本,
同樣的原理也適用于其它編程語言霉撵,而且也有這樣的開源項目來幫助我們做這樣的事情磺浙。
最早這樣管理環(huán)境的是ruby,ruby工程師發(fā)明了很多項目管理工具徒坡,早期的rvm就是管理版本環(huán)境與依賴的撕氧,功能比較強(qiáng)大,而另一個輕型解決方案叫做rbenv就是用我上面講的辦法來實現(xiàn)復(fù)雜的環(huán)境的管理.
由于有了rbenv這樣好用的工具管理ruby喇完,因此就有人利用rbenv進(jìn)行改造伦泥,誕生了pyenv來管理python,還有phpenv等等锦溪。
分享結(jié)束!