[原]OpenStreetMap數據瓦片服務性能篇

上文說到如何利用node-mapnik架設OpenStreetMap瓦片服務,解決了有沒有的問題。然而這個服務仍是比較孱弱,主要表如今如下幾個方面:php

1. Node.js只能使用CPU的一個核,不能有效發揮服務器的多核優點;html

2. 前端使用了一臺TileStrata服務器,即沒法實現負載均衡,也沒法實現服務主備冗餘;前端

3. 後端使用了一臺PostgreSQL,和前端同樣,沒法達到高性能和高可用性;node

4. 在Node.js和PostgreSQL之間沒有使用鏈接池,形成數據數性能低下;python

針對這些問題,本文將給出解決方案。然而「調優性能」的關鍵是「調」,本文只是給出思路和通常性方法,可能沒法真正在您的環境中能起到立竿見影的效果。針對具體的環境,可能須要採用具體的參數。接下來,我將從後端到前端來介紹。linux

1、PostgreSQL鏈接池

本文不打算提PostgreSQL性能調優,由於這一塊太大、太深奧,我自已也沒有什麼好的心得體會,就不耽誤你們了,接下來有工夫了我也要好好的學習下PostgreSQL性能調優技術。請你們自行Google,若是有好的方法記得留言分享哦:)git

當應用程序直接訪問PostgreSQL時,每次鏈接時PostgreSQL者會克隆出一個服務進程來爲應用程序服務,在關閉鏈接後,PostgreSQL將自動把服務進程停掉。頻繁的建立和銷燬進程,會大大消耗服務器資源。要解決這個問題,就要引入數據庫鏈接池,把鏈接緩存住,實現下降服務器資源消耗的目的。github

PostgreSQL有兩個知名的鏈接池: PgBouncer (官網)和 Pgpool-II (官網)。其中 PgBouncer比較單純,僅做數據庫鏈接池之用;而 Pgpool-II則功能較爲強大,除可用於鏈接池外,還能用於PostgreSQL服務複製、負載均衡以及並行查詢。然而貌似 Pgpool-II 在集羣中的服務和併發鏈接較少時效果並不顯著,甚至還要性能還要遠低於單機性能,因此這裏就不考慮使用 Pgpool-II  了。本文將選用 PgBouncer 做爲PostgreSQL的鏈接池。下面將介紹安裝及配置方法。web

1. 從yum安裝pgbouncer及工具的依賴項redis

yum install pgbouncer python-psycopg2 -y

2. 修改pgbouncer配置

vim /etc/pgbouncer/pgbouncer.ini

a.  [databases] 節

#gis = 是PgBouncer公開給客戶端的數據庫名稱,能夠和實際數據庫不一致
#connect_query=驗證數據庫是否正常鏈接
#此外沒有指定user和password參數,將從下面的pgbouncer配置節中從auth_file中匹配

gis = host=127.0.0.1 port=5432 dbname=gis datestyle=ISO connect_query='SELECT 1'

b.  [pgbouncer] 節

logfile = /var/log/pgbouncer/pgbouncer.log
pidfile = /var/run/pgbouncer/pgbouncer.pid

#*表明任意地址 listen_addr = * listen_port = 6432 auth_type = md5
#auth_file是鏈接數據庫的用戶名和密碼匹配文件 auth_file = /etc/pgbouncer/userlist.txt
#postgres是能夠登陸到虛擬的pgbouncer庫的管理用戶 admin_users = postgres stats_users = stats, postgres pool_mode = session server_reset_query = DISCARD ALL max_client_conn = 100 default_pool_size = 20

3. 生成 auth_file  文件,該文件存儲實際用於登陸的用戶名和密碼。

cd /etc/pgbouncer

# 第二個參數將使用PostgreSQL的配置項 ./mkauth.py "/etc/pgbouncer/userlist.txt" "dbname='postgres' user='postgres' password='111111' host='127.0.0.1'" chown pgbouncer:pgbouncer userlist.txt

4. 啓動並驗證pgbouncer ,注意,此處不可以使用 root 用戶,請使用安裝包自動建立的 pgbouncer 用戶

su pgbouncer

pgbouncer -d /etc/pgbouncer/pgbouncer.ini

5. 查看pgbouncer鏈接池和客戶端

#經實測,若是不使用-h參數將沒法登陸
psql -p 6432 -h 127.0.0.1 -U postgres -d pgbouncer -W show pools; show clients; show help;

6. 關閉pgbouncer

sudo pkill -9 -f 'pgbouncer'

2、PostgreSQL主備模式 

 PostgreSQL提供了Standby(主備)模式,用於實現一臺主數據庫、n臺備數據庫,達到高可用性的目的。該模式也順便爲實現多臺只讀數據庫提供了條件。接下來將介紹如何實現Standby模式。

1. 安裝PostgreSQL主庫步驟(過程略),詳情請參見《CentOS7下安裝並簡單設置PostgreSQL筆記

2. 導入OpenStreetMap數據(過程略),詳情請參見《CentOS7部署PostGis》、《CentOS7部署osm2pgsql

3. 安裝PostgreSQL備庫(終於到主角上場了),咱就再也不Step by Step了,直接一次性裝上。

yum install http://yum.postgresql.org/9.5/redhat/rhel-7-x86_64/pgdg-redhat95-9.5-2.noarch.rpm -y

yum install postgresql95-server postgresql95-contrib -y

#安裝PostGis
yum install postgis2_95 postgis2_95-client ogr_fdw95 pgrouting_95 -y
mkdir /home/postgresql_data

4. 修改主庫配置,請注意,這裏不是修改剛安裝好的數據庫,而是修改第1步中主庫的配置文件

a. $PGPATH下的 pg_hba.conf 文件

 在文件最下面添加以下配置 

host    replication            postgres            192.168.1.0/24        md5

  

b. $PGPATH下 postgresql.conf 文件,確保有三處配置以下: 

i.    listen_address = '*'  

ii.   wal_level = hot_standby  

iii.  max_wal_senders = 5  

c. 爲postgres數據庫賬號設置密碼 

ALTER USER postgres WITH PASSWORD '111111'

 d. 重啓Postgresql服務,使配置生效 systemctl restart postgresql-9.5  

5. 在備庫服務器上生成基礎備份,請注意,此處回到備庫的服務器進行操做

# -D參數是你要把主庫備份出來的目的目錄
# -l參數是你備份的標籤,請隨意

pg_basebackup -h 192.168.1.99 -U postgres -F p -P -x -R -D /home/postgresql_data -l pgbak201701291308

 6. 修改備庫配置文件, vim /home/postgresql_data/postgresql.conf 

 hot_standby = on  

7. 設置備庫數據目錄的全部者和權限

chown -R postgres:postgres /home/postgresql_data

chmod -R 700 /home/postgresql_data

 8. 設置備庫postgresql服務啓動選項 vim /usr/lib/systemd/system/postgresql-9.5.service  

 Environment=PGDATA=/home/postgresql_data  

9. 啓動備庫並查看狀態 

systemctl start postgresql-9.5

systemctl status postgresql-9.5

 10. 查看備庫狀態:

11. 驗證主備模式是否有效,當前主庫的測試表數據是:

select * from tetst01;

主庫中添加一行數據

insert into test01(id,note) values (2, 'aCloud');

再在備庫中查詢

至此,PostgreSQL的主備模式構建完成。

3、使用HAProxy 實現PostgreSQL負載均衡

上一節中咱們經過創建Standby模式,在一臺主數據庫和n臺備數據庫之間實現了數據同步。雖然備數據庫只能提供只讀服務,然而對於存儲地理空間數據的應用而言,90%的狀況下就夠用了,由於咱們要修改數據的時機仍是比較少的,所以採用負載均衡技術將應用程序對數據庫的請求分攤到幾臺數據庫服務器上,將有助於性能提高。

一般而言,負載均衡服務軟件有三種:Nginx、HAProxy和LVS。Nginx在網絡的第7層、LVS在網絡的第4層,而HAProxy在四、7層均可以工做,並且有文章指出,HAProxy在虛擬機上能較好的工做,So,不費勁了,直接選HAProxy吧。

1. 安裝HAProxy

yum install haproxy -y

2. 配置HAProxy, vim /etc/haproxy/haproxy.cfg ,配置文件中超時時間和網絡檢查時間設置的偏大,這是由於若是這些值設置的過小的話,postgresql在進行運算時,舊的查詢尚未完成,新的請求或檢查就來了,就形成超時了。這個問題在之後有時間了再好好的研究下,看是否有更好的辦法。目前使用這個方法也能解決問題。

global

    log 127.0.0.1 local2

    chroot /var/lib/haproxy
    pidfile /var/run/haproxy.pid
    maxconn 4000
    user haproxy
    group haproxy
    daemon

    stats socket /var/lib/haproxy/stats

defaults
    mode tcp
    log global
    option redispatch
    option httplog
    retries 10
    timeout queue 5m
    timeout connect 5m
    timeout client 5m
    timeout server 5m
    timeout http-keep-alive 20m
    timeout check 1m
    maxconn 3000

listen webservers
    bind 0.0.0.0:808
    mode http
    log global
    stats refresh 30s
    stats realm Private lands
    stats uri /admin?stats
    stats auth admin:111111

listen postgres
    bind 0.0.0.0:7432
    mode tcp
    balance roundrobin
    server pg1 192.168.1.99:6432 weight 1 maxconn 1000 check inter 5m
    server pg2 192.168.1.80:6432 weight 1 maxconn 1000 check inter 5m
    server pg3 192.168.1.85:6432 weight 1 maxconn 1000 check inter 5m
    server pg4 192.168.1.86:6432 weight 1 maxconn 1000 check inter 5m

3. 防火牆打洞

firewall-cmd --zone=public --add-port=7432/tcp --permanent

firewall-cmd --reload

4. 關閉SELinux(規則太難配,乾脆關了), vim /etc/selinux/config 

SELinux=disabled

5. 啓動HAProxy

systemctl start haproxy

systemctl enable haproxy

6. 使用 http://haproxyaddr:port/admin?stats 可對HAProxy狀態進行監控。這裏咱們能夠看到目前狀態正常。

7. 至此,咱們已經有了四個PostgreSQL數據庫,而且使用HAProxy進行負載均衡,下面就能夠配置mapnik,使用HAProxy。打開 OpenStreetMap-Carto 文件夾(不知道這個文件夾在什麼地方?請參考《使用node-mapnik生成openstreetmap-carto風格的瓦片》一文中的設置),修改 project.mml ,將其中的 host 、 port 修改成HAProxy的地址和偵聽端口,將 dbname 修改成 pgbouncer.ini 中 [databases] 的值。將 user 、 password 修改成  pgbouncer.ini 中 auth_file 文件中的相應用戶名和密碼信息。

8. 從新生成mapnik配置

carto project.mml > mapnik.xml

此時,  node-mapnik  就可使用HAProxy提供的服務了。

4、TileStrata實現瓦片服務負載均衡

1. 《使用node-mapnik和openstreetmap數據初步搭建瓦片服務》的第四節,已經講了TileStrata提供的 TileStrata-Balancer 組件實現瓦片服務負載均衡,本文繼續使用該節內容,有須要的筒子們請參考。效果以下:

tilestrata-balancer --hostname=192.168.1.51 --port=8083 --private-port=8081 --check-interval=5000 --unhealthy-count=1

注意:記得在提供瓦片服務的服務器上打開相應的防火牆端口。爲了省事,最好把SELinux關閉掉。最後,不要把tilestrata-balancer的private端口公佈到公網上。

5、Node.js的單機集羣

Node.js應用程序通常狀況下僅能使用CPU的一個核,要充分利用CPU,最好是每一個核上跑一個Node.js的程序。簡單點來講,Node.js內置了這一實現,看下面代碼:

1. tileserver/server/cluster.js ,在這個文件中,Node.js將在每個CPU的核心上執行一個 ./server.js 文件。爲了能成功加入到 tilestrata-balancer ,我給每個fork指定一個單獨的端口號

var cluster = require('cluster');
var cpus = require('os').cpus();

cluster.setupMaster({
  exec: './server.js'
});

for(var i = 0; i < cpus.length; i++){
  var port = 8088 + i;
  cluster.fork({port : port});
}

2.  tileserver/server/server.js ,在 cluster.js 傳來的端口上進行偵聽

var tilestrata = require('tilestrata');
var disk = require('tilestrata-disk');
var mapnik = require('tilestrata-mapnik');

var strata = tilestrata({
  balancer: {
    host: '192.168.1.51:8081'
  }
});

strata.layer('map')
  .route('tile.png')   
  .use(disk.cache({dir: './tilecache'}))   
  .use(mapnik({
    pathname: '/home/openstreetmap/openstreetmap-carto/mapnik.xml'
  }));

var port = process.env['port'];

strata.listen(port);

3. 進入服務端程序目錄,啓動程序

cd projectdir/tileserver/server

node cluster

能夠看到四核CPU,就起了四個端口,效果以下:

6、OpenLayers使用多個瓦片服務器

 若是咱們看OpenStreetMap官網,就能夠發現它使用的瓦片服務器可不止一臺,下面咱們看如何使用OpenStreetMap來實現相似效果(OpenStreetMap使用的是Leaflet)

只須要定義Tile時,指定 ulrs 屬性爲一個瓦片服務Url的數組就好了

        var tileStrataMapLayer = new ol.layer.Tile({
          source: new ol.source.XYZ({
            urls: [
            'http://192.168.1.51:8083/map/{z}/{x}/{y}/tile.png',
            'http://192.168.1.99:8083/map/{z}/{x}/{y}/tile.png']
            })});

效果以下:

 

 爲了方便,特將本文中的代碼公佈出來,有須要的筒子們請下載

 

後記:

前先後後好長時間了,主要仍是時間嚴重不足,致使這個系列進度過於緩慢,並且每一篇都只能草草的講講過程,對於其中的原理講的不多。但這也沒有辦法,過完春節後可能工做要更忙了,因此OpenStreetMap、node-mapnik這個系列極可能不會再作深刻的學習了。將來主要是想辦法將這些技術應用到工做中,以及提高這些技術的高性能、高可用性。歡迎有相同興趣的兄弟一塊兒研討。每次寫文章,都是趁着休息時間弄,文字上面也不太講究,不太通順的地方請諒解。

 

若是非得讓我學點新的,我但願能實現Docker下的OpenStreetMap數據服務和OpenStreetMap數據的WMS服務。

 

轉載請註明原做者(think8848)和出處(http://think8848.cnblogs.com) 

相關文章
相關標籤/搜索