~增加內(nèi)存緩存功能??蓪⒁焉蛇^的切片數(shù)據(jù)自動緩存在機器內(nèi)存中,之后可從內(nèi)存中直接返回該切片,而不是動態(tài)生成。啟用內(nèi)存緩存功能后,可顯著提高PBS性能,尤其對于動態(tài)緩存地圖服務(wù)功能(影像數(shù)據(jù)或動態(tài)地圖服務(wù)作為數(shù)據(jù)源),在幾乎不占用cpu資源的情況下,支持的并發(fā)數(shù)可提高數(shù)十倍。該功能利用Memcached完成,它是一個免費的高性能分布式緩存系統(tǒng)(http://memcached.org/)。詳細介紹;
2011.10.25更新v1.0.6:
~增加底圖風格化選項。目前除了原本的底圖之外,為所有服務(wù)提供兩個視覺風格選項:灰度圖(Gray)和反色圖(Invert),用于特殊目的。比如使用灰度圖可突出顯示業(yè)務(wù)內(nèi)容,詳見這里。詳細介紹;
2011.10.12更新v1.0.5:
~增加ArcGIS Server Endpoint(http://localhost/arcgis/rest/services?f=json)信息,以便需要此信息的程序來使用PBS發(fā)布的服務(wù)。比如可在Silverlight Viewer中,直接加載PBS轉(zhuǎn)發(fā)的天地圖服務(wù);
2011.8.8更新v1.0.4:
~增加配置文件功能:可將已發(fā)布的服務(wù)保存為配置文件,下回啟動程序時可載入配置文件以啟動相應(yīng)服務(wù);
~增加選擇本地IP地址功能:方便生成供其他機器使用的正確服務(wù)地址;
~修復bug:在有些機器上雙擊服務(wù)進行預(yù)覽時,程序會崩潰。原因是預(yù)覽窗口中的服務(wù)屬性使用了xaml binding,但出現(xiàn)了沒有捕捉到的異常(有vs2010開發(fā)環(huán)境的機器不會拋出此異常)。感謝ningjun198624的反饋;
~修復bug:在沒有vs2010開發(fā)環(huán)境的機器上發(fā)布RasterDataset數(shù)據(jù)源報錯。原因是程序中使用的gdal由vs2010編譯,需要用到幾個額外的動態(tài)鏈接庫。新版本中已將所需的文件隨壓縮包分發(fā)。
2011.7.31更新v1.0.3:
~影像數(shù)據(jù)源增加對.sid格式的支持:MrSID是LizardTech公司持有的高壓縮比影像存儲格式,根據(jù)GDAL的解釋,最初被FBI用于指紋存儲。了解遙感的mm同事告訴我,MrSID格式壓縮率通常比ecw格式要高,并且使用更廣泛;
~數(shù)據(jù)源增加對ArcGIS影像服務(wù)的支持:在10.1版本之前,ArcGIS Server發(fā)布的Image Service是不能夠做切片的。通過PBS,可將ArcGIS Server的影像服務(wù)轉(zhuǎn)換成動態(tài)緩存地圖服務(wù),既提高了顯示速度和效果,又省去了切圖時間和硬盤空間;
~添加平均出圖時間統(tǒng)計:服務(wù)信息中增加“Seconds Per Tile”統(tǒng)計信息,即該服務(wù)平均成功輸出一張切片所用的時間。
2011.7.24更新v1.0.2:
~影像數(shù)據(jù)源增加對.ecw格式的支持:ecw是ERDAS公司持有的高壓縮比影像存儲格式,壓縮率可達1:2~1:100。比如1m大小的ecw文件可包含3波段3000*3000(行/列)大小的影像數(shù)據(jù);
~影像數(shù)據(jù)源增加對.vrt格式的支持:類似于ArcGIS中的Raster Catalog。比如你有不同空間范圍內(nèi)的若干小的影像文件,可通過構(gòu)建后綴名為vrt的xml文件,直接將它們通過動態(tài)鑲嵌,發(fā)布為一個完整的動態(tài)緩存地圖服務(wù);
~修復bug:ArcGISDynamicMapService數(shù)據(jù)源輸入錯誤服務(wù)地址時程序會崩潰;
~代碼重構(gòu)。
2011.7.17更新v1.0.1:
~數(shù)據(jù)源加入對影像數(shù)據(jù)的支持:對于大數(shù)據(jù)量的影像文件,無需切圖,即可提供動態(tài)緩存地圖服務(wù)。數(shù)據(jù)源選擇RasterDataset,可發(fā)布文件形式的影像數(shù)據(jù)。利用GDAL讀取柵格圖像,支持格式見這里;不支持動態(tài)投影(TilingScheme文件中的空間參考必須與影像數(shù)據(jù)的空間參考一致);
~修復bug:未發(fā)布服務(wù)時點擊“Copy to Clipboard”按鈕出錯;
~修復bug:預(yù)覽窗口中左上角的縮放級別信息在有的坐標系下不準確。
————————————————-更新分割線————————————————-
使用現(xiàn)在流行的Web地圖API的第一件事情,就是往地圖控件中添加一個底圖(Basemap)圖層,做為我們整個GIS應(yīng)用的可視化基礎(chǔ)。而這個底圖圖層通常有兩個特點,一是經(jīng)過了緩存,即服務(wù)器端提供已經(jīng)預(yù)先緩存好或動態(tài)提供固定大?。ū热?56*256)地圖切片,加快客戶端的訪問速度;二是該圖層由一個REST風格的網(wǎng)絡(luò)服務(wù)暴露出來。對于它的訪問,客戶端一般會發(fā)起若干個包含有三個關(guān)鍵參數(shù)的請求,比如http://hostaddress/servicename/LEVEL/ROW/COLUMN,將請求的結(jié)果(若干切片)拼接成我們所看到的地圖。
目前來講,要使用這些底圖服務(wù)的前提是,我們必須使用特定的客戶端才能加載特定的底圖服務(wù),比如利用Google Maps API加載Google的底圖;如果要加載自己地理數(shù)據(jù),還需要有專門的GIS軟件,比如ArcGIS Server來發(fā)布Map Service。
為了解決這一問題,使得開發(fā)人員能夠更加方便地加載各種底圖服務(wù),從而將更多的精力投入到做出更有用的系統(tǒng)中去,我做了這個稱作Portable Basemap Server(簡稱PBS)的小程序供大家免費使用。它的目的是通過一個可以拷貝到U盤里的,免安裝的WPF程序,來加載各種數(shù)據(jù)源作為底圖圖層,直接為更多的客戶端API提供一致風格的REST底圖服務(wù),從而使開發(fā)人員免去為每個應(yīng)用程序自定義圖層的麻煩。
關(guān)于PBS的功能
使用起來很簡單,大致分四個步驟。1、選擇數(shù)據(jù)源類型,2、設(shè)置數(shù)據(jù)源路徑,3、設(shè)置將要發(fā)布的服務(wù)端口號和服務(wù)名,4、啟動服務(wù)。程序界面如下:
一、選擇數(shù)據(jù)源類型:
二、設(shè)置數(shù)據(jù)源:
為選擇的數(shù)據(jù)源類型設(shè)置相應(yīng)的數(shù)據(jù)源位置即可。MAC和MBTile直接選去本地的Sqlite文件;ArcGISCache選擇包含有Conf.xml和Conf.cdi的文件夾;ArcGISDynamicMapService直接輸入一個或多個REST服務(wù)的地址;所有在線地圖不需要設(shè)置數(shù)據(jù)源位置,PBS已為你做好。
三、設(shè)置端口號和服務(wù)名
PBS是通過.NET Framework的WCF框架完成的。在啟動服務(wù)之前需要選擇將服務(wù)發(fā)布到本機的哪個端口上。一個端口上可以發(fā)布多個服務(wù),也可將服務(wù)發(fā)布在多個端口上。但同一端口上不能有同名的服務(wù)。
DisableClientCache:默認情況下,PBS輸出的圖片可以被緩存在客戶端,下次訪問時會直接使用客戶端的緩存而不需要重新繪制切片。勾選此選項后,PBS輸出的圖片響應(yīng)會指明不允許客戶端進行緩存,從而方便客戶端每次都請求道最新的數(shù)據(jù)。
Display”NoData”Tile:勾選此項后,在Tiling Scheme范圍內(nèi),如果某些范圍或某些比例尺沒有創(chuàng)建緩存,則會顯示一個NoData的圖片;如果打算用此服務(wù)與其它服務(wù)疊加(保持此服務(wù)背景透明),請不要勾選。
四、啟動服務(wù)
設(shè)置好上面參數(shù)后,點擊“Start New Service”,即可啟動該服務(wù)。啟動好的服務(wù)會出現(xiàn)在下方的服務(wù)列表中:
五、服務(wù)管理
程序下方的服務(wù)列表內(nèi)會列出所有正在運行的底圖服務(wù),會顯示服務(wù)名,所在端口號,數(shù)據(jù)源類型,服務(wù)啟動后輸出的切片數(shù)量,平均成功輸出一張切片所需時間,以及最后一次被請求的客戶端ip地址做為服務(wù)情況的大致預(yù)覽??稍诜?wù)列表中雙擊某個服務(wù),會彈出一個對話框,調(diào)用ArcGIS API for WPF查看該服務(wù),并顯示該服務(wù)的詳細信息。如果該服務(wù)缺少全圖范圍參數(shù),比如MAC數(shù)據(jù)源,則會新彈出的WPF對話框會額外添加一個ArcGIS Online底圖,以便方便瀏覽到該服務(wù)的范圍。
如果加載某個切片失敗,比如下載在線數(shù)據(jù)源時網(wǎng)絡(luò)連接出現(xiàn)問題,會顯示失敗的圖片:
若要刪除某個服務(wù),請在服務(wù)列表中選中,然后點擊“DeleteService”即可。
此外,還可將已發(fā)布的全部服務(wù)保存成配置文件(v1.0.4版本以上),下回程序啟動時可載入配置文件以啟動相應(yīng)的服務(wù)。配置文件保存在程序根目錄下的Config.db文件中(sqlite文件格式)。
2.0.3版本開始,PBS增加REST Admin API。任何程序可通過發(fā)送HTTP(POST)請求,對PBS的服務(wù)進行管理。PBS的REST Admin API使用HTTP基本認證,即HTTP請求頭(request header)中必須含有“Authorization”項,該項內(nèi)容為Base64編碼字符串,格式為“用戶名:密碼”。請求認證信息中的用戶(包含正確的密碼),必須為PBS運行機器上Administrators組中的成員,所發(fā)送的請求才會被正確處理,否則將返回包含詳細錯誤描述的響應(yīng)信息。
為了保證PBS能夠正確響應(yīng)請求的操作,請求中的端口必須提前打開。2.0.3版本開始,PBS默認使用7080端口,該端口會在PBS啟動時自動開啟。可修改配置文件中的DefaultPort值來更改PBS使用的默認端口號。
每項管理操作都需要相應(yīng)的參數(shù),參數(shù)提交格式為標準JSON對象,對象中每一個鍵值對即為一個參數(shù)(鍵應(yīng)為string類型,值應(yīng)為string/int/bool/null類型)。參數(shù)應(yīng)存放于HTTP請求體(request body)內(nèi)。
~添加服務(wù)(addService):v2.0.3,該操作的地址為“http://serverip:port/PBS/rest/admin/addService”,參數(shù)列表如下:
或用C#發(fā)送如下請求:
1: byte[] postData = Encoding.UTF8.GetBytes(@"{""port"":7080, ""disableClientCache"":false, ""dataSourcePath"":""D:\\arcgisserver\\arcgiscache\\CharlotteRaster.tpk"",""dataSourceType"":""ArcGISTilePackage"", ""tilingSchemePath"":null, ""allowMemoryCache"":true, ""visualStyle"":""None"", ""name"":""ServiceName1"", ""displayNodataTile"":false}");
2: HttpWebRequest myReq = WebRequest.Create("http://localhost:7080/PBS/rest/admin/addService") as HttpWebRequest;
3: myReq.Method = "POST";
4: string username = "Administrator";
5: string password = "123456";
6: string usernamePassword = username + ":" + password;
7: //注意格式 “用戶名:密碼”,之后Base64編碼
8: myReq.Headers.Add("Authorization", Convert.ToBase64String(Encoding.UTF8.GetBytes(usernamePassword)));
9: myReq.ContentLength = postData.Length;
10: using (System.IO.Stream requestStream = myReq.GetRequestStream())
11: {
12: requestStream.Write(postData, 0, postData.Length);
13: }
14: WebResponse wr = myReq.GetResponse();
15: System.IO.Stream receiveStream = wr.GetResponseStream();
16: System.IO.StreamReader reader = new System.IO.StreamReader(receiveStream, Encoding.UTF8);
17: string content = reader.ReadToEnd();
18: receiveStream.Close();
19: reader.Close();
響應(yīng)內(nèi)容:JSON字符串,格式:{“success”": [ture|false],”message”: [detail message]}。如果操作成功,detail message將返回PBS服務(wù)信息的JSON字符串,如果失敗,將返回詳細錯誤原因。
~刪除服務(wù)(deleteService):v2.0.3,該操作地址為“http://serverip:port/PBS/rest/admin/deleteService”,參數(shù)列表如下:
響應(yīng)內(nèi)容:JSON字符串,格式:{“success”": [ture|false],”message”: [detail message]}。
~開啟內(nèi)存緩存(enable):v2.0.4,該操作地址為“http://serverip:port/PBS/rest/admin/memCache/enable”,參數(shù)列表如下:
如果內(nèi)存緩存功能已經(jīng)開啟,返回結(jié)果依然為true,但會有額外提示。
響應(yīng)內(nèi)容:JSON字符串,格式:{“success”": [ture|false],”message”: [detail message]}。
~關(guān)閉內(nèi)存緩存(disable):v2.0.4,該操作地址為“http://serverip:port/PBS/rest/admin/memCache/disable”,此操作不需要參數(shù)(請求體為空即可,如有則忽略)。如果內(nèi)存緩存功能已經(jīng)關(guān)閉,返回結(jié)果依然為true,但會有額外提示。
響應(yīng)內(nèi)容:JSON字符串,格式:{“success”": [ture|false],”message”: [detail message]}。
~清除某個服務(wù)的內(nèi)存緩存(clearByService):v2.0.4,該操作地址為“http://serverip:port/PBS/rest/admin/memCache/clearByService”,參數(shù)列表如下:
響應(yīng)內(nèi)容:JSON字符串,格式:{“success”": [ture|false],”message”: [detail message]}。
后續(xù)版本將增加更多操作…
六、服務(wù)使用
啟動好的服務(wù)都會暴露出來一個REST服務(wù)地址,
目前僅支持ArcGIS緩存服務(wù)規(guī)范,可供所有ArcGIS客戶端API,包括Javascript/Flex/Silverlight/iOS/Windows Phone/Android,以及即將推出的ArcGIS Runtime直接使用;由于OpenLayer中可通過ArcGIS93REST圖層直接加載ArcGIS的服務(wù),因此PBS服務(wù)也可直接被OpenLayers客戶端使用。
比如在ArcGIS API for Javascript中,我們在地圖中添加一個底圖圖層,Url地址指向PBS發(fā)布的某個服務(wù):
這樣就能直接通過PBS為我們提供的,類似于原生ArcGIS緩存地圖服務(wù)的Url地址,訪問到第三方的底圖數(shù)據(jù)了。開發(fā)人員從此免去了在客戶端自定義圖層,去加載第三方切片的麻煩。比如通過PBS提供的服務(wù),分別在ArcGIS API for Javascript/Flex/Silverlight中調(diào)用Google Maps地圖。
除此之外,從1.0.6版本開始,PBS增加了風格化的選項,可以在不需要重新切圖的情況下(動態(tài)地圖服務(wù)則無需切圖),直接改變所有底圖服務(wù)的視覺呈現(xiàn)效果。目前提供視覺風格選項:灰度圖(Gray)和反色圖(Invert),用于特殊目的。比如使用灰度圖可突出顯示業(yè)務(wù)內(nèi)容,詳見這里。
2.0.3版本新增泛黃(tint)與浮雕(embossed)兩種效果。
關(guān)于PBS的性能
PBS利用WCF REST框架開發(fā),支持多用戶,多并發(fā)請求,性能僅受機器硬件限制。初步用Apache JMeter做了測試,在我的筆記本上,通過PBS的REST服務(wù),請求Sqlite數(shù)據(jù)庫中一張22kb的圖片,500個并發(fā)請求的響應(yīng)時間在10ms以下:
在磁盤性能更好的服務(wù)器上測試,1000個并發(fā)請求的相應(yīng)時間可以在10ms以下。
而實際使用中,單個底圖服務(wù)達到上千個并發(fā)請求的情況還是比較少見的,所以PBS可以滿足大多數(shù)需求。
從2.0版本開始,PBS增加了內(nèi)存緩存功能??蓪⒁焉蛇^的切片數(shù)據(jù)自動緩存在機器內(nèi)存中,之后可從內(nèi)存中直接返回該切片,而不是動態(tài)生成。
2.0.1版本增加對單個服務(wù)是否啟用內(nèi)存緩存的控制,并增加輸出動態(tài)生成切片數(shù)量和內(nèi)存緩存切片數(shù)量的信息。
2.0.2版本增加對單一服務(wù)清除內(nèi)存緩存的功能。
只需在Memory Cache菜單下,勾選Enable選項,即可啟用內(nèi)存緩存功能。該特性可顯著提高PBS性能,尤其對于動態(tài)緩存地圖服務(wù)功能(影像數(shù)據(jù)或動態(tài)地圖服務(wù)作為數(shù)據(jù)源),在幾乎不占用cpu資源的情況下,支持的并發(fā)數(shù)可提高數(shù)十倍。該功能利用Memcached完成,它是一個免費的高性能分布式緩存系統(tǒng)(http://memcached.org/)。
默認情況下,Memory Cache會使用64M機器內(nèi)存來緩存切片數(shù)據(jù),達到64M后,會自動替換掉最早的緩存數(shù)據(jù)。使用機器內(nèi)存的大小可通過PortableBasemapServer.exe.config配置文件進行配置,只需修改其中MemcachedSize節(jié)點的數(shù)值即可。
比如對于影像數(shù)據(jù)作為數(shù)據(jù)源的動態(tài)緩存地圖服務(wù)功能,在服務(wù)器機器上,可配置更多的物理內(nèi)存(比如4G)供PBS使用。這樣一來,只需在第一個客戶端訪問時生成一次切片數(shù)據(jù),后續(xù)的請求就可直接從內(nèi)存中獲得切片。以內(nèi)存方式替代cpu的工作和硬盤的存儲空間,使得PBS投入實際生產(chǎn)運行成為可能。
經(jīng)測試(筆記本環(huán)境),對于PBS轉(zhuǎn)發(fā)的在線地圖服務(wù)(Google Maps)中的一張切片,沒有使用內(nèi)存緩存功能時,100個并發(fā)請求響應(yīng)時間平均為10秒左右(和我的網(wǎng)速慢也有很大關(guān)系),因為每次請求都需要在線下載該切片;使用了內(nèi)存緩存功能后,對于同樣的一個切片,100個并發(fā)請求響應(yīng)時間平均為2毫秒(該切片已在內(nèi)存中的情況,下同),500個并發(fā)平均響應(yīng)時間為6毫秒,1000個并發(fā)平均響應(yīng)時間為200毫秒左右。在內(nèi)存更好的服務(wù)器上測試,可獲得更理想的結(jié)果
總結(jié)
對于ArcGIS用戶來說,通過PBS,可直接加載第三方的離線數(shù)據(jù)源(MAC/MBTile),而不需要按照ArcGIS的切圖規(guī)則重新組織切片;可將動態(tài)地圖服務(wù)轉(zhuǎn)換成動態(tài)緩存地圖服務(wù),無需自己在客戶端API中自定義圖層;可使用多種數(shù)據(jù)源;
對于OpenLayers用戶,可使用更多的,內(nèi)容更豐富的底圖數(shù)據(jù);
Portable Basemap Server可裝入U盤帶走,在任何具有.NET Framework 4.0環(huán)境的機器上直接運行,無需安裝。一個U盤即可提供多種底圖,方便開發(fā)者使用;
后續(xù)計劃加入更多數(shù)據(jù)源,比如本地影像數(shù)據(jù)(已加入),以及為更多客戶端提供支持。