大魚

          提高 Web Service 數(shù)據(jù)傳輸效率的基本方法

          本文介紹了在 Web Service 實施和開發(fā)過程中,提高系統(tǒng)效率的一些方法,實踐證明,這些方法都是非常有效且易于實現(xiàn)的。針對各種方法的優(yōu)缺點以及應(yīng)用場景,文章也進行了相應(yīng)的討論。

          背景

          Web Service 現(xiàn)如今已經(jīng)成為 SOA 實現(xiàn)標準之一。很多公司已經(jīng)或者正在參與到 Web Service 項目的實現(xiàn)和部署中。Web Service 的優(yōu)點在于松散的處理異構(gòu)系統(tǒng)之間的通信和數(shù)據(jù)交換,可以隨機應(yīng)變的處理企業(yè)各個系統(tǒng)之間的整合問題。但是同時,Web Service 采用 XML 標準進行系統(tǒng)間的數(shù)據(jù)傳輸,加大了傳輸?shù)臄?shù)據(jù)量,尤其是在傳輸一些具有比較嚴格結(jié)構(gòu)的數(shù)據(jù)時,會使得傳輸效率有所下降。所以,如何提高 Web Service 傳輸效率成為很多公司進行項目部署時非常關(guān)心的問題。

          目的

          本文介紹了在 Web Service 實施和開發(fā)過程中,提高系統(tǒng)效率的一些方法,實踐證明,這些方法都是非常有效且易于實現(xiàn)的。不同的方法都有其應(yīng)用領(lǐng)域和優(yōu)缺點,我們會分別進行討論。文章的主要目的在于,提供給讀者多種方式的基本解決方案,使得讀者在 Web Service 項目部署時,擁有更多的思路。

          原因分析

          Web Service 是采用 XML 標準進行數(shù)據(jù)傳輸?shù)摹ML 在傳輸過程中,會附帶很多數(shù)據(jù)的相關(guān)信息,并以標簽的形式表現(xiàn)出來。在傳輸過程中,一些情況下,這些標簽會占用一半以上甚至更多的數(shù)據(jù)傳輸量,例如,要傳輸一個表格信息,如下(表格中的人名為虛構(gòu)的):


          表 1. 將要進行傳輸?shù)谋砀袷纠?/strong>
          Name City Apartment
          Air Wang Beijing Some Place

          表 1 中的數(shù)據(jù)在傳輸過程中,有可能會生成下面的 XML 文件:
          清單 1. 對應(yīng)于表 1 數(shù)據(jù)所傳輸?shù)?XML 文件示例
                      <Heading>
                      <column> Name</column>
                      <column>City</column>
                      <column>Apartment</column>
                      </Heading>
                      <Data Grid>
                      <row>
                      <column>Air Wang</column>
                      <column>Beijing</column>
                      <column>IBM CDL</column>
                      </row>
                      </Data Grid>
                      

          如果上面的表格中還帶有格式的信息(比如字體,背景顏色等等)的話,那么相應(yīng)的 XML 就會更加復雜了。從上述 XML 中我們可以看出,除了數(shù)據(jù)之外,XML 會附加很多標簽信息,這就使得傳輸?shù)臄?shù)據(jù)量增大,當所需要傳輸?shù)臄?shù)據(jù)比較多的時候,XML的標簽就會帶來比較大的效率問題。

          解決方案一: 壓縮與解壓縮

          Web Service 在網(wǎng)絡(luò)中傳輸?shù)氖且?XML 為基礎(chǔ)的消息的請求和響應(yīng)。大量的數(shù)據(jù)傳輸會使網(wǎng)絡(luò)成為瓶頸。一個最直接的解決方案就是對傳輸?shù)南⑦M行壓縮。對于不同規(guī)模的數(shù)據(jù)量,壓縮應(yīng)該有不同的解決方案,下面分別介紹如下:

          1. 對于整個 XML 傳輸文件進行壓縮
          數(shù)據(jù)壓縮已經(jīng)發(fā)展了很多年,有很多成熟的技術(shù),算法以及工具包。經(jīng)常用于對數(shù)據(jù)壓縮的 API 有 gzip 等方式。對文件進行壓縮的做法非常簡單,就是在發(fā)送 XML 之前對 XML 進行壓縮,經(jīng)過壓縮以后,再在 XML 接收端對已經(jīng)壓縮的文件進行解壓縮。
          優(yōu)點:
          該方法的優(yōu)點在于,使用了成熟的壓縮和解壓縮技術(shù),當數(shù)據(jù)量比較大的時候,可以大大提高傳輸效率。對于純文本的 XML,壓縮可以減少其80%以上的體積。
          缺點:
          壓縮和解壓縮雖然可以使得 XML 的體積大大減少,但是其過程卻是十分耗費系統(tǒng)資源的。壓縮和解壓縮往往會具有很大的 CPU 占有率以及內(nèi)存占有率。對于配置不高的客戶端甚至是服務(wù)器端,都會造成不小的壓力。
          應(yīng)用場景:
          該技術(shù)應(yīng)用于網(wǎng)絡(luò)瓶頸非常嚴重的情況或是主機配置比較高的情況。
          舉例:
          正如本小節(jié)最開始已經(jīng)介紹的,現(xiàn)在已經(jīng)有很多成熟的壓縮與解壓縮的 API 提供給開發(fā)人員進行使用,我們選取其中最常用的 gzip 方式舉例說明。一般來講,系統(tǒng)請求 XML 的體積相對較小,沒有必要使用壓縮和解壓縮的方法處理請求 XML。而對于系統(tǒng)響應(yīng) XML 來講,一般都包含大量的數(shù)據(jù),導致其體積龐大,需要進行壓縮處理。對響應(yīng) XML 進行壓縮的流程如下:
          服務(wù)器端數(shù)據(jù)模型-->序列化操作-->利用 gzip 方式對序列化后的 XML 進行壓縮-->返回到客戶端-->以 gzip 方式進行解壓縮-->對解壓縮后的 XML 進行反序列化操作-->客戶端數(shù)據(jù)模型
          這里需要說明的一點是,客戶端以及服務(wù)器端的數(shù)據(jù)模型需要實現(xiàn) Serializable 接口。
          清單 2. gzip 方式壓縮部分實現(xiàn)代碼示例(java 實現(xiàn))
                      import java.io.*;
                      import java.util.zip.*;
                      public class Compress
                      {
                      public String gzip(OutputStream pStream)
                      {
                      …
                      try
                      {
                      GZIPOutputStream stream = new GZIPOutputStream(pStream);
                      return stream.toString();
                      }catch(IOException e){…}
                      …
                      return null;
                      }
                      …
                      }
                      

          在程序?qū)ο竽P托蛄谢?XML 之前,可以使用上面的壓縮方法,對數(shù)據(jù)流進行壓縮。部分代碼如下:
          清單 3. 對象模型序列化后再進行壓縮的實現(xiàn)代碼示例
                      public class XMLSerializerHelper
                      {
                      …
                      public static String saveOBJtoString(Object inputOBJ) throws ConverException
                      {
                      ……
                      ByteArrayOutputStream outputStream = null;
                      try{
                      outputStream = new java.io.ByteArrayOutputStream();
                      m_serializer.save((IXMLSerializable) inputObject, outputStream);
                      return Compress.gzip(outputStream);
                      }catch(Exception e){…}
                      ……
                      }
                      …
                      }
                      

          解壓縮的過程也類似于上述代碼。測試表明,采用 gzip 壓縮可以減少60%以上的網(wǎng)絡(luò)所帶來的消耗。

          2. 對于特定的數(shù)據(jù)進行特殊的處理
          在企業(yè)日常的數(shù)據(jù)傳輸中,往往大量的數(shù)據(jù)具有很多共同的特點。數(shù)據(jù)和數(shù)據(jù)之間往往具有很多相同的地方,或者說,具有很多重復的地方。例如,在一個以 Web Service 為構(gòu)架的報表處理系統(tǒng)中,報表往往會含有很多的空數(shù)據(jù),或者相同屬性和值域的數(shù)據(jù),對于這樣的情況,可以在代碼中對特殊情況進行特殊的處理。我們同樣以傳輸一個表格作為例子,如下:


          表 2. 將要傳輸?shù)暮卸鄠€空值的表格示例
          Software sold Hardware sold System sold Others
          120 - - -
          - - 90 -
          - 110 - -

          可以看到,上述表格具有很多的空值,那么在 XML 中完全可以把空值的部分統(tǒng)一處理,這樣就能大大減少網(wǎng)絡(luò)傳輸?shù)臄?shù)量,其對應(yīng)的部分 XML 如下:
          清單 4. 對空值進行處理后的簡化 XML 示例
                      ……
                      <NULL Value>(1,2),(1,3),(1,4),(2,1),(2,2),(2,4)(3,1),(3,3),(3,4)</NULL Value>
                      ……
                      

          優(yōu)點:
          對于重復性的數(shù)據(jù)來說,該方法可以幾十倍甚至上百倍的減少傳輸?shù)臄?shù)據(jù)量(這取決于數(shù)據(jù)重復的數(shù)量大小),相對于第一種壓縮方式,由于只是對固定形式的數(shù)據(jù)進行處理,所以不會占用很大的 CPU 以及內(nèi)存。
          缺點:
          數(shù)據(jù)的特點不容易把握,能夠處理的情況比較簡單和單一。對于空值或者某些值重復較多的情況,可以采用本方法。

          解決方案二: 減少多次調(diào)用,盡量使用一次性的調(diào)用方式。

          傳統(tǒng)的 RPC 調(diào)用,在多次使用的時候會產(chǎn)生很大的效率問題。用戶在進行每次遠程調(diào)用的時候都要等待網(wǎng)絡(luò)傳輸所耗費的時間。而對于 Web Service 來講,很多用戶仍然將其作為傳統(tǒng)的 RPC 來進行調(diào)用。每次都調(diào)用 Web Service Provider 所提供的函數(shù),造成了效率的極大浪費。Web Service 的一大特點在于,可以在本地進行一次性的設(shè)置,再把生成的 XML 統(tǒng)一的發(fā)送給服務(wù)的另外一端。對于用戶來講,所有的設(shè)置工作都是在本地進行的,用戶完全感覺不到網(wǎng)絡(luò)所帶來的瓶頸,而在最后的數(shù)據(jù)傳輸過程中,多消耗一些時間也是值得的。
          應(yīng)用場景:
          對于同用戶交互的情況,盡可能使用這樣的處理,即減少多次的遠程調(diào)用,盡量使得程序僅需完成一次調(diào)用。舉一個簡單的例子來說明問題:在一個用戶界面上(User Interface),需要進行很多的設(shè)置,而這些設(shè)置的每一步都是需要進行遠程調(diào)用的,這樣對于用戶來說,就會在每一次的設(shè)置過程中都等待網(wǎng)絡(luò)傳輸所耗費的時間。而對于 Web Service 而言,客戶端所有的工作就是生成請求 XML,所有的設(shè)置工作都可以統(tǒng)一生成一份 XML 文件,然后將其傳送給服務(wù)器端,這樣一來,用戶只用等待一次的數(shù)據(jù)傳輸時間(可能相對時間較長,但是用戶只用等待一次,還是值得的),而其他的工作都在服務(wù)器端進行處理。
          優(yōu)點:
          所有數(shù)據(jù)操作在本地進行,用戶在處理數(shù)據(jù)時不會感到網(wǎng)絡(luò)所帶來的停頓。最終所有操作請求統(tǒng)一發(fā)送給服務(wù)器端,使得原本多次等待的遠程操作只需要一次數(shù)據(jù)傳輸就能完成。
          舉例:
          下面的兩幅圖(圖 1 和圖 2)是某數(shù)據(jù)導入向?qū)е械膬蓚€步驟,用戶通過界面設(shè)置數(shù)據(jù)庫以及數(shù)據(jù)表的信息,從而得到目的數(shù)據(jù)。


          圖 1. 數(shù)據(jù)導入設(shè)置向?qū)纠?/strong>
          數(shù)據(jù)導入向?qū)纠龍D

          圖 2. 數(shù)據(jù)導入設(shè)置向?qū)纠?/strong>
          數(shù)據(jù)導入向?qū)纠龍D

          很多初學者容易進入的一個誤區(qū)是在數(shù)據(jù)庫選擇以后,在程序中直接連接數(shù)據(jù)庫,通過用戶提供的用戶密碼建立數(shù)據(jù)庫連接,然后在后續(xù)的每一個步驟中(如圖中的設(shè)定數(shù)據(jù)表條件)都進行遠程函數(shù)調(diào)用,以至于用戶每一次點擊向?qū)е械?#8220;下一步”按鈕時都會感覺到網(wǎng)絡(luò)帶來的瓶頸,例如停頓感,或者更嚴重的程序一段時間的沒有響應(yīng)等等。事實上,對于 Web Service 來講,每一步都可以對請求 XML 進行設(shè)置(這種設(shè)置是在本地進行的),當所有步驟都完成以后,再將 XML 統(tǒng)一發(fā)送給服務(wù)器端進行處理。這樣一來,用戶在每一步之間的操作都是在本地進行的,不會帶來多余的網(wǎng)絡(luò)響應(yīng)等待時間,使得整個向?qū)У脑O(shè)置工作能夠很快的進行。而最后一步完成以后,用戶對于網(wǎng)絡(luò)的一次性等待是相對值得的。在這個例子中,請求XML的部分結(jié)構(gòu)如下:
          清單 5. 客戶端進行數(shù)據(jù)導入設(shè)置的 XML 示例
                      ……
                      <Data Retrieving>
                      <Database>
                      <Type>Toolbox</Type>
                      <Pattern>TCP/IP</Pattern>
                      <UserName>Wang Yun</UserName>
                      </Password>
                      </Database>
                      <Table>
                      <Condition method=’more than’ value=’table’ >2500</Condition>
                      <Condition method=’equal to’ value=’table’>Wang Yun</Condition>
                      <Condition method=’less than’ value=’table’>10 days</Condition>
                      </Table>
                      <Data Retrieving>
                      ……
                      

          系統(tǒng)客戶端對 XML 進行設(shè)置的部分示例代碼如下(將對象模型序列化的過程,僅列出 Database 節(jié)點):
          清單 6. 對象模型序列化成 XML 示例
                      public class DataBaseLoginOBJ
                      {
                      …
                      public Element persistToXML(DataObject pOBJ)
                      {
                      …
                      Element dbElement = pOBJ.createElement(“Database”);
                      Element typeElement = pOBJ.createElement(“Type”);
                      Element patternElement = pOBJ.createElement(“Pattern”);
                      Element userElement = pOBJ.createElement(“UserName”);
                      Element pwdElement = pOBJ.createElement(“Password”);
                      dbElement.appendChild(typeElement);
                      dbElement.appendChild(patternElement);
                      dbElement.appendChild(userElement);
                      dbElement.appendChild(pwdElement);
                      …
                      }
                      …
                      }
                      

          DataObject實現(xiàn)了org.w3c.dom.Document的接口, Element實現(xiàn)了org.w3c.dom.Element接口。在完成了整個請求XML的設(shè)置之后,就將其統(tǒng)一傳輸至服務(wù)器端進行處理。

          解決方案三: XML 解析器的選擇和優(yōu)化

          現(xiàn)在軟件領(lǐng)域有很多種類的 XML 解析器,最基本的方式有兩種:DOM 和 SAX。對于不同級別的XML文件,應(yīng)該使用不同的解析器。有關(guān) XML 解析器的介紹,請參考其他相關(guān)文檔。下面列出他們使用的場景以及優(yōu)缺點:


          表 3. SAX 與 DOM 解析方式的基本比較
          種類 優(yōu)點 缺點 使用場景
          DOM 1.XML樹在內(nèi)存中完整存儲,因此可以直接修改其數(shù)據(jù)和結(jié)構(gòu)。 2.可以通過該解析器隨時訪問XML樹中的任何一個節(jié)點。 3.DOM解析器的API在使用上也相對比較簡單。 如果XML文檔體積比較大時,將文檔讀入內(nèi)存是非常消耗系統(tǒng)資源的。 DOM 是用與平臺和語言無關(guān)的方式表示 XML 文檔的官方 W3C 標準。DOM 是以層次結(jié)構(gòu)組織的節(jié)點的集合。這個層次結(jié)構(gòu)允許開發(fā)人員在樹中尋找特定信息。分析該結(jié)構(gòu)通常需要加載整個文檔和構(gòu)造層次結(jié)構(gòu),然后才能進行任何工作。DOM是基于對象層次結(jié)構(gòu)的。
          SAX SAX 對內(nèi)存的要求比較低,因為它讓開發(fā)人員自己來決定所要處理的標簽。特別是當開發(fā)人員只需要處理文檔中所包含的部分數(shù)據(jù)時,SAX 這種擴展能力得到了更好的體現(xiàn)。 用SAX方式進行XML解析時,需要順序執(zhí)行,所以很難訪問到同一文檔中的不同數(shù)據(jù)。此外,在基于該方式的解析編碼過程也相對復雜。 對于含有數(shù)據(jù)量十分巨大,而又不用對文檔的所有數(shù)據(jù)進行遍歷或者分析的時候,使用該方法十分有效。該方法不用將整個文檔讀入內(nèi)存,而只需讀取到程序所需的文檔標簽處即可。

          正確的選擇XML解析器的種類,對于Web Service系統(tǒng)的效率會有很大的幫助。現(xiàn)在有很多廠家提供了基于這兩種類型的很多XML解析器,在選擇的時候,應(yīng)該仔細閱讀說明文檔,慎重進行選擇。另外,往往在一個系統(tǒng)中可以同時使用這兩種方式,以達到解析的最高效率。一般來講,對于請求XML可以采用DOM的解析方式進行解析,而對于響應(yīng)XML可以使用SAX的方式進行解析。

          解決方案四: 簡化標簽

          我們知道,Web Service 解決方案在網(wǎng)絡(luò)中傳輸 XML 具有比較復雜的結(jié)構(gòu)。在傳輸過程中,不僅僅必要的數(shù)據(jù)被發(fā)送和接收,同時也會由于 XML 的結(jié)構(gòu)過于冗雜而附加了更多的信息進行傳輸。舉例如下:
          系統(tǒng)客戶端從服務(wù)器端得到的返回數(shù)據(jù)的響應(yīng) XML 結(jié)構(gòu)如下:
          清單 7. 在網(wǎng)絡(luò)中傳輸?shù)谋砀駭?shù)據(jù)對應(yīng)的 XML
                      <Cells>
                      <Heading Cells>
                      <Column>
                      <Row> Data </Row>
                      </Column>
                      <Column>
                      <Row/>
                      </Column>
                      …
                      </Heading Cells>
                      <DataGrid Cells>
                      …
                      </DataGrid Cells>
                      </Cells>
                      

          由上面的 XML 我們可以看出,每一個返回數(shù)值,都至少有 <Column>, </Column>, <Row>, </Row> 來標識它,也就是說,如果我們要傳輸一個表格,那么表格中每一個數(shù)據(jù)都要伴隨傳輸相應(yīng)的這四個標簽。假設(shè)表格中的每一個數(shù)據(jù)的字節(jié)數(shù)為8,那么標簽所帶來的附加字節(jié)就將近為數(shù)據(jù)的4倍。如果要傳輸?shù)臄?shù)據(jù)量十分巨大的話,效率自然會降低許多。所以我們可以采用一種十分簡單的方式,有效的減少XML所帶來的附加字節(jié)數(shù),即簡化XML標簽。可以將上面所說的XML改寫成下面的格式:
          清單 8. 對應(yīng)于清單 7 的簡化后的 XML
                      <Cells>
                      <Heading Cells>
                      <C>
                      <R> Data </R>
                      </C>
                      <C>
                      <R/>
                      </C>
                      …
                      </Heading Cells>
                      <DataGrid Cells>
                      …
                      </DataGrid Cells>
                      </Cells>
                      

          優(yōu)點:
          測試證明,采用這樣的改進方式,可以使得整個系統(tǒng)的效率提高近一倍甚至更多。而且這樣的處理方式簡單易行,只是修改標簽就可以了。
          缺點:
          使XML自身代表的意義變得不那么容易讀懂,彌補的方式是一般會有一個對照表,來說明具體簡化后的 XML 文件的含義。
          舉例:
          該方法比較簡單直觀,這里列出對照表的一個例子如下:


          表 4. 簡化前后 XML 的對照表及其含義
          簡化前標簽 簡化后標簽 含義
          Row R 表示表格中的行
          Column C 表示表格中的列
          ... ... ...

          類似上面這樣的聲明表格應(yīng)該作為文檔提供給用戶。

          應(yīng)用場景:
          這里需要說明一點,XML 能夠清晰的表示出整個數(shù)據(jù)結(jié)構(gòu),而很多軟件開發(fā)人員往往希望利用 XML 來觀察數(shù)據(jù)的情況,而標簽就是協(xié)助他們更好的完成這樣的工作。所以,一般來講,標簽需要盡可能的有意義,由于 C 和 R 可以比較明確的表示 Column 和 Row,并且他們在數(shù)據(jù)傳輸過程中是重復的最多的(占傳輸標簽總數(shù)的80%),所以我們進行了上述的改動。但是對于像 Cells 這樣的標簽,由于其重復率不是很高,而且我們需要這個標簽具有字面上的意義,所以,類似于這樣的情況,我們給予保留。

          解決方案五: 緩存機制

          前面介紹的四種提高效率的方法都是基于 XML 傳輸?shù)模簿褪钦f,都是在如何提高 XML 傳輸效率上進行介紹的。而第五種機制對于任何的軟件解決方案都適用,而對于 Web Service 解決方案來講,更是具有錦上添花的作用。緩存機制最通用的一個思想是,將使用次數(shù)比較多的數(shù)據(jù)緩存起來,如果再有相同請求時,就將緩存中的數(shù)據(jù)返回。這樣會減少數(shù)據(jù)邏輯處理所帶來的時間。我們以用戶的一次刷新數(shù)據(jù)的操作為例,介紹一種比較通用的緩存方式,如圖:


          圖 3. 某數(shù)據(jù)刷新操作的緩存流程
          某數(shù)據(jù)刷新操作的緩存流程

          由圖中可知,當用戶進行刷新操作時,服務(wù)器端先檢查請求 XML,取出要刷新數(shù)據(jù)源的 CUID。根據(jù)該 CUID,系統(tǒng)檢查在緩存中是否存在該 CUID 對應(yīng)的數(shù)據(jù)對象,如果有,則取出其刷新狀態(tài),并與對應(yīng)該 CUID 的數(shù)據(jù)源的刷新狀態(tài)進行比較。如果比較一致,則直接返回數(shù)據(jù)給客戶端,如果比較不一致,則需要打開數(shù)據(jù)源進行重新刷新,并將刷新以后的結(jié)果集的對象保存在緩存中。如果緩存已經(jīng)滿了,則利用最近最少使用原則,清除緩存中的一部分數(shù)據(jù)對象。另外,緩存的大小設(shè)置是可以通過屬性文件進行設(shè)置的,在程序中,對緩存進行初始化時,首先讀取了屬性文件來進行緩存大小的設(shè)定。緩存數(shù)據(jù)的好處在于,在對數(shù)據(jù)進行多次重復刷新時,系統(tǒng)不需要重新打開數(shù)據(jù)源(有時候連接并打開數(shù)據(jù)源是非常消耗時間的),從而提高了系統(tǒng)的效率。
          優(yōu)點:
          對于多次的相同方式的數(shù)據(jù)操作,數(shù)據(jù)直接從緩存返回,可以很大程度的提高系統(tǒng)效率。
          缺點:
          編程的工作量比較大,需要測試的部分比較多。
          應(yīng)用場景:
          一般的 Web Service 部署程序都可以采用緩存機制的處理。

          其他解決方案

          對于 Web Service 服務(wù)器,各個廠商都提供了很多服務(wù)器設(shè)置,以提高 Web Service 的性能和效率。具體請參考相關(guān)服務(wù)器的文檔。

          小結(jié)

          對于提高 Web Service 的效率,本文給出了一些解決方案,從各個不同方面對 Web Service 效率的提高進行了討論。對于不同的應(yīng)用系統(tǒng),應(yīng)該酌情分析系統(tǒng)建立的環(huán)境以及系統(tǒng)的使用人群和范圍,以最終決定采用何種解決方案。

          posted on 2009-11-23 22:37 大魚 閱讀(451) 評論(0)  編輯  收藏 所屬分類: j2ee

          主站蜘蛛池模板: 镶黄旗| 永登县| 南开区| 来宾市| 仪征市| 台南县| 奈曼旗| 柘城县| 宜宾县| 绥德县| 富平县| 宜川县| 香格里拉县| 天台县| 漯河市| 玉山县| 将乐县| 额尔古纳市| 故城县| 蒲城县| 遵义县| 安溪县| 启东市| 额尔古纳市| 四子王旗| 灵台县| 衡阳县| 吐鲁番市| 同仁县| 平塘县| 洪洞县| 岳阳市| 金塔县| 七台河市| 宁城县| 溧水县| 乐陵市| 旺苍县| 惠水县| 和田县| 日喀则市|