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

SpringCloud中的灰度路由使用詳解

 更新時間:2023年08月31日 11:07:53   作者:韓_師兄  
這篇文章主要介紹了SpringCloud中的灰度路由使用詳解,在微服務(wù)中,?通常為了高可用,?同一個服務(wù)往往采用集群方式部署,?即同時存在幾個相同的服務(wù),而灰度的核心就?是路由,?通過我們特定的策略去調(diào)用目標(biāo)服務(wù)線路,需要的朋友可以參考下

1 灰度路由的簡介

在微服務(wù)中, 通常為了高可用, 同一個服務(wù)往往采用集群方式部署, 即同時存在幾個相同的服務(wù),而灰度的核心就 是路由, 通過我們特定的策略去調(diào)用目標(biāo)服務(wù)線路

灰度發(fā)布(又名金絲雀發(fā)布)是指在黑與白之間,能夠平滑過渡的一種發(fā)布方式。

在其上可以進(jìn)行A/B testing,即讓一部分用戶繼續(xù)用產(chǎn)品特性A,一部分用戶開始用產(chǎn)品特性B,如果用戶對B沒有什么反對意見,那么逐步擴(kuò)大范圍,把所有用戶都遷移到B上面來。

灰度發(fā)布可以保證整體系統(tǒng)的穩(wěn)定,在初始灰度的時候就可以發(fā)現(xiàn)、調(diào)整問題,以保證其影響度.

關(guān)于SpringCloud微服務(wù)+nacos的灰度發(fā)布實(shí)現(xiàn), 首先微服務(wù)中之間的調(diào)用通常使用Feign方式和Resttemplate方式(較少使用),因此 , 我們需要指定服務(wù)之間的調(diào)用, 首先要給各個服務(wù)添加唯一標(biāo)識, 我們可是使用一些特殊的標(biāo)記, 如版本號version等, 其次,要干預(yù)微服務(wù)中Ribbon的默認(rèn)輪詢調(diào)用機(jī)制, 我們需要根據(jù)微服務(wù)的版本等不同, 來進(jìn)行調(diào)用, 最后, 在服務(wù)之間, 需要傳遞調(diào)用鏈路的信息, 我們可以在請求頭中,添加調(diào)用鏈路的信息.

整理思路為:

  • 在請求頭中添加調(diào)用鏈路信息
  • 微服務(wù)之間調(diào)用時,使用feign攔截器,增強(qiáng)請求頭
  • 微服務(wù)調(diào)用選擇時,根據(jù)指定的策略(如唯一標(biāo)識版本等)從nacos中獲取指定的服務(wù),調(diào)用

2 灰度路由的使用

基礎(chǔ)服務(wù)

一個父服務(wù),一個工具服務(wù)

父服務(wù)

pom依賴

   <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.4.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <!--spring cloud 版本-->
    <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
  </properties>
  <dependencies>
    <!--nacos-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
      <version>0.2.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba.nacos</groupId>
      <artifactId>nacos-client</artifactId>
      <version>1.1.0</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
    <!--feign-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
      <exclusions>
        <exclusion>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-loadbalancer</artifactId>
    </dependency>
  </dependencies>

工具服務(wù)

feign攔截器

@Slf4j
public class FeignInterceptor implements RequestInterceptor {
    /**
     * feign接口攔截, 添加上灰度路由請求頭
     * @param template
     */
    @Override
    public void apply(RequestTemplate template) {
        String header = null;
        try {
            header = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .getRequest().getHeader("gray-route");
            if (null == header || header.isEmpty()) {
                return;
            }
        } catch (Exception e) {
            log.info("請求頭獲取失敗, 錯誤信息為: {}", e.getMessage());
        }
        template.header("gray-route", header);
    }
}

灰度路由屬性類

@Slf4j
public class FeignInterceptor implements RequestInterceptor {
    /**
     * feign接口攔截, 添加上灰度路由請求頭
     * @param template
     */
    @Override
    public void apply(RequestTemplate template) {
        String header = null;
        try {
            header = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .getRequest().getHeader("gray-route");
            if (null == header || header.isEmpty()) {
                return;
            }
        } catch (Exception e) {
            log.info("請求頭獲取失敗, 錯誤信息為: {}", e.getMessage());
        }
        template.header("gray-route", header);
    }
}

路由屬性類

@Data
@ConfigurationProperties(prefix = "spring.cloud.nacos.discovery.metadata.gray-route.route", ignoreUnknownFields = false)
@RefreshScope
public class RouteProp {
    /**
     * 本服務(wù)直接調(diào)用的所有服務(wù)的統(tǒng)一版本號
     */
    private String all;
    /**
     * 指定調(diào)用服務(wù)的版本  serviceA:v1 表示在調(diào)用時只會調(diào)用v1版本服務(wù)
     */
    private Map<String,String> custom;
}

灰度路由規(guī)則類(繼承ZoneAvoidanceRule類)

微服務(wù)在攔截處理后, Ribbon組件會從服務(wù)實(shí)例列表中獲取一個實(shí)現(xiàn)進(jìn)行轉(zhuǎn)發(fā), 且Ribbon默認(rèn)的規(guī)則是ZoneAvoidanceRule類, 我們定義自己的規(guī)則, 只需要繼承該類,重寫choose方法即可.

@Slf4j
public class GrayRouteRule extends ZoneAvoidanceRule {
    @Autowired
    protected GrayRouteProp grayRouteProperties;
    /**
     * 參考 {@link PredicateBasedRule#choose(Object)}
     *
     */
    @Override
    public Server choose(Object key) {
        // 根據(jù)灰度路由規(guī)則,過濾出符合規(guī)則的服務(wù) this.getServers()
        // 再根據(jù)負(fù)載均衡策略,過濾掉不可用和性能差的服務(wù),然后在剩下的服務(wù)中進(jìn)行輪詢  getPredicate().chooseRoundRobinAfterFiltering()
        Optional<Server> server = getPredicate()
                .chooseRoundRobinAfterFiltering(this.getServers(), key);
        return server.isPresent() ? server.get() : null;
    }
    /**
     * 灰度路由過濾服務(wù)實(shí)例
     *
     * 如果設(shè)置了期望版本, 則過濾出所有的期望版本 ,然后再走默認(rèn)的輪詢 如果沒有一個期望的版本實(shí)例,則不過濾,降級為原有的規(guī)則,進(jìn)行所有的服務(wù)輪詢。(灰度路由失效) 如果沒有設(shè)置期望版本
     * 則不走灰度路由,按原有輪詢機(jī)制輪詢所有
     */
    protected List<Server> getServers() {
        // 獲取spring cloud默認(rèn)負(fù)載均衡器
        ZoneAwareLoadBalancer lb = (ZoneAwareLoadBalancer) getLoadBalancer();
        // 獲取本次請求生效的灰度路由規(guī)則
        RouteProp routeRule = this.getGrayRoute();
        // 獲取本次請求期望的服務(wù)版本號
        String version = getDesiredVersion(routeRule, lb.getName());
        // 獲取所有待選的服務(wù)
        List<Server> allServers = lb.getAllServers();
        if (CollectionUtils.isEmpty(allServers)) {
            return new ArrayList<>();
        }
        // 如果沒有設(shè)置要訪問的版本,則不過濾,返回所有,走原有默認(rèn)的輪詢機(jī)制
        if (StringUtils.isEmpty(version)) {
            return allServers;
        }
        // 開始灰度規(guī)則匹配過濾
        List<Server> filterServer = new ArrayList<>();
        for (Server server : allServers) {
            // 獲取服務(wù)實(shí)例在注冊中心上的元數(shù)據(jù)
            Map<String, String> metadata = ((NacosServer) server).getMetadata();
            // 如果注冊中心上服務(wù)的版本標(biāo)簽和期望訪問的版本一致,則灰度路由匹配成功
            if (null != metadata && version.equals(metadata.get(GrayRouteProp.VERSION_KEY))) {
                filterServer.add(server);
            }
        }
        // 如果沒有匹配到期望的版本實(shí)例服務(wù),為了保證服務(wù)可用性,讓灰度規(guī)則失效,走原有的輪詢所有可用服務(wù)的機(jī)制
        if (CollectionUtils.isEmpty(filterServer)) {
            log.warn(String.format("沒有找到版本version[%s]的服務(wù)[%s],灰度路由規(guī)則降級為原有的輪詢機(jī)制!", version,
                    lb.getName()));
            filterServer = allServers;
        }
        return filterServer;
    }
    /**
     * 獲取本次請求 期望的服務(wù)版本號
     *
     * @param routeRule 生效的配置規(guī)則
     * @param appName 服務(wù)名
     */
    protected String getDesiredVersion(RouteProp routeRule, String appName) {
        // 取路由規(guī)則里指定要訪問的微服務(wù)的版本號
        String version = null;
        if (routeRule != null) {
            if (routeRule.getCustom() != null) {
                // 優(yōu)先取custom里指定版本
                version = routeRule.getCustom().get(appName);
            } else {
                // custom里沒有指定就找all里面設(shè)置的統(tǒng)一版本
                version = routeRule.getAll();
            }
        }
        return version;
    }
    /**
     * 獲取設(shè)置的灰度路由規(guī)則
     */
    protected RouteProp getGrayRoute() {
        // 確定路由規(guī)則(請求頭優(yōu)先,yml配置其次)
        RouteProp routeRule;
        String route_header = null;
        try {
            route_header = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .getRequest().getHeader(GrayRouteProp.GRAY_ROUTE);
        } catch (Exception e) {
            log.error("灰度路由從上下文獲取路由請求頭異常!");
        }
        if (!StringUtils.isEmpty(route_header)) {//header
            routeRule = JSONObject.parseObject(route_header, RouteProp.class);
        } else {
            // yml配置
            routeRule = grayRouteProperties.getRoute();
        }
        return routeRule;
    }
}

業(yè)務(wù)服務(wù)

一個client服務(wù);兩個consumer服務(wù),分版本v1和v2;兩個provider服務(wù),分版本v1和v2

client服務(wù)

Controller控制器

@RestController
@Slf4j
public class ACliController {
    @Autowired
    private ConsumerFeign consumerFeign;
    @GetMapping("/client")
    public String list() {
        String info = "我是客戶端,8000  ";
        log.info(info);
        String result = consumerFeign.list();
        return JSON.toJSONString(info + result);
    }
}

Feign接口

@FeignClient(value = "consumer-a")
public interface ConsumerFeign {
    @ResponseBody
    @GetMapping("/consumer")
    String list();
}

Application啟動器

@SpringBootApplication
@EnableFeignClients({"com.cf.client.feign"})
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

application.yml

server:
  port: 8000
spring:
  cloud:
    nacos:
      discovery:
        server-addr:  127.0.0.1:8848 # 配置nacos 服務(wù)端地址
        namespace: public
        metadata:
          # gray-route是灰度路由配置的開始
          gray-route:
            enable: true
            version: v1
  application:
    name: client-test # 服務(wù)名稱

pom依賴

  <!--自定義commons工具包-->
  <dependencies>
    <dependency>
      <groupId>com.cf</groupId>
      <artifactId>commons</artifactId>
      <version>0.0.1-SNAPSHOT</version>
    </dependency>
  </dependencies>

consumer1服務(wù)

Controller控制器

@RestController
@Slf4j
public class AConController {
    @Autowired
    private ProviderFeign providerFeign;
    @GetMapping("/consumer")
    public String list() {
        String info = "我是consumerA,8081    ";
        log.info(info);
        String result = providerFeign.list();
        return JSON.toJSONString(info + result);
    }
}

Feign接口

@FeignClient(value = "provider-a")
public interface ProviderFeign {
    @ResponseBody
    @GetMapping("/provider")
    String list();
}

Application啟動類

@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients({"com.cf.consumer.feign"})
public class AConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(AConsumerApplication.class, args);
    }
}

application.yml

server:
  port: 8081
spring:
  cloud:
    nacos:
      discovery:
        server-addr:  127.0.0.1:8848 # 配置nacos 服務(wù)端地址
        namespace: public
        metadata:
          # gray-route是灰度路由配置的開始
          gray-route:
            enable: true
            version: v1
  application:
    name: consumer-a # 服務(wù)名稱

pom依賴

  <dependencies>
    <dependency>
      <groupId>com.cf</groupId>
      <artifactId>commons</artifactId>
      <version>0.0.1-SNAPSHOT</version>
    </dependency>
  </dependencies>

consumer2服務(wù)

consumer2服務(wù)和consumer1服務(wù)一樣,只是灰度路由版本不一樣(同一個服務(wù)器時,其端口也不一致)

application.yml

server:
  port: 8082
spring:
  cloud:
    nacos:
      discovery:
        server-addr:  127.0.0.1:8848 # 配置nacos 服務(wù)端地址
        namespace: public
        metadata:
          # gray-route是灰度路由配置的開始
          gray-route:
            enable: true
            version: v2
  application:
    name: consumer-a # 服務(wù)名稱

provider1服務(wù)

Controller控制器

@RestController
@Slf4j
public class AProController {
    @GetMapping("/provider")
    public String list() {
        String info = "我是 providerA,9091  ";
        log.info(info);
        return JSON.toJSONString(info);
    }
}

Application啟動類

@EnableDiscoveryClient
@SpringBootApplication
public class AProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(AProviderApplication.class, args);
    }
}

application.yml

server:
  port: 9091
spring:
  cloud:
    nacos:
      discovery:
        server-addr:  127.0.0.1:8848 # 配置nacos 服務(wù)端地址
        namespace: public
        metadata:
          # gray-route是灰度路由配置的開始
          gray-route:
            enable: true
            version: v1
  application:
    name: provider-a # 服務(wù)名稱

provider2服務(wù)

provider2服務(wù)和provider1服務(wù)相比, 就是灰度路由版本不一致(同一個服務(wù)器時,其端口也不一致)

application.yml

server:
  port: 9091
spring:
  cloud:
    nacos:
      discovery:
        server-addr:  127.0.0.1:8848 # 配置nacos 服務(wù)端地址
        namespace: public
        metadata:
          # gray-route是灰度路由配置的開始
          gray-route:
            enable: true
            version: v2
  application:
    name: provider-a # 服務(wù)名稱

驗(yàn)證測試

  • 啟動本地nacos服務(wù)
  • 啟動五個項(xiàng)目服務(wù)
    • 此時,在nacos中,存在服務(wù)列表中存在三個, 分別是client-test服務(wù)(1個),provider-a服務(wù)(2個實(shí)例),consumer-a服務(wù)(2個實(shí)例)
  • 使用postman進(jìn)行測試

1 不指定請求頭灰度路由

"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerA,9091  \\\"\""
"我是客戶端,8000  \"我是consumerB,8082    \\\"我是 providerA,9091  \\\"\""
"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerB,9092     \\\"\""
"我是客戶端,8000  \"我是consumerB,8082    \\\"我是 providerB,9092     \\\"\""

調(diào)用四次, 采用的是Ribbon中默認(rèn)的輪詢策略.

2 指定請求頭灰度路由

請求頭中設(shè)置 gray-route = {"all":"v1"}

"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerA,9091  \\\"\""
"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerA,9091  \\\"\""
"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerA,9091  \\\"\""
"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerA,9091  \\\"\""

四次測試結(jié)果, 每個服務(wù)都是v1版本, 灰度路由生效.

請求頭中設(shè)置 {custom":{"consumer-a":"v1","provider-a":"v1"}}

"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerA,9091  \\\"\""
"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerA,9091  \\\"\""
"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerA,9091  \\\"\""
"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerA,9091  \\\"\""

四次測試結(jié)果, 每個服務(wù)都是v1版本, 灰度路由生效.

請求頭中設(shè)置 {custom":{"consumer-a":"v1","provider-a":"v2"}}

"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerB,9092     \\\"\""
"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerB,9092     \\\"\""
"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerB,9092     \\\"\""
"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerB,9092     \\\"\""

四次測試結(jié)果, consumer服務(wù)都是v1版本, provider服務(wù)都是版本2,灰度路由生效.

請求頭中設(shè)置{custom":{"consumer-a":"v1"}}

"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerA,9091  \\\"\""
"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerB,9092     \\\"\""
"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerA,9091  \\\"\""
"我是客戶端,8000  \"我是consumerA,8081    \\\"我是 providerB,9092     \\\"\""

四次測試結(jié)果, consumer服務(wù)都是v1版本, provider服務(wù)沒有指定,所以采用默認(rèn)輪詢機(jī)制,灰度路由生效

到此這篇關(guān)于SpringCloud中的灰度路由使用詳解的文章就介紹到這了,更多相關(guān)SpringCloud灰度路由內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Spring mvc DispatchServlet 實(shí)現(xiàn)機(jī)制

    詳解Spring mvc DispatchServlet 實(shí)現(xiàn)機(jī)制

    本篇文章主要介紹了詳解Spring mvc DispatchServlet 實(shí)現(xiàn)機(jī)制,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • 使用SpringAI整合Ollama實(shí)現(xiàn)工具鏈調(diào)用功能

    使用SpringAI整合Ollama實(shí)現(xiàn)工具鏈調(diào)用功能

    文章介紹了SpringAI的ToolCalling能力,允許大模型自主調(diào)用外部工具以完成多步驟任務(wù),具體而言,通過@Tool注解標(biāo)記方法,SpringAI自動解析生成JSONSchema,@Tools注解注冊多個工具,模型可自主選擇調(diào)用順序和組合,需要的朋友可以參考下
    2026-05-05
  • SpringCloud中的openFeign調(diào)用服務(wù)并傳參的過程

    SpringCloud中的openFeign調(diào)用服務(wù)并傳參的過程

    服務(wù)和服務(wù)之間通信,不僅僅是調(diào)用,往往在調(diào)用過程中還伴隨著參數(shù)傳遞,接下來重點(diǎn)來看看OpenFeign在調(diào)用服務(wù)時如何傳遞參數(shù),感興趣的朋友一起看看吧
    2023-11-11
  • maven配置多個倉庫的實(shí)現(xiàn)

    maven配置多個倉庫的實(shí)現(xiàn)

    本文主要介紹了maven配置多個倉庫的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • spring5 SAXParseException:cvc-elt.1: 找不到元素“beans 的聲明詳解

    spring5 SAXParseException:cvc-elt.1: 找不到元素“beans 的聲明詳解

    這篇文章主要給大家介紹了關(guān)于spring5 SAXParseException:cvc-elt.1: 找不到元素“beans 聲明的相關(guān)資料,需要的朋友可以參考下
    2020-08-08
  • Java 基于AQS實(shí)現(xiàn)一個同步器

    Java 基于AQS實(shí)現(xiàn)一個同步器

    這篇文章主要介紹了如何基于AQS實(shí)現(xiàn)一個同步器,幫助大家更好的理解和學(xué)習(xí)Java并發(fā),感興趣的朋友可以了解下
    2020-09-09
  • springboot項(xiàng)目讀取resources目錄下的文件的9種方式

    springboot項(xiàng)目讀取resources目錄下的文件的9種方式

    本文主要介紹了springboot項(xiàng)目讀取resources目錄下的文件的9種方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 使用JPA傳遞參數(shù)的方法

    使用JPA傳遞參數(shù)的方法

    這篇文章主要介紹了使用JPA傳遞參數(shù)的方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • IntelliJ?IDEA安裝與基礎(chǔ)配置指南

    IntelliJ?IDEA安裝與基礎(chǔ)配置指南

    IntelliJ?IDEA是一款由JetBrains公司開發(fā)的Java集成開發(fā)環(huán)境,支持Java、Kotlin、Groovy、Scala等多種編程語言,IntelliJ?IDEA作為一款強(qiáng)大的開發(fā)工具,被廣泛應(yīng)用于Java開發(fā)、Web開發(fā)、Android開發(fā)等領(lǐng)域,本文給大家介紹了IntelliJ?IDEA安裝與基礎(chǔ)配置
    2025-07-07
  • Java 泛型總結(jié)(一):基本用法與類型擦除

    Java 泛型總結(jié)(一):基本用法與類型擦除

    本文主要介紹了Java泛型的使用以及類型擦除相關(guān)的問題。具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03

最新評論

大安市| 铜川市| 伊春市| 宣威市| 安义县| 聂荣县| 宜春市| 凉山| 安康市| 花莲市| 西昌市| 同江市| 丹东市| 清苑县| 桃园市| 延川县| 张家港市| 玉山县| 兴安盟| 新野县| 浙江省| 全州县| 遂溪县| 泾阳县| 平潭县| 延安市| 碌曲县| 黑山县| 获嘉县| 蚌埠市| 潞城市| 枝江市| 瑞安市| 汉寿县| 阿拉善盟| 玉山县| 哈尔滨市| 象山县| 临海市| 大宁县| 溧水县|