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

SpringBoot與gRPC2.0集成的實(shí)現(xiàn)示例

 更新時(shí)間:2026年04月13日 08:31:36   作者:亞歷克斯神  
本文主要介紹了SpringBoot與gRPC2.0集成,包括HTTP/2支持、ProtocolBuffers增強(qiáng)、服務(wù)定義改進(jìn)等內(nèi)容,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

gRPC 是 Google 開源的高性能、通用的 RPC 框架,它基于 HTTP/2 協(xié)議,使用 Protocol Buffers 作為序列化格式。gRPC 2.0 帶來了許多新特性和改進(jìn),本文將深入探討 Spring Boot 與 gRPC 2.0 的集成方法和最佳實(shí)踐,幫助你構(gòu)建高性能的微服務(wù)通信系統(tǒng)。

1. gRPC 2.0 新特性

1.1 HTTP/2 支持

gRPC 2.0 基于 HTTP/2 協(xié)議,提供了以下優(yōu)勢(shì):

  • 多路復(fù)用:在單個(gè)連接上同時(shí)發(fā)送多個(gè)請(qǐng)求
  • 頭部壓縮:減少網(wǎng)絡(luò)傳輸開銷
  • 服務(wù)器推送:服務(wù)器可以主動(dòng)向客戶端推送數(shù)據(jù)
  • 流控:控制數(shù)據(jù)傳輸速率

1.2 Protocol Buffers 增強(qiáng)

gRPC 2.0 使用 Protocol Buffers 3.0+ 作為序列化格式,提供了以下改進(jìn):

  • 更簡(jiǎn)潔的語法:簡(jiǎn)化了消息定義
  • 更好的向后兼容性:支持字段的添加和刪除
  • 更豐富的類型:支持更多的數(shù)據(jù)類型
  • 性能優(yōu)化:序列化和反序列化速度更快

1.3 服務(wù)定義改進(jìn)

gRPC 2.0 改進(jìn)了服務(wù)定義語法,提供了更靈活的服務(wù)定義方式:

  • 支持流式 RPC:包括服務(wù)器流、客戶端流和雙向流
  • 支持超時(shí)和取消:可以設(shè)置 RPC 超時(shí)和取消操作
  • 支持元數(shù)據(jù):可以傳遞自定義元數(shù)據(jù)
  • 支持錯(cuò)誤處理:提供更豐富的錯(cuò)誤處理機(jī)制

1.4 其他新特性

  • 健康檢查:內(nèi)置健康檢查機(jī)制
  • 負(fù)載均衡:支持客戶端負(fù)載均衡
  • 名稱解析:支持多種名稱解析方式
  • 安全傳輸:支持 TLS 加密

2. Spring Boot 與 gRPC 集成

2.1 添加依賴

<dependency>
    <groupId>net.devh</groupId>
    <artifactId>grpc-server-spring-boot-starter</artifactId>
    <version>2.14.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>net.devh</groupId>
    <artifactId>grpc-client-spring-boot-starter</artifactId>
    <version>2.14.0.RELEASE</version>
</dependency>

2.2 定義服務(wù)

// user.proto
syntax = "proto3";
package com.example.grpc;
option java_package = "com.example.grpc";
option java_outer_classname = "UserProto";
message User {
    int64 id = 1;
    string name = 2;
    string email = 3;
}
message GetUserRequest {
    int64 id = 1;
}
message GetUserResponse {
    User user = 1;
}
message ListUsersRequest {
}
message ListUsersResponse {
    repeated User users = 1;
}
service UserService {
    rpc GetUser(GetUserRequest) returns (GetUserResponse);
    rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
    rpc CreateUser(User) returns (User);
}

2.3 生成代碼

使用 Maven 插件生成 gRPC 代碼:

<plugin>
    <groupId>org.xolstice.maven.plugins</groupId>
    <artifactId>protobuf-maven-plugin</artifactId>
    <version>0.6.1</version>
    <configuration>
        <protocArtifact>com.google.protobuf:protoc:3.21.12:exe:${os.detected.classifier}</protocArtifact>
        <pluginId>grpc-java</pluginId>
        <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.54.1:exe:${os.detected.classifier}</pluginArtifact>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
                <goal>compile-custom</goal>
            </goals>
        </execution>
    </executions>
</plugin>

2.4 實(shí)現(xiàn)服務(wù)

@GrpcService
public class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase {
    private final Map<Long, User> users = new ConcurrentHashMap<>();
    public UserServiceImpl() {
        // 初始化一些測(cè)試數(shù)據(jù)
        users.put(1L, User.newBuilder().setId(1).setName("John Doe").setEmail("john@example.com").build());
        users.put(2L, User.newBuilder().setId(2).setName("Jane Smith").setEmail("jane@example.com").build());
    }
    @Override
    public void getUser(GetUserRequest request, StreamObserver<GetUserResponse> responseObserver) {
        Long id = request.getId();
        User user = users.get(id);
        if (user != null) {
            GetUserResponse response = GetUserResponse.newBuilder().setUser(user).build();
            responseObserver.onNext(response);
        } else {
            responseObserver.onError(new StatusRuntimeException(Status.NOT_FOUND.withDescription("User not found")));
        }
        responseObserver.onCompleted();
    }
    @Override
    public void listUsers(ListUsersRequest request, StreamObserver<ListUsersResponse> responseObserver) {
        ListUsersResponse response = ListUsersResponse.newBuilder()
            .addAllUsers(users.values())
            .build();
        responseObserver.onNext(response);
        responseObserver.onCompleted();
    }
    @Override
    public void createUser(User request, StreamObserver<User> responseObserver) {
        long id = users.size() + 1;
        User user = User.newBuilder(request)
            .setId(id)
            .build();
        users.put(id, user);
        responseObserver.onNext(user);
        responseObserver.onCompleted();
    }
}

2.5 配置 gRPC 服務(wù)器

grpc:
  server:
    port: 9090
    enable-reflection: true
    shutdownGracePeriod: 30s

3. gRPC 客戶端

3.1 配置 gRPC 客戶端

grpc:
  client:
    user-service:
      address: static://localhost:9090
      negotiation-type: plaintext

3.2 使用 gRPC 客戶端

@Service
public class UserClientService {
    private final UserServiceGrpc.UserServiceBlockingStub userServiceStub;
    @Autowired
    public UserClientService(@GrpcClient("user-service") UserServiceGrpc.UserServiceBlockingStub userServiceStub) {
        this.userServiceStub = userServiceStub;
    }
    public User getUser(Long id) {
        GetUserRequest request = GetUserRequest.newBuilder().setId(id).build();
        GetUserResponse response = userServiceStub.getUser(request);
        return response.getUser();
    }
    public List<User> listUsers() {
        ListUsersRequest request = ListUsersRequest.newBuilder().build();
        ListUsersResponse response = userServiceStub.listUsers(request);
        return response.getUsersList();
    }
    public User createUser(User user) {
        return userServiceStub.createUser(user);
    }
}

4. 流式 RPC

4.1 服務(wù)器流 RPC

// stream.proto
syntax = "proto3";
package com.example.grpc;
option java_package = "com.example.grpc";
option java_outer_classname = "StreamProto";
message StreamRequest {
    int32 count = 1;
}
message StreamResponse {
    int32 value = 1;
}
service StreamService {
    rpc ServerStream(StreamRequest) returns (stream StreamResponse);
    rpc ClientStream(stream StreamRequest) returns (StreamResponse);
    rpc BidirectionalStream(stream StreamRequest) returns (stream StreamResponse);
}

4.2 實(shí)現(xiàn)流式服務(wù)

@GrpcService
public class StreamServiceImpl extends StreamServiceGrpc.StreamServiceImplBase {
    @Override
    public void serverStream(StreamRequest request, StreamObserver<StreamResponse> responseObserver) {
        int count = request.getCount();
        for (int i = 1; i <= count; i++) {
            StreamResponse response = StreamResponse.newBuilder().setValue(i).build();
            responseObserver.onNext(response);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        responseObserver.onCompleted();
    }
    @Override
    public StreamObserver<StreamRequest> clientStream(StreamObserver<StreamResponse> responseObserver) {
        return new StreamObserver<StreamRequest>() {
            private int sum = 0;
            @Override
            public void onNext(StreamRequest request) {
                sum += request.getCount();
            }
            @Override
            public void onError(Throwable t) {
                responseObserver.onError(t);
            }
            @Override
            public void onCompleted() {
                StreamResponse response = StreamResponse.newBuilder().setValue(sum).build();
                responseObserver.onNext(response);
                responseObserver.onCompleted();
            }
        };
    }
    @Override
    public StreamObserver<StreamRequest> bidirectionalStream(StreamObserver<StreamResponse> responseObserver) {
        return new StreamObserver<StreamRequest>() {
            @Override
            public void onNext(StreamRequest request) {
                int value = request.getCount() * 2;
                StreamResponse response = StreamResponse.newBuilder().setValue(value).build();
                responseObserver.onNext(response);
            }
            @Override
            public void onError(Throwable t) {
                responseObserver.onError(t);
            }
            @Override
            public void onCompleted() {
                responseObserver.onCompleted();
            }
        };
    }
}

4.3 使用流式客戶端

@Service
public class StreamClientService {
    private final StreamServiceGrpc.StreamServiceStub streamServiceStub;
    @Autowired
    public StreamClientService(@GrpcClient("stream-service") StreamServiceGrpc.StreamServiceStub streamServiceStub) {
        this.streamServiceStub = streamServiceStub;
    }
    public void testServerStream() {
        StreamRequest request = StreamRequest.newBuilder().setCount(5).build();
        streamServiceStub.serverStream(request, new StreamObserver<StreamResponse>() {
            @Override
            public void onNext(StreamResponse response) {
                System.out.println("Received: " + response.getValue());
            }
            @Override
            public void onError(Throwable t) {
                System.err.println("Error: " + t.getMessage());
            }
            @Override
            public void onCompleted() {
                System.out.println("Server stream completed");
            }
        });
    }
    public void testClientStream() {
        StreamObserver<StreamResponse> responseObserver = new StreamObserver<StreamResponse>() {
            @Override
            public void onNext(StreamResponse response) {
                System.out.println("Sum: " + response.getValue());
            }
            @Override
            public void onError(Throwable t) {
                System.err.println("Error: " + t.getMessage());
            }
            @Override
            public void onCompleted() {
                System.out.println("Client stream completed");
            }
        };
        StreamObserver<StreamRequest> requestObserver = streamServiceStub.clientStream(responseObserver);
        for (int i = 1; i <= 5; i++) {
            StreamRequest request = StreamRequest.newBuilder().setCount(i).build();
            requestObserver.onNext(request);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        requestObserver.onCompleted();
    }
    public void testBidirectionalStream() {
        StreamObserver<StreamResponse> responseObserver = new StreamObserver<StreamResponse>() {
            @Override
            public void onNext(StreamResponse response) {
                System.out.println("Received: " + response.getValue());
            }
            @Override
            public void onError(Throwable t) {
                System.err.println("Error: " + t.getMessage());
            }
            @Override
            public void onCompleted() {
                System.out.println("Bidirectional stream completed");
            }
        };
        StreamObserver<StreamRequest> requestObserver = streamServiceStub.bidirectionalStream(responseObserver);
        for (int i = 1; i <= 5; i++) {
            StreamRequest request = StreamRequest.newBuilder().setCount(i).build();
            requestObserver.onNext(request);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        requestObserver.onCompleted();
    }
}

5. 錯(cuò)誤處理

5.1 服務(wù)端錯(cuò)誤處理

@GrpcService
public class ErrorHandlingServiceImpl extends ErrorServiceGrpc.ErrorServiceImplBase {
    @Override
    public void divide(DivideRequest request, StreamObserver<DivideResponse> responseObserver) {
        int dividend = request.getDividend();
        int divisor = request.getDivisor();
        if (divisor == 0) {
            Status status = Status.INVALID_ARGUMENT.withDescription("Divisor cannot be zero");
            responseObserver.onError(status.asRuntimeException());
            return;
        }
        int result = dividend / divisor;
        DivideResponse response = DivideResponse.newBuilder().setResult(result).build();
        responseObserver.onNext(response);
        responseObserver.onCompleted();
    }
}

5.2 客戶端錯(cuò)誤處理

@Service
public class ErrorClientService {
    private final ErrorServiceGrpc.ErrorServiceBlockingStub errorServiceStub;
    @Autowired
    public ErrorClientService(@GrpcClient("error-service") ErrorServiceGrpc.ErrorServiceBlockingStub errorServiceStub) {
        this.errorServiceStub = errorServiceStub;
    }
    public int divide(int dividend, int divisor) {
        try {
            DivideRequest request = DivideRequest.newBuilder()
                .setDividend(dividend)
                .setDivisor(divisor)
                .build();
            DivideResponse response = errorServiceStub.divide(request);
            return response.getResult();
        } catch (StatusRuntimeException e) {
            if (e.getStatus().getCode() == Status.Code.INVALID_ARGUMENT) {
                throw new IllegalArgumentException(e.getStatus().getDescription());
            } else {
                throw new RuntimeException("Error calling gRPC service", e);
            }
        }
    }
}

6. 性能優(yōu)化

6.1 連接管理

  1. 使用連接池:配置合理的連接池大小
  2. 重用連接:避免頻繁創(chuàng)建和關(guān)閉連接
  3. 設(shè)置超時(shí):設(shè)置合理的連接超時(shí)和 RPC 超時(shí)
  4. 健康檢查:定期檢查連接狀態(tài)

6.2 序列化優(yōu)化

  1. 使用 Protocol Buffers:Protocol Buffers 比 JSON 更高效
  2. 優(yōu)化消息大小:避免發(fā)送過大的消息
  3. 使用壓縮:對(duì)大型消息啟用壓縮

6.3 并發(fā)處理

  1. 使用異步 API:對(duì)于非阻塞操作使用異步 API
  2. 合理設(shè)置線程池:配置合理的服務(wù)器和客戶端線程池大小
  3. 使用虛擬線程:在 Java 19+ 中使用虛擬線程提高并發(fā)性能

7. 最佳實(shí)踐

7.1 服務(wù)設(shè)計(jì)

  1. 合理劃分服務(wù):根據(jù)業(yè)務(wù)功能劃分服務(wù)
  2. 定義清晰的接口:使用 Protocol Buffers 定義清晰的服務(wù)接口
  3. 版本管理:為服務(wù)接口添加版本號(hào)
  4. 錯(cuò)誤處理:定義統(tǒng)一的錯(cuò)誤處理機(jī)制

7.2 代碼組織

// 推薦的代碼組織結(jié)構(gòu)
com.example
├── grpc/             // gRPC 相關(guān)代碼
│   ├── proto/        //  proto 文件
│   ├── generated/    // 生成的代碼
│   ├── service/      // 服務(wù)實(shí)現(xiàn)
│   └── client/       // 客戶端代碼
├── service/          // 業(yè)務(wù)邏輯
├── controller/       // 控制器
└── config/           // 配置類

7.3 監(jiān)控與日志

  1. 集成 Prometheus:收集 gRPC 相關(guān)的監(jiān)控指標(biāo)
  2. 集成 Grafana:可視化監(jiān)控?cái)?shù)據(jù)
  3. 配置日志:記錄詳細(xì)的 gRPC 調(diào)用日志
  4. 設(shè)置告警:及時(shí)發(fā)現(xiàn)和處理問題

8. 案例分析

8.1 微服務(wù)通信

某微服務(wù)架構(gòu)使用 gRPC 進(jìn)行服務(wù)間通信,主要包括:

  1. 訂單服務(wù):處理訂單相關(guān)操作
  2. 用戶服務(wù):處理用戶相關(guān)操作
  3. 產(chǎn)品服務(wù):處理產(chǎn)品相關(guān)操作
  4. 支付服務(wù):處理支付相關(guān)操作

該系統(tǒng)使用 gRPC 2.0 實(shí)現(xiàn)服務(wù)間通信,提高了通信效率和可靠性。

8.2 實(shí)時(shí)數(shù)據(jù)處理

某實(shí)時(shí)數(shù)據(jù)處理系統(tǒng)使用 gRPC 流式 RPC 處理實(shí)時(shí)數(shù)據(jù),主要包括:

  1. 數(shù)據(jù)采集:從各種數(shù)據(jù)源采集數(shù)據(jù)
  2. 數(shù)據(jù)處理:實(shí)時(shí)處理采集的數(shù)據(jù)
  3. 數(shù)據(jù)存儲(chǔ):將處理后的數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫
  4. 數(shù)據(jù)推送:將處理結(jié)果推送給客戶端

該系統(tǒng)使用 gRPC 2.0 的流式 RPC 功能,實(shí)現(xiàn)了高效的實(shí)時(shí)數(shù)據(jù)處理。

9. 未來趨勢(shì)

9.1 服務(wù)網(wǎng)格集成

gRPC 與服務(wù)網(wǎng)格(如 Istio)的集成將成為未來的趨勢(shì),它可以提供更細(xì)粒度的流量管理和安全控制。

9.2 邊緣計(jì)算

gRPC 在邊緣計(jì)算中的應(yīng)用將成為未來的研究方向,它可以提供高效的邊緣設(shè)備通信。

9.3 AI 驅(qū)動(dòng)的 gRPC

AI 驅(qū)動(dòng)的 gRPC 是指使用人工智能技術(shù)來優(yōu)化 gRPC 的性能和可靠性,例如智能路由、智能負(fù)載均衡、智能錯(cuò)誤處理等。

10. 總結(jié)

Spring Boot 與 gRPC 2.0 的集成是構(gòu)建高性能微服務(wù)通信系統(tǒng)的重要組成部分。通過本文的介紹,你應(yīng)該對(duì) Spring Boot 與 gRPC 2.0 的集成方法和最佳實(shí)踐有了更深入的了解。

gRPC 2.0 提供了許多新特性和改進(jìn),如 HTTP/2 支持、Protocol Buffers 增強(qiáng)、流式 RPC 等,這些特性使得 gRPC 成為微服務(wù)架構(gòu)中理想的通信方式。

通過合理使用 gRPC 2.0,我們可以構(gòu)建更高效、更可靠的微服務(wù)通信系統(tǒng)。

結(jié)語

gRPC 是一個(gè)功能強(qiáng)大的 RPC 框架,它為微服務(wù)架構(gòu)提供了高效、可靠的通信方式。Spring Boot 與 gRPC 的集成使得我們可以更方便地使用 gRPC 的功能,構(gòu)建各種高性能的微服務(wù)應(yīng)用。

隨著 gRPC 的不斷發(fā)展,它將為我們提供更多強(qiáng)大的功能,幫助我們構(gòu)建更加高效、可靠的分布式系統(tǒng)。

到此這篇關(guān)于SpringBoot與gRPC2.0集成的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)SpringBoot集成gRPC 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java網(wǎng)絡(luò)編程基礎(chǔ)篇之單向通信

    Java網(wǎng)絡(luò)編程基礎(chǔ)篇之單向通信

    這篇文章主要介紹了Java網(wǎng)絡(luò)編程里通過套接字實(shí)現(xiàn)單向通信的方法及相關(guān)實(shí)例,屬于網(wǎng)絡(luò)編程入門程序,雖然簡(jiǎn)單,但具有一定參考價(jià)值,需要的朋友可以參考下。
    2017-09-09
  • Java靜態(tài)內(nèi)部類實(shí)現(xiàn)單例過程

    Java靜態(tài)內(nèi)部類實(shí)現(xiàn)單例過程

    這篇文章主要介紹了Java靜態(tài)內(nèi)部類實(shí)現(xiàn)單例過程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • 基于idea把springboot項(xiàng)目部署到docker

    基于idea把springboot項(xiàng)目部署到docker

    這篇文章主要介紹了基于idea把springboot項(xiàng)目部署到docker,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • ImportBeanDefinitionRegistrar手動(dòng)控制BeanDefinition創(chuàng)建注冊(cè)詳解

    ImportBeanDefinitionRegistrar手動(dòng)控制BeanDefinition創(chuàng)建注冊(cè)詳解

    這篇文章主要為大家介紹了ImportBeanDefinitionRegistrar手動(dòng)控制BeanDefinition創(chuàng)建注冊(cè)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Mybatis的association使用子查詢結(jié)果錯(cuò)誤的問題解決

    Mybatis的association使用子查詢結(jié)果錯(cuò)誤的問題解決

    本文主要介紹了Mybatis的association使用子查詢結(jié)果錯(cuò)誤的問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-07-07
  • Java面試題沖刺第二十六天--實(shí)戰(zhàn)編程

    Java面試題沖刺第二十六天--實(shí)戰(zhàn)編程

    這篇文章主要為大家分享了最有價(jià)值的三道java實(shí)戰(zhàn)面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-08-08
  • java  HttpServletRequest和HttpServletResponse詳解

    java HttpServletRequest和HttpServletResponse詳解

    這篇文章主要介紹了java HttpServletRequest和HttpServletResponse詳解的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • Spring中配置數(shù)據(jù)源的幾種方式

    Spring中配置數(shù)據(jù)源的幾種方式

    今天小編就為大家分享一篇關(guān)于Spring中配置數(shù)據(jù)源的幾種方式,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Mybatis CURD及模糊查詢功能的實(shí)現(xiàn)

    Mybatis CURD及模糊查詢功能的實(shí)現(xiàn)

    這篇文章主要介紹了Mybatis CURD及模糊查詢功能的實(shí)現(xiàn),有查詢刪除,插入,更新功能,通過實(shí)例代碼講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-06-06
  • Spring攔截器中注入Bean失敗解放方案詳解

    Spring攔截器中注入Bean失敗解放方案詳解

    這兩天遇到SpringBoot攔截器中Bean無法注入問題。下面介紹關(guān)于SpringBoot攔截器中Bean無法注入的問題解決方案,感興趣的朋友一起看看吧
    2022-06-06

最新評(píng)論

桂阳县| 迁西县| 定结县| 平潭县| 共和县| 郯城县| 丽水市| 望谟县| 孙吴县| 柳州市| 白朗县| 古蔺县| 微山县| 北宁市| 福州市| 镇雄县| 湾仔区| 托克逊县| 太白县| 鄂托克旗| 马鞍山市| 甘德县| 石阡县| 阳江市| 清镇市| 北海市| 吐鲁番市| 柯坪县| 贵阳市| 湖州市| 丰都县| 广德县| 潼南县| 万全县| 延安市| 济宁市| 普洱| 苗栗市| 山西省| 威海市| 富川|