最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入探討Golang中如何進(jìn)行并發(fā)發(fā)送HTTP請(qǐng)求

 更新時(shí)間:2024年01月16日 08:19:19   作者:海擁  
在?Golang?領(lǐng)域,并發(fā)發(fā)送?HTTP?請(qǐng)求是優(yōu)化?Web?應(yīng)用程序的一項(xiàng)重要技能,本文探討了實(shí)現(xiàn)此目的的各種方法,文中的示例代碼講解詳細(xì),希望對(duì)大家有所幫助

在 Golang 領(lǐng)域,并發(fā)發(fā)送 HTTP 請(qǐng)求是優(yōu)化 Web 應(yīng)用程序的一項(xiàng)重要技能。本文探討了實(shí)現(xiàn)此目的的各種方法,從基本的 goroutine 到涉及通道和sync.WaitGroup 的高級(jí)技術(shù)。我們將深入研究并發(fā)環(huán)境中性能和錯(cuò)誤處理的最佳實(shí)踐,為你提供提高 Go 應(yīng)用程序速度和可靠性的策略。讓我們深入探討 Golang 中并發(fā) HTTP 請(qǐng)求的世界!

使用 Goroutines 的基本方法

當(dāng)談到在 Golang 中實(shí)現(xiàn)并發(fā)時(shí),最直接的方法是使用 goroutine。這些是 Go 中并發(fā)的構(gòu)建塊,提供了一種簡(jiǎn)單而強(qiáng)大的并發(fā)執(zhí)行函數(shù)的方法。

Goroutine 入門

要啟動(dòng)一個(gè) goroutine,只需在函數(shù)調(diào)用前加上go關(guān)鍵字即可。這會(huì)將函數(shù)作為 goroutine 啟動(dòng),從而允許主程序繼續(xù)獨(dú)立運(yùn)行。這就像開始一項(xiàng)任務(wù)并繼續(xù)前進(jìn)而不等待它完成。

例如,考慮發(fā)送 HTTP 請(qǐng)求的場(chǎng)景。通常,你會(huì)調(diào)用類似 的函數(shù)sendRequest(),并且你的程序?qū)⒌却摵瘮?shù)完成。使用 goroutine,你可以同時(shí)執(zhí)行此操作:

go sendRequest("http://example.com")

處理多個(gè)請(qǐng)求

假設(shè)你有一個(gè) URL 列表,并且需要向每個(gè) URL 發(fā)送一個(gè) HTTP 請(qǐng)求。如果沒有 goroutine,你的程序?qū)⒁粋€(gè)接一個(gè)地發(fā)送這些請(qǐng)求,這非常耗時(shí)。使用 goroutine,你幾乎可以同時(shí)發(fā)送它們:

urls := []string{"http://example.com", "http://another.com", ...}  
for _, url := range urls {  
go sendRequest(url)  
}

這個(gè)循環(huán)為每個(gè) URL 啟動(dòng)一個(gè)新的 goroutine,大大減少了程序發(fā)送所有請(qǐng)求所需的時(shí)間。

并發(fā) HTTP 請(qǐng)求的方法

在本節(jié)中,我們將深入研究在 Go 中并發(fā)處理 HTTP 請(qǐng)求的各種方法。每種方法都有其獨(dú)特的特點(diǎn),了解這些可以幫助你選擇適合特定需求的正確方法。

我們使用 insrequester 包(開源請(qǐng)求程序)來(lái)處理本文中提到的 HTTP請(qǐng)求

基本 Goroutine

在 Go 中并發(fā)發(fā)送 HTTP 請(qǐng)求的最簡(jiǎn)單方法是使用 goroutine。Goroutines 是由 Go 運(yùn)行時(shí)管理的輕量級(jí)線程。這是一個(gè)基本示例:

requester := insrequester.NewRequester().Load()  
  
urls := []string{"http://example.com", "http://example.org", "http://example.net"}  
for _, url := range urls {  
go requester.Get(insrequester.RequestEntity{Endpoint: url})  
}  
  
time.Sleep(2 * time.Second) // 等待 goroutine 完成

這種方法很簡(jiǎn)單,但一旦啟動(dòng)就缺乏對(duì) goroutine 的控制。通過(guò)這種方式無(wú)法獲取Get方法的返回值。你需要睡眠大約一段時(shí)間來(lái)等待所有 goroutine。即使你調(diào)用 sleep,你可能仍然不確定它們是否完成。

WaitGroup

為了改進(jìn)基本的 goroutine,sync.WaitGroup可用于更好的同步。它等待 goroutine 集合完成執(zhí)行:

requester := insrequester.NewRequester().Load()  
wg := sync.WaitGroup{}  
  
urls := []string{"http://example.com", "http://example.org", "http://example.net"}  
wg.Add(len(urls))  
  
for _, url := range urls {  
go requester.Get(insrequester.RequestEntity{Endpoint: url})  
}  
  
wg.Wait() //等待所有要完成的 goroutine

這確保了 main 函數(shù)等待所有 HTTP 請(qǐng)求完成。

Channels

Channels 是 Go 中用于 goroutine 之間通信的強(qiáng)大功能。它們可用于從多個(gè) HTTP 請(qǐng)求收集數(shù)據(jù):

requester := insrequester.NewRequester().Load()  
  
urls := []string{"http://example.com", "http://example.org", "http://example.net"}  
ch := make(chan string, len(urls))  
  
for _, url := range urls {  
go func() {  
res, _ := requester.Get(insrequester.RequestEntity{Endpoint: url})  
ch <- fmt.Sprintf("%s: %d", url, res.StatusCode)  
}()  
}  
  
for range urls {  
response := <-ch  
fmt.Println(response)  
}

通道不僅可以同步 goroutine,還可以促進(jìn)它們之間的數(shù)據(jù)傳遞。

Worker Pools

Worker Pool 是一種模式,其中創(chuàng)建固定數(shù)量的工作人員(goroutines)來(lái)處理可變數(shù)量的任務(wù)。這有助于限制并發(fā) HTTP 請(qǐng)求的數(shù)量,從而防止資源耗盡。

以下是在 Go 中實(shí)現(xiàn) Worker Pool 的方法:

// 定義 Job 結(jié)構(gòu)體,包含一個(gè) URL 字段
type Job struct {
	URL string
}

// worker 函數(shù)用于處理作業(yè),接收請(qǐng)求者、作業(yè)通道、結(jié)果通道和等待組作為參數(shù)
func worker(requester *insrequester.Request, jobs <-chan Job, results chan<- *http.Response, wg *sync.WaitGroup) {
	for job := range jobs {
		// 使用請(qǐng)求者獲取 URL 對(duì)應(yīng)的響應(yīng)
		res, _ := requester.Get(insrequester.RequestEntity{Endpoint: job.URL})
		// 將結(jié)果發(fā)送到結(jié)果通道,并減少等待組計(jì)數(shù)
		results <- res
		wg.Done()
	}
}

func main() {
	// 創(chuàng)建并加載請(qǐng)求者
	requester := insrequester.NewRequester().Load()

	// 定義要處理的 URL 列表
	urls := []string{"http://example.com", "http://example.org", "http://example.net"}
	// 定義工作池中的工作者數(shù)量
	numWorkers := 2

	// 創(chuàng)建作業(yè)通道和結(jié)果通道
	jobs := make(chan Job, len(urls))
	results := make(chan *http.Response, len(urls))
	var wg sync.WaitGroup

	// 啟動(dòng)工作者
	for w := 0; w < numWorkers; w++ {
		go worker(requester, jobs, results, &wg)
	}

	// 將作業(yè)發(fā)送到工作者池
	wg.Add(len(urls))
	for _, url := range urls {
		jobs <- Job{URL: url}
	}
	close(jobs)
	wg.Wait()

	// 收集結(jié)果并輸出
	for i := 0; i < len(urls); i++ {
		fmt.Println(<-results)
	}
}

使用工作池可以讓你有效地管理大量并發(fā) HTTP 請(qǐng)求。它是一個(gè)可擴(kuò)展的解決方案,可以根據(jù)工作負(fù)載和系統(tǒng)容量進(jìn)行調(diào)整,從而優(yōu)化資源利用率并提高整體性能。

使用通道限制 Goroutine

該方法使用通道創(chuàng)建類似信號(hào)量的機(jī)制來(lái)限制并發(fā) goroutine 的數(shù)量。它在你需要限制 HTTP 請(qǐng)求以避免服務(wù)器不堪重負(fù)或達(dá)到速率限制的情況下非常有效。

以下是實(shí)現(xiàn)它的方法:

// 創(chuàng)建請(qǐng)求者并加載配置
requester := insrequester.NewRequester().Load()

// 定義要處理的 URL 列表
urls := []string{"http://example.com", "http://example.org", "http://example.net"}
maxConcurrency := 2 // 限制并發(fā)請(qǐng)求的數(shù)量

// 創(chuàng)建一個(gè)用于限制并發(fā)請(qǐng)求的通道
limiter := make(chan struct{}, maxConcurrency)

// 遍歷 URL 列表
for _, url := range urls {
    limiter <- struct{}{} // 獲取一個(gè)令牌。在這里等待令牌從限制器釋放
    go func(url string) {
        defer func() { <-limiter }() // 釋放令牌
        // 使用請(qǐng)求者進(jìn)行 POST 請(qǐng)求
        requester.Post(insrequester.RequestEntity{Endpoint: url})
    }(url)
}

// 等待所有 goroutine 完成
for i := 0; i < cap(limiter); i++ {
    limiter <- struct{}{}
}

在這種情況下使用延遲至關(guān)重要。如果將 <-limiter語(yǔ)句放在 Post 方法之后,并且 Post 方法觸發(fā)恐慌或類似異常,則 <-limiter行將不會(huì)被執(zhí)行。這可能會(huì)導(dǎo)致無(wú)限等待,因?yàn)樾盘?hào)量令牌永遠(yuǎn)不會(huì)被釋放,最終導(dǎo)致超時(shí)問(wèn)題。

使用信號(hào)量限制 Goroutines

sync/semaphore 包提供了一種干凈有效的方法來(lái)限制并發(fā)運(yùn)行的 goroutine 數(shù)量。當(dāng)你想要更系統(tǒng)地管理資源分配時(shí),此方法特別有用。

// 創(chuàng)建請(qǐng)求者并加載配置
requester := insrequester.NewRequester().Load()

// 定義要處理的 URL 列表
urls := []string{"http://example.com", "http://example.org", "http://example.net"}
maxConcurrency := int64(2) // 設(shè)置最大并發(fā)請(qǐng)求數(shù)量

// 創(chuàng)建一個(gè)帶權(quán)重的信號(hào)量
sem := semaphore.NewWeighted(maxConcurrency)
ctx := context.Background()

// 遍歷 URL 列表
for _, url := range urls {
    // 在啟動(dòng) goroutine 前獲取信號(hào)量權(quán)重
    if err := sem.Acquire(ctx, 1); err != nil {
       fmt.Printf("無(wú)法獲取信號(hào)量:%v\n", err)
       continue
    }

    go func(url string) {
       defer sem.Release(1) // 在完成時(shí)釋放信號(hào)量權(quán)重
       // 使用請(qǐng)求者獲取 URL 對(duì)應(yīng)的響應(yīng)
       res, _ := requester.Get(insrequester.RequestEntity{Endpoint: url})
       fmt.Printf("%s: %d\n", url, res.StatusCode)
    }(url)
}

// 等待所有 goroutine 釋放它們的信號(hào)量權(quán)重
if err := sem.Acquire(ctx, maxConcurrency); err != nil {
    fmt.Printf("等待時(shí)無(wú)法獲取信號(hào)量:%v\n", err)
}

與手動(dòng)管理通道相比,這種使用信號(hào)量包的方法提供了一種更加結(jié)構(gòu)化和可讀的并發(fā)處理方式。當(dāng)處理復(fù)雜的同步要求或需要更精細(xì)地控制并發(fā)級(jí)別時(shí),它特別有用。

那么,最好的方法是什么

在探索了 Go 中處理并發(fā) HTTP 請(qǐng)求的各種方法之后,問(wèn)題出現(xiàn)了:最好的方法是什么?正如軟件工程中經(jīng)常出現(xiàn)的情況一樣,答案取決于應(yīng)用程序的具體要求和約束。讓我們考慮確定最合適方法的關(guān)鍵因素:

評(píng)估你的需求

  • 請(qǐng)求規(guī)模:如果你正在處理大量請(qǐng)求,工作池或基于信號(hào)量的方法可以更好地控制資源使用。
  • 錯(cuò)誤處理:如果強(qiáng)大的錯(cuò)誤處理至關(guān)重要,那么使用通道或信號(hào)量包可以提供更結(jié)構(gòu)化的錯(cuò)誤管理。
  • 速率限制:對(duì)于需要遵守速率限制的應(yīng)用程序,使用通道或信號(hào)量包限制 goroutine 可能是有效的。
  • 復(fù)雜性和可維護(hù)性:考慮每種方法的復(fù)雜性。雖然渠道提供了更多控制,但它們也增加了復(fù)雜性。另一方面,信號(hào)量包提供了更直接的解決方案。

錯(cuò)誤處理

由于 Go 中并發(fā)執(zhí)行的性質(zhì),goroutines 中的錯(cuò)誤處理是一個(gè)棘手的話題。由于 goroutine 獨(dú)立運(yùn)行,管理和傳播錯(cuò)誤可能具有挑戰(zhàn)性,但對(duì)于構(gòu)??建健壯的應(yīng)用程序至關(guān)重要。以下是一些有效處理并發(fā) Go 程序中錯(cuò)誤的策略:

集中誤差通道

一種常見的方法是使用集中式錯(cuò)誤通道,所有 goroutine 都可以通過(guò)該通道發(fā)送錯(cuò)誤。然后,主 goroutine 可以監(jiān)聽該通道并采取適當(dāng)?shù)牟僮鳌?/p>

func worker(errChan chan<- error) {
    // 執(zhí)行任務(wù)
    if err := doTask(); err != nil {
        errChan <- err // 將任何錯(cuò)誤發(fā)送到錯(cuò)誤通道
    }
}

func main() {
    errChan := make(chan error, 1) // 用于存儲(chǔ)錯(cuò)誤的緩沖通道

    go worker(errChan)

    if err := <-errChan; err != nil {
        // 處理錯(cuò)誤
        log.Printf("發(fā)生錯(cuò)誤:%v", err)
    }
}

或者你可以在不同的 goroutine 中監(jiān)聽 errChan。

func worker(errChan chan<- error, job Job) {
 // 執(zhí)行任務(wù)
 if err := doTask(job); err != nil {
  errChan <- err // 將任何錯(cuò)誤發(fā)送到錯(cuò)誤通道
 }
}

func listenErrors(done chan struct{}, errChan <-chan error) {
 for {
  select {
  case err := <-errChan:
   // 處理錯(cuò)誤
  case <-done:
   return
  }
 }
}

func main() {
 errChan := make(chan error, 1000) // 存儲(chǔ)錯(cuò)誤的通道
 done := make(chan struct{})       // 用于通知 goroutine 停止的通道

 go listenErrors(done, errChan)
 
 for _, job := range jobs {
   go worker(errChan, job)
 }

 // 等待所有 goroutine 完成(具體方式需要根據(jù)代碼的實(shí)際情況進(jìn)行實(shí)現(xiàn))
 done <- struct{}{} // 通知 goroutine 停止監(jiān)聽錯(cuò)誤
}

Error Group

golang.org/x/sync/errgroup 包提供了一種便捷的方法來(lái)對(duì)多個(gè) goroutine 進(jìn)行分組并處理它們產(chǎn)生的任何錯(cuò)誤。

errgroup.Group確保一旦任何 goroutine 發(fā)生錯(cuò)誤,所有后續(xù)操作都將被取消。

import "golang.org/x/sync/errgroup"

func main() {
    g, ctx := errgroup.WithContext(context.Background())

    urls := []string{"http://example.com", "http://example.org"}
    for _, url := range urls {
        // 為每個(gè) URL 啟動(dòng)一個(gè) goroutine
        g.Go(func() error {
            // 替換為實(shí)際的 HTTP 請(qǐng)求邏輯
            _, err := fetchURL(ctx, url)
            return err
        })
    }

    // 等待所有請(qǐng)求完成
    if err := g.Wait(); err != nil {
        log.Printf("發(fā)生錯(cuò)誤:%v", err)
    }
}

這種方法簡(jiǎn)化了錯(cuò)誤處理,特別是在處理大量 goroutine 時(shí)。

包裝 Goroutine

另一種策略是將每個(gè) goroutine 包裝在一個(gè)處理其錯(cuò)誤的函數(shù)中。這種封裝可以包括從恐慌或其他錯(cuò)誤管理邏輯中恢復(fù)。

func work() error {
  // 進(jìn)行一些工作
  return err
}

func main() {
 go func() {
   err := work()
   if err != nil {
     // 處理錯(cuò)誤
   }
 }()

 // 等待工作完成的某種方式
}

綜上所述,Go 并發(fā)編程中錯(cuò)誤處理策略的選擇取決于應(yīng)用程序的具體要求和上下文。無(wú)論是通過(guò)集中式錯(cuò)誤通道、專用錯(cuò)誤處理 goroutine、使用錯(cuò)誤組,還是將 goroutine 包裝在錯(cuò)誤管理函數(shù)中,每種方法都有自己的優(yōu)點(diǎn)和權(quán)衡。

總結(jié)

總之,本文探討了在 Golang 中并發(fā)發(fā)送 HTTP 請(qǐng)求的各種方法,這是優(yōu)化 Web 應(yīng)用程序的一項(xiàng)關(guān)鍵技能。我們已經(jīng)討論了基本的 goroutine、sync.WaitGroup、通道、工作池以及限制 goroutine 的方法。每種方法都有其獨(dú)特的特點(diǎn),可以根據(jù)特定的應(yīng)用要求進(jìn)行選擇。

此外,本文還強(qiáng)調(diào)了并發(fā) Go 程序中錯(cuò)誤處理的重要性。管理并發(fā)環(huán)境中的錯(cuò)誤可能具有挑戰(zhàn)性,但對(duì)于構(gòu)建健壯的應(yīng)用程序至關(guān)重要。已經(jīng)討論了使用集中式錯(cuò)誤通道、errgroup 包或使用錯(cuò)誤處理邏輯包裝 goroutine 等策略來(lái)幫助開發(fā)人員有效地處理錯(cuò)誤。

最終,在 Go 中處理并發(fā) HTTP 請(qǐng)求的最佳方法的選擇取決于請(qǐng)求規(guī)模、錯(cuò)誤處理要求、速率限制以及代碼的整體復(fù)雜性和可維護(hù)性等因素。開發(fā)人員在應(yīng)用程序中實(shí)現(xiàn)并發(fā)功能時(shí)應(yīng)仔細(xì)考慮這些因素。

以上就是深入探討Golang中如何進(jìn)行并發(fā)發(fā)送HTTP請(qǐng)求的詳細(xì)內(nèi)容,更多關(guān)于Go并發(fā)發(fā)送HTTP請(qǐng)求的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go語(yǔ)言defer的一些神奇規(guī)則示例詳解

    Go語(yǔ)言defer的一些神奇規(guī)則示例詳解

    這篇文章主要為大家介紹了Go語(yǔ)言defer的一些神奇規(guī)則示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 一文帶你了解Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)strings的常用函數(shù)和方法

    一文帶你了解Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)strings的常用函數(shù)和方法

    strings?庫(kù)包含了許多高效的字符串常用操作的函數(shù)和方法,巧用這些函數(shù)與方法,能極大的提高我們程序的性能。本文就來(lái)和大家分享一下Go標(biāo)準(zhǔn)庫(kù)strings的常用函數(shù)和方法,希望對(duì)大家有所幫助
    2022-11-11
  • 淺談Go中數(shù)字轉(zhuǎn)換字符串的正確姿勢(shì)

    淺談Go中數(shù)字轉(zhuǎn)換字符串的正確姿勢(shì)

    這篇文章主要介紹了淺談Go中數(shù)字轉(zhuǎn)換字符串的正確姿勢(shì),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Go?gRPC服務(wù)雙向流式RPC教程

    Go?gRPC服務(wù)雙向流式RPC教程

    這篇文章主要為大家介紹了Go?gRPC服務(wù)雙向流式RPC教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • golang字符串轉(zhuǎn)64位整數(shù)的示例代碼

    golang字符串轉(zhuǎn)64位整數(shù)的示例代碼

    這篇文章主要介紹了golang字符串轉(zhuǎn)64位整數(shù),在Go語(yǔ)言中,可以使用strconv包中的ParseInt函數(shù)將字符串轉(zhuǎn)換為64位整數(shù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • 深入理解Go設(shè)計(jì)模式之代理模式

    深入理解Go設(shè)計(jì)模式之代理模式

    代理模式是一種結(jié)構(gòu)型設(shè)計(jì)模式,?其中代理控制著對(duì)于原對(duì)象的訪問(wèn),?并允許在將請(qǐng)求提交給原對(duì)象的前后進(jìn)行一些處理,從而增強(qiáng)原對(duì)象的邏輯處理,這篇文章主要來(lái)學(xué)習(xí)一下代理模式的構(gòu)成和用法,需要的朋友可以參考下
    2023-05-05
  • Go語(yǔ)言JSON編解碼神器之marshal的運(yùn)用

    Go語(yǔ)言JSON編解碼神器之marshal的運(yùn)用

    這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中JSON編解碼神器——marshal的運(yùn)用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-09-09
  • Go語(yǔ)言的WebAssembly實(shí)戰(zhàn)開發(fā)

    Go語(yǔ)言的WebAssembly實(shí)戰(zhàn)開發(fā)

    Go語(yǔ)言的WebAssembly支持為Web開發(fā)帶來(lái)了新的可能性,本文主要介紹了Go語(yǔ)言與WebAssembly的結(jié)合,內(nèi)容包括編譯方法、JavaScript交互、性能優(yōu)化技巧和實(shí)戰(zhàn)案例,感興趣的可以了解一下
    2026-05-05
  • 深入淺出Go:掌握基礎(chǔ)知識(shí)的關(guān)鍵要點(diǎn)

    深入淺出Go:掌握基礎(chǔ)知識(shí)的關(guān)鍵要點(diǎn)

    Go是一種開源的編程語(yǔ)言,由Google開發(fā),它具有簡(jiǎn)潔、高效、并發(fā)性強(qiáng)的特點(diǎn),適用于構(gòu)建可靠的、高性能的軟件系統(tǒng),本文將介紹Go的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2023-10-10
  • Go語(yǔ)言入門Go?Web?Fiber框架快速了解

    Go語(yǔ)言入門Go?Web?Fiber框架快速了解

    這篇文章主要為大家介紹了Go語(yǔ)言入門Go?Web?Fiber框架的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05

最新評(píng)論

留坝县| 六枝特区| 休宁县| 曲靖市| 西城区| 咸丰县| 射阳县| 利津县| 罗甸县| 阳谷县| 涪陵区| 精河县| 邛崃市| 洱源县| 辰溪县| 涡阳县| 曲阳县| 沙田区| 双牌县| 且末县| 和龙市| 桑日县| 孝义市| 章丘市| 咸阳市| 图木舒克市| 朝阳市| 建平县| 德昌县| 腾冲县| 垣曲县| 深州市| 咸宁市| 黎平县| 陇西县| 霍邱县| 富阳市| 江安县| 来凤县| 浮山县| 宁河县|