React搭建我的博客(二)consul-template+nginx+docker實現負載均衡

一.簡介

上一篇只講了博客的前端問題,這一篇講一下後端的微服務搭建。項目的後端使用的thinkjs框架,在我以前的博客中已經寫過,這裏就不重點說明了。
後端項目分爲三個:html

  1. 博客前臺頁面服務端:在這裏
  2. 博客後臺頁面服務端:在這裏
  3. consul-template+nginx實現的基於微服務註冊發現的負載均衡:在這裏

前兩個數據業務相關的服務即下圖的service_web,第三個項目就是consul-template+nginx的實現的負載均衡。
若是對consul基礎概念不瞭解,建議讀完我博客裏這兩篇文章再繼續看下面的內容。
consul+docker實現服務註冊
consul+docker實現服務發現及網關
首先看下架構圖:
在這裏插入圖片描述前端

架構圖解析

consul-template會訂閱consul註冊中心上的服務消息,當service-web改變時,consul註冊中心會將新的service web信息推送給consul-template,consul-template會修改nginx配置文件,nginx重載入配置後,就達到了能夠自動修改更新的負載均衡。react

二.consul-template+nginx實現基於微服務的負載均衡

consul-template 介紹

Consul-Template是基於Consul的自動替換配置文件的應用。在Consul-Template沒出現以前,你們構建服務發現系統大多采用的是Zookeeper、Etcd+Confd這樣相似的系統。linux

使用場景:能夠查詢Consul中的服務目錄、Key、Key-values等。這種強大的抽象功能和查詢語言模板可使Consul-Template特別適合動態的建立配置文件。例如:建立Apache/Nginx Proxy Balancers、Haproxy Backends、Varnish Servers、Application Configurations等。nginx

代碼介紹

當consul註冊中心的的服務改變時,consul-template會根據nginx-consul-template從新生成nginx.conf。首先看一下nginx.conf.ctmpl的代碼:git

nginx.conf.ctmpl
upstream admin {
  {{range service "service-admin"}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;
  {{else}}server 127.0.0.1:65535; # force a 502{{end}}
}
upstream app {
  {{range service "service-web"}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;
  {{else}}server 127.0.0.1:65535; # force a 502{{end}}
}

server {
  listen 80 default_server;
# 映射博客後臺管理服務
  location  /admin{
    proxy_pass http://admin/;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
   #請求博客後臺服務的靜態資源 
   location  ^~/static/blog-backend-react{
    proxy_pass http://admin/static/blog-backend-react;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
 #請求博客前臺服務的靜態資源 
location  ^~/static/blog-react{
    proxy_pass http://app/static/blog-react;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
 # 接口請求,映射博客前臺服務
  location  /font{
    proxy_pass http://app;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
  # 接口請求,映射博客後臺服務
  location  /api{
    proxy_pass http://admin/api;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
  # 默認映射到博客前端服務
    location  / {
    proxy_pass http://app;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}

template與正常nginx.conf區別就是upstream裏部分,根據服務名——這裏是兩個服務,self-blog-backend博客後臺管理服務與self-blog-fontend博客前臺服務——動態生成服務對應的ip。
template的反向代理部分,與正常nginx配置一致,由於有兩個項目,因此每一個url請求接口,靜態資源,服務,都須要映射到特定的服務。
服務啓動後,根據模版生成的nginx配置文件以下:github

upstream admin {
  server 172.25.0.7:8362 max_fails=3 fail_timeout=60 weight=1;
  server 172.25.0.8:8362 max_fails=3 fail_timeout=60 weight=1;
   server 172.25.0.11:8362 max_fails=3 fail_timeout=60 weight=1;
}
upstream app {
  server 172.25.0.4:8365 max_fails=3 fail_timeout=60 weight=1;
  server 172.25.0.9:8365 max_fails=3 fail_timeout=60 weight=1;
  server 172.25.0.10:8365 max_fails=3 fail_timeout=60 weight=1;
}

server {
 ....
}

能夠看到,upstream裏,根據服務名已經找到了對應的ip。這裏後臺,前臺項目各啓動了三個實例,用戶訪問的時候,就會根據配置的nginx負載均衡的策略,訪問其中一個ip。web

nginx.service

用於啓動nginx服務docker

#!/bin/sh
# 啓動nginx
# daemon off 關閉守衛進程,保證nginx前臺運行
nginx -c /etc/nginx/nginx.conf -t && \
  nginx -c /etc/nginx/nginx.conf -g "daemon off;"
consul.template.service

用於啓動consul-templatebootstrap

#!/bin/sh
# 啓動consul-template,指定consul地址
# consul變化後,根據模板 nginx.conf ,生成nigix配置文件並reload
exec consul-template \
     -consul-addr=consul:8500 \
     -template "/etc/consul-templates/nginx.conf:/etc/nginx/conf.d/app.conf:nginx -s reload"
Dockerfile

由於整個負載均衡服務須要作成鏡像,與其餘服務一塊兒部署,因此這裏須要維護Dockerfile

FROM nginx
 # 聲明告訴系統,無需向用戶請求輸入(非交互式)
RUN DEBIAN_FRONTEND=noninteractive \
    # 更新軟件包列表
    apt-get update -qq && \
    # 安裝 curl runit
    apt-get -y install curl runit && \
    # rm 刪除,-r 所有刪除子目錄, -f 強制刪除
    rm -rf /var/lib/apt/lists/*

ADD consul-template_0.19.4_linux_amd64.tgz /usr/local/bin/
# 將 nginx.service 放到指定文件夾,生成run文件
ADD nginx.service /etc/service/nginx/run
# 給全部人添加文件的可執行權限
RUN chmod a+x /etc/service/nginx/run
ADD consul-template.service /etc/service/consul-template/run
RUN chmod a+x /etc/service/consul-template/run

RUN rm -v /etc/nginx/conf.d/*
ADD nginx.conf /etc/consul-templates/nginx.conf
# 使用runit ,當 runsvdir在/etc/service/目錄中發現新的配置時,
# 啓動runsv進程來執行和監控/etc/service下的run腳本
CMD ["/usr/bin/runsvdir", "/etc/service"]

維護好以後,就能夠製做本身的nginx-consul-template鏡像了。

docker-compose.yml

博客後臺與前臺服務端項目github上,都有本身的Dockerfile,將他們作成鏡像後,與nginx-consul-template鏡像一塊兒,經過docker-compose統一部署這幾個服務。

version: "2.0"
services:
    consulserver:
        image: progrium/consul:latest
        hostname: consulserver
        ports:
            - "8300"
            - "8400"
            - 8500:8500
            - "53"
        command: -server -ui-dir /ui -data-dir /tmp/consul --bootstrap-expect=3
    consulserver1:
        image: progrium/consul:latest
        hostname: consulserver1
        depends_on:
            - consulserver
        ports:
            - "8300"
            - "8400"
            - "8500"
            - "53"
        command: -server -data-dir /tmp/consul -join consulserver
    consulserver2:
        image: progrium/consul:latest
        hostname: consulserver2
        depends_on:
            - consulserver
        ports:
            - "8300"
            - "8400"
            - "8500"
            - "53"
        command: -server -data-dir /tmp/consul -join consulserver
    registrator:
        image: gliderlabs/registrator:master
        hostname: registrator
        depends_on:
            - consulserver
        volumes:
            - /var/run/docker.sock:/tmp/docker.sock
        command: -internal consul://consulserver:8500
    serviceadmin1:
        image: daocloud.io/sunxing102005/self-blog-backend:latest
        depends_on:
            - consulserver
        environment:
            SERVICE_8362_NAME: service-admin
        ports:
            - 3002:3002
            - "8362"
    serviceweb1:
        image: daocloud.io/sunxing102005/self-blog-fontend:latest
        depends_on:
            - consulserver
        environment:
            SERVICE_8365_NAME: service-web
        ports:
            - 3005:3005
            - "8365"
    lb:
        image: daocloud.io/sunxing102005/consul-template-nginx-blog:latest
        hostname: lb
        links:
            - consulserver:consul
        ports:
            - 80:80

運行命令,啓動服務

docker-compose up -d

運行後,就能夠從註冊中心看到consul上註冊的服務:
在這裏插入圖片描述
其中consul-template-nginx-blog就是lb,service-admin,service-web分別是博客的前臺,後臺服務(3002,3005兩個服務是留給prometheus抓數據用的,不用在乎)由於這裏各只啓動了一個實例,因此他們每一個只有一個服務。下面看下nginx的效果
在這裏插入圖片描述
訪問默認80端口,直接訪問博客前端服務
在這裏插入圖片描述
訪問80端口加上admin後綴,就會跳到博客管理網站。

三.開發筆記

這裏放一些開發過程當中,本身記錄的一些問題和知識點。

如何進入docker容器查看consul-template生成的nginx.conf

docker ps                                  //查看consul-template-nginx容器id
docker exec -it exec 22fff6c360f1 /bin/sh // 進入容器
cat /etc/nginx/conf.d/app.conf           //查看文件

docker運行nginx爲何要執行daemon off

docker容器後臺運行時,前臺必須有一個前臺進程。
容器運行的命令,若是不是一直掛起的就會自動退出。
nginx是後臺進程模式運行,致使沒有前臺運行的應用,他就會當即退出應用。
解決方法:

  1. 將你要運行的容器之前臺形式運行,關閉守衛進程

    nginx -g " daemon off"
  2. 添加tail,top這種能夠前臺運行的程序,推薦使用tail,而後持續輸出log

    service nginx start && tail -f /var/log/nginx/error.log

nginx.conf.ctmpl注意事項

upstream admin {
  {{range service "service-admin"}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;
  {{else}}server 127.0.0.1:65535; # force a 502{{end}}
}
upstream app {
  {{range service "service-web"}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;
  {{else}}server 127.0.0.1:65535; # force a 502{{end}}
}

server {
  listen 80 default_server;

  location  /admin{
    proxy_pass http://admin/;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }

location匹配的若是不是/ ,若是想跳轉到這個服務的根目錄,裏面proxy_pass定義的url,後面要加上/,好比這裏匹配的 /admin,
proxy_pass是http://admin/,若是是http://admin,則反向代理的路徑是http://XXXX:8362/admin,而不是8362服務的跟路徑http://XXXX:8362。

nginx經常使用命令

nginx 服務器重啓命令,關閉
nginx -s reload :修改配置後從新加載生效
nginx -s reopen :從新打開日誌文件
nginx -t -c /path/to/nginx.conf 測試nginx配置文件是否正確

關閉nginx:
nginx -s stop :快速中止nginx
quit :完整有序的中止nginx

其餘的中止nginx 方式:

ps -ef | grep nginx

kill -QUIT 主進程號 :從容中止Nginx
kill -TERM 主進程號 :快速中止Nginx
pkill -9 nginx :強制中止Nginx

 

啓動nginx:
nginx -c /path/to/nginx.conf

平滑重啓nginx:
kill -HUP 主進程號

nginx 反向代理加req header

前端每次請求,都token放到了request header裏。以前header裏設置的字段叫access_token,傳不過去,發現nginx反向代理時,會忽略帶下劃線的header,因此改爲了accesstoken。

docker經常使用命令

啓動        systemctl start docker
守護進程重啓   sudo systemctl daemon-reload
重啓docker服務   systemctl restart  docker
重啓docker服務  sudo service docker restart
關閉docker   service docker stop   
關閉docker  systemctl stop docker

docker 批量刪除容器

docker rm `docker ps -a -q` //刪除全部容器
docker rmi `docker images -q` //刪除全部鏡像

//按條件刪除鏡像
    //沒有打標籤
docker rmi `docker images -q | awk '/^<none>/ {print $3}'`
    //鏡像關鍵字
docker rmi `docker images | grep doss api | awk 'print $3'`

linx chmod 命令

  • 若是給全部人添加可執行權限:chmod a+x 文件名
  • 若是給文件全部者添加可執行權限:chmod u+x 文件名
  • 若是給所在組添加可執行權限:chmod g+x 文件名
  • 若是給所在組之外的人添加可執行權限:chmod o+x 文件名
  • 詳細chmod命令,可參考這裏

linx service服務管理

經過ubuntu自帶service,能夠很方便建立後臺運行程序。
service文件路徑:/lib/systemd/ystem
service文件包含多個部分,下面是簡單的後臺運行的service文件。
在這裏插入圖片描述
啓動服務

service leshan-erver start

中止服務

service leshan-erver stop

查看服務狀態

systemctl status lenshan-server

從新加載service文件

systemctl daemon-reload

四.總結

本篇主要講解consul-template+nginx的負載均衡的實現,網上相似的講解有不少,consul+nginx+consul-template構建簡單微服務也是很基礎經常使用的方案。這一部分與以前我轉發的consul+docker實現服務發現及網關其實也只是差了個網關和負載均衡。稍微值得注意的是,本項目裏,用到了兩個業務層面的服務——博客前臺與後臺兩個服務——而不是單體項目,稍微有點微服務的感受了,把大項目拆開管理。因此nginx這部分就須要分別反向代理到兩個項目裏,這裏請求接口,靜態什麼的,兩個服務要有區分,讓nginx有代理區分的標準。
至此博客的前端,後端微服務搭建都講完了,有空的話下一篇講一下daocloud平臺部署和prometheus+grafana的監控系統。

五.參考

https://www.jianshu.com/p/a4c...
http://blog.zongwu233.com/Con...

相關文章
相關標籤/搜索