1、Hadoop HA的Web頁面訪問html
Hadoop開啓HA後,會同時存在兩個Master組件提供服務,其中正在使用的組件稱爲Active,另外一個做爲備份稱爲Standby,例如HDFS的NameNode、YARN 的ResourceManager。HDFS的web頁面只有經過Active的NameNode才能正常訪問,一樣地,YARN的web頁面也只有經過Active的ResouceManager才能正常訪問。node
(1) HDFS HA的Web訪問nginx
正常使用Nginx的proxy_pass代理單一的Web服務地址時很是簡單(參考博文最簡反向代理配置),而面對Hadoop HA這樣的多Web服務地址時就會有點麻煩。git
(2) HDFS HA的Web代理github
雖然Nginx的upstream支持配置多個Web地址,默認會隨機將Web請求隨機轉發到任意一個Web地址,只有某個web地址被認爲不可達後,纔會被Nginx列入黑名單。而Hadoop HA的Active和Standby節點都是一直服務的,只是同一個時刻,最多隻有一個節點的Web訪問是有效的,這就要求Nginx對upstream中的Web地址更細緻地檢查,而非粗略地判斷是否可達。web
2、Nginx的upstream健康檢查dom
對upstream的地址有效性檢查稱爲健康檢查。經過按期的調用檢查邏輯,對upstream配置的Web地址進行標記,不健康的Web地址會被臨時列入黑名單內,直到該地址被標記爲健康狀態時,纔會有新的Web請求轉發到該地址上。socket
(1)Nginx自己對upstream的健康檢查支持並不強大,作不到對檢查邏輯的自由定製。oop
(2)開源項目nginx_upstream_check_module以Nginx補丁的方式擴展了Nginx的upstream語法,支持自定義HTTP請求的方式檢查Web服務的健康狀態。但在實際使用過程當中,遇到一個很不方便的地方。測試
upstream resourcemanagers { server 192.168.0.1:8084; server 192.168.0.2:8084; check interval=30000 rise=1 fall=3 timeout=5000 type=http; check_http_send "HEAD / HTTP/1.0\r\n\r\n"; check_http_expect_alive http_3xx; keepalive 2000; }
nginx_upstream_check_module使用check命令定義健康檢查的基本屬性,使用check_http_send自定義HTTP請求,check_http_expect_alive定義指望的健康狀態HTTP code。這裏使用http_3xx是該模塊定義的內置匹配語法,表示以3開頭的HTTP code。想必你們已經想到,這種定義方式是沒法精確區分30一、30二、307報文的。固然正常狀況下,3xx的報文應該是同類型的報文,不須要如此精確的區分,可是不巧的是Hadoop2.7.2版本的Active ResourceManager和Standby ResourceManager分別返回的是302和307報文!
(3)以上兩種方案並非解決Nginx upstream健康檢查的完美方案,真正完美的方案是OpenResty的lua-resty-upstream-healthcheck。OpenResty內置了大量的Lua庫,能夠自由擴展、定製Nginx的功能。其中healthcheck.lua模塊用於upstream的健康檢查。
不過我但願在Nginx的基礎上只擴展upstream健康檢查的功能,而非用OpenResty代替Nginx,所以須要使用Nginx的lua-upstream-nginx-module模塊。
3、編譯安裝擴展Nginx
(1)因爲lua-upstream-nginx-module是使用Lua腳本對Nginx進行擴展,所以必須安裝Lua解釋器。LuaJIT是Lua語言的即時編譯器,效率更高。
$ wget http://luajit.org/download/LuaJIT-2.0.4.tar.gz $ tar zxvf LuaJIT-2.0.4.tar.gz $ cd LuaJIT-2.0.4 $ make $ make install $ export LUAJIT_LIB=/usr/local/lib $ export LUAJIT_INC=/usr/local/include/luajit-2.0 $ rm /usr/local/lib/libluajit-5.1.so* $ cd ..
導出環境變量LUAJIT_LIB和LUAJIT_INC是爲了後續編譯lua-nginx-module模塊使用。刪除libluajit的全部動態連接庫是爲了保證後續編譯時是靜態連接,不然默認爲動態連接。
(2)準備好Lua環境後,接下來下載Nginx的Lua模塊lua-nginx-module、Nginx開發包ngx_devel_kit、Nginx upstreamLua模塊lua-upstream-nginx-module、pcre庫和openssl庫、Nginx源碼。解壓後的文件列表以下:
./lua-nginx-module-0.10.5 ./lua-upstream-nginx-module-0.05 ./nginx-1.10.1 ./ngx_devel_kit-0.3.0 ./openssl-OpenSSL_1_0_1t ./pcre-8.38
執行命令編譯Nginx:
$ cd nginx-1.10.1 $ ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=root --group=root --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-threads --with-stream --with-stream_ssl_module --with-http_slice_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_v2_module --with-http_v2_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' --with-pcre=../pcre-8.38 --with-openssl=../openssl-OpenSSL_1_0_1t --add-module=../ngx_devel_kit-0.3.0 --add-module=../lua-nginx-module-0.10.5 --add-module=../lua-upstream-nginx-module-0.05 $ make && make install
(3) 安裝完畢後,Nginx的配置文件爲/etc/nginx/nginx.conf,可執行文件爲/usr/sbin/nginx。執行Nginx啓動命令:
$ nginx
訪問http://127.0.0.1:8080便可看到Nginx主頁。
(4) 添加Lua測試連接,測試Lua模塊是否正常工做。
location /lua { set $test "hello, world."; content_by_lua ' ngx.header.content_type = "text/plain"; ngx.say(ngx.var.test); '; }
更新Nginx配置:
$ nginx -s reload
訪問http://127.0.0.1:8080/lua便可看到」hello,world.」。
4、Nginx代理Hadoop HA
(3) Nginx代理Hadoop HA
雖然安裝了lua-upstream-nginx-module模塊,可是仍須要使用OpenResty的healthcheck.lua模塊才能完成upstream的健康檢查功能。
(1) 下載最新版本的OpenResty代碼。執行以下命令:
make && make install ls /usr/local/openresty/lualib/resty/upstream/healthcheck.lua
其中healthcheck.lua腳本就是咱們須要的健康檢查模塊。
(2) 配置nginx.conf:
# upstream upstream resourcemanagers { server 192.168.0.1:8084; server 192.168.0.2:8084; keepalive 2000; } upstream namenodes { server 192.168.0.1:50070; server 192.168.0.2:50070; keepalive 2000; } # health check lua_package_path "/usr/local/openresty/lualib/?.lua;;"; lua_shared_dict healthcheck 1m; lua_socket_log_errors off; init_worker_by_lua_block { local hc = require "resty.upstream.healthcheck" local ok, err = hc.spawn_checker { shm = "healthcheck", upstream = "resourcemanagers ", type = "http", http_req = "GET / HTTP/1.0\r\n\r\n", interval = 2000, timeout = 5000, fall = 3, rise = 2, valid_statuses = {302}, concurrency = 1, } if not ok then ngx.log(ngx.ERR, "=======> failed to spawn RM health checker: ", err) return end local ok, err = hc.spawn_checker { shm = "healthcheck", upstream = "namenodes ", type = "http", http_req = "GET /webhdfs/v1/?op=LISTSTATUS HTTP/1.0\r\n\r\n", interval = 2000, timeout = 5000, fall = 3, rise = 2, valid_statuses = {200}, concurrency = 1, } if not ok then ngx.log(ngx.ERR, "=======> failed to spawn NameNode health checker: ", err) return end } # proxy location /yarn/ { proxy_pass http://resourcemanagers/; # some sub_filter, rewrite config } location /hdfs/ { proxy_pass http://namenodes/; # some sub_filter, rewrite config }
更新Nginx配置:
$ nginx -s reload
訪問http://127.0.0.1:8080/hdfs或http://127.0.0.1:8080/yarn便可看到HDFS或YARN的Web頁面。
5、總結
綜上,使用Lua擴展Nginx的功能十分強大,且十分容易定製,這也是OpenResty的功能如此強大的緣由。雖然OpenResty已經提供了lua-resty-upstream-healthcheck模塊完成upstream的健康檢查功能,不過咱們仍在社區版的Nginx上親自擴展了該功能。但願這篇文章能幫助你們快速的配置Nginx+Lua的環境,並方便地開發本身的Nginx擴展功能。