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

高性能C++ 日志實(shí)戰(zhàn):spdlog 核心架構(gòu)解析與最佳實(shí)踐指南

 更新時間:2026年04月14日 10:00:29   作者:梓?  
spdlog是一個高性能的日志庫,支持多種輸出目標(biāo)和格式化選項(xiàng),這篇文章給大家介紹高性能C++ 日志實(shí)戰(zhàn):spdlog 核心架構(gòu)解析與最佳實(shí)踐指南,感興趣的朋友跟隨小編一起看看吧

一、spdlog 介紹

spdlog 是一個高性能、超快速、零配置的 C++ 日志庫,它旨在提供簡潔的 API 和豐富的功能,同時保持高性能的日志記錄。它支持多種輸出目標(biāo)、格式化選項(xiàng)、線程安全以及異步日志記錄。

特點(diǎn):

  • 高性能: spdlog 專為速度而設(shè)計(jì),即使在高負(fù)載情況下也能保持良好的性能。
  • 零配置: 無需復(fù)雜的配置,只需包含頭文件即可在項(xiàng)目中使用。
  • 異步日志: 支持異步日志記錄,減少對主線程的影響。
  • 格式化: 支持自定義日志消息的格式化,包括時間戳、線程 ID、日志級別等。
  • 多平臺: 跨平臺兼容,支持 Windows、Linux、macOS 等操作系統(tǒng)。
  • 豐富的 API: 提供豐富的日志級別和操作符重載,方便記錄各種類型的日志。

二、spdlog 安裝

1. 直接命令安裝(適用于 Ubuntu/Debian 系統(tǒng))

(1)步驟:

sudo apt-get update                 # 更新軟件源
sudo apt-get install libspdlog-dev  # 安裝開發(fā)庫

(2)特點(diǎn):

  • 簡單快捷: 適合快速部署,無需手動編譯。
  • 版本受限: 依賴系統(tǒng)倉庫的版本,可能非最新(如 Ubuntu 20.04 默認(rèn)版本較舊)。

(3)驗(yàn)證安裝:

  • 檢查頭文件: ls /usr/include/spdlog/
  • 檢查庫文件: ls /usr/lib/x86_64-linux-gnu/libspdlog*

2. 源碼編譯安裝

# 下載源碼
git clone https://github.com/gabime/spdlog.git
# 切換目錄
cd spdlog/
# 創(chuàng)建并進(jìn)入構(gòu)建目錄
mkdir build
cd build/
# 執(zhí)行構(gòu)建命令,生成 Makefile
cmake ..
# 編譯代碼
make
# 安裝到系統(tǒng)目錄(默認(rèn) /usr/local)
sudo make install

三、spdlog 的重要組成結(jié)構(gòu)

1. 日志輸出等級枚舉

  • 日志輸出等級枚舉:
namespace spdlog {
	 namespace level {
			enum level_enum : int 
			{
				 trace = SPDLOG_LEVEL_TRACE,
				 debug = SPDLOG_LEVEL_DEBUG,
				 info = SPDLOG_LEVEL_INFO,
				 warn = SPDLOG_LEVEL_WARN,
				 error = SPDLOG_LEVEL_ERROR,
				 critical = SPDLOG_LEVEL_CRITICAL,
				 off = SPDLOG_LEVEL_OFF,
				 n_levels
		    };
     }
}

在 spdlog/include/spdlog/common.h 頭文件中,其宏定義如下:

#define SPDLOG_LEVEL_TRACE 0
#define SPDLOG_LEVEL_DEBUG 1
#define SPDLOG_LEVEL_INFO 2
#define SPDLOG_LEVEL_WARN 3
#define SPDLOG_LEVEL_ERROR 4
#define SPDLOG_LEVEL_CRITICAL 5
#define SPDLOG_LEVEL_OFF 6

2. (同步)日志記錄器類(含 自定義日志輸出格式 接口的使用介紹 )

  • (同步)日志記錄器類:
namespace spdlog {
	class logger 
	{
		 // 構(gòu)造函數(shù)
		 logger(std::string name);
		 logger(std::string name, sink_ptr single_sink);
		 logger(std::string name, sinks_init_list sinks);
		 // 設(shè)置輸出等級(只輸出 高于或等于 此等級的日志)
		 void set_level(level::level_enum log_level);
		 // 自定義 日志輸出格式
		 void set_pattern(const std::string& pattern);
         // 以不同等級 輸出日志信息的接口
		 template<typename... Args>
		 void trace(fmt::format_string<Args...> fmt, Args &&...args)
		 template<typename... Args>
		 void debug(fmt::format_string<Args...> fmt, Args &&...args)
		 template<typename... Args>
		 void info(fmt::format_string<Args...> fmt, Args &&...args)
		 template<typename... Args>
		 void warn(fmt::format_string<Args...> fmt, Args &&...args)
		 template<typename... Args>
		 void error(fmt::format_string<Args...> fmt, Args &&...args)
		 template<typename... Args>
		 void critical(fmt::format_string<Args...> fmt, Args &&...args)
		 // 立刻刷新日志信息
		 void flush(); 
		 // 設(shè)置刷新策略(指定一個日志等級,一旦有 高于或等于指定等級的日志,立刻刷新日志信息)
		 void flush_on(level::level_enum log_level);
	};
}
  • logger類內(nèi),set_pattern接口的使用:

假設(shè)Log 是logger類對象的智能指針

Log->set_pattern("%Y-%m-%d %H:%M:%S [%t] [%-8l] %v");
%t - 線程 ID(Thread ID)
%n - 日志器名稱(Logger name)
%l - 日志級別名稱(Level name),如 INFO, DEBUG, ERROR 等
%v - 日志內(nèi)容(message)
%Y - 年(Year)
%m - 月(Month)
%d - 日(Day)
%H - 小時(24-hour format)
%M - 分鐘(Minute)
%S - 秒(Second)

3. 線程池類(含 單例模式管理全局線程池實(shí)例 的介紹 )

  • spdlog中只有一種線程池實(shí)現(xiàn),即spdlog::details::thread_pool類
namespace spdlog {
	namespace details {
		class thread_pool 
		{
			 thread_pool(size_t q_max_items, size_t threads_n, std::function<void()> on_thread_start,
			             std::function<void()> on_thread_stop);
			 thread_pool(size_t q_max_items, size_t threads_n, std::function<void()> on_thread_start);
			 thread_pool(size_t q_max_items, size_t threads_n);
		 };
	 }
 }
  • 單例模式的實(shí)現(xiàn)

通過registry類(單例)持有 全局線程池實(shí)例:

// registry 類(單例)管理全局線程池
namespace spdlog {
	namespace details {
		  class registry 
		  {
		      std::shared_ptr<thread_pool> _tp; // 全局線程池實(shí)例
		      std::mutex _mutex;                // 線程安全鎖
		  public:
		      // 獲取單例實(shí)例(線程安全)
		      static registry &instance() 
		      {
		          static registry s_instance; // 靜態(tài)實(shí)例(C++11保證線程安全)
		          return s_instance;
		      }
		      // 獲取全局線程池(延遲初始化)
		      std::shared_ptr<thread_pool> get_tp() 
		      {
		          std::lock_guard<std::mutex> lock(_mutex);
		          if (!_tp) 
		          {
		              // 首次調(diào)用時創(chuàng)建默認(rèn)線程池(8192隊(duì)列 + 1線程)
		              _tp = std::make_shared<thread_pool>(8192, 1);
		          }
		          return _tp;
		      }
		      // 重置全局線程池(線程安全)
		      void set_tp(std::shared_ptr<thread_pool> new_tp) 
		      {
		          std::lock_guard<std::mutex> lock(_mutex);
		          // 先停止舊線程池的所有任務(wù)
		          if (_tp) 
		          {
		              _tp->shutdown(); // 內(nèi)部停止所有工作線程
		          }
		          _tp = std::move(new_tp); // 替換為新線程池
		      }
	   	  private:
		      registry() = default;            // 禁用外部構(gòu)造
		      registry(const registry&) = delete; // 禁用拷貝
		      registry& operator=(const registry&) = delete; // 禁用賦值
		  };
	 }
}
  • 通過spdlog庫中的 spdlog::init_thread_pool() 和 spdlog::thread_pool() 函數(shù) 來使用 registry類(單例)持有的 全局線程池實(shí)例
namespace spdlog {
	// 獲取全局線程池的共享指針
	std::shared_ptr<details::thread_pool> thread_pool() 
	{
	    return details::registry::instance().get_tp();
	}
	// 重置全局線程池(指定隊(duì)列大小和線程數(shù))
	void init_thread_pool(size_t q_size, size_t thread_count) 
	{
	    auto new_tp = std::make_shared<details::thread_pool>(q_size, thread_count);
	    details::registry::instance().set_tp(new_tp);
	}
}
  • 注意: spdlog::init_thread_pool() 重置全局線程池時,如果 static registry s_instance(registry類單例,靜態(tài)對象)的 _tp已經(jīng)指向了一個線程池實(shí)例,_tp會銷毀指向的線程池實(shí)例,然后指向新創(chuàng)建的線程池實(shí)例

4. 異步日志記錄器類(與 日志記錄器類 對比)

  • async_logger 是異步日志的核心實(shí)現(xiàn)類,繼承自 logger 基類。它通過線程池和任務(wù)隊(duì)列實(shí)現(xiàn)異步日志記錄:
namespace spdlog {
	class async_logger final : public logger 
	{
		 async_logger(std::string logger_name, sinks_init_list sinks_list, std::weak_ptr<details::thread_pool> tp,
		              async_overflow_policy overflow_policy = async_overflow_policy::block);
		 async_logger(std::string logger_name, sink_ptr single_sink, std::weak_ptr<details::thread_pool> tp,
		              async_overflow_policy overflow_policy = async_overflow_policy::block);
	}
}
類型日志寫入流程線程模型
(同步)日志記錄器主線程直接調(diào)用I/O操作(如文件寫入、控制臺輸出)
• 日志生成 → 立即執(zhí)行磁盤/網(wǎng)絡(luò)I/O → 主線程阻塞等待完成
單線程模型:日志I/O占用主線程時間片
異步日志記錄器主線程將日志存入內(nèi)存隊(duì)列(任務(wù)隊(duì)列)
• 日志生成 → 存入隊(duì)列 → 立即返回主線程
• 后臺線程池消費(fèi)隊(duì)列并執(zhí)行I/O
生產(chǎn)者-消費(fèi)者模型:主線程與I/O線程分離

關(guān)鍵區(qū)別:異步日志通過內(nèi)存隊(duì)列緩沖和線程池異步刷盤,避免主線程因I/O等待被阻塞

5. 日志記錄器工廠類

using async_factory = async_factory_impl<async_overflow_policy::block>;
//創(chuàng)建一個彩色輸出到標(biāo)準(zhǔn)輸出的日志記錄器,默認(rèn)工廠 創(chuàng)建同步日志記錄器
template<typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name, 
                                        color_mode mode = color_mode::automatic);
//標(biāo)準(zhǔn)錯誤
template<typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> stderr_color_mt(const std::string &logger_name, 
                                        color_mode mode = color_mode::automatic);
// 指定文件 
template<typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> basic_logger_mt(const std::string &logger_name, const filename_t &filename,
                                        bool truncate = false,
                                        const file_event_handlers &event_handlers = {})
//循環(huán)文件 
template<typename Factory = spdlog::synchronous_factory>
std::shared_ptr<logger> rotating_logger_mt(const std::string &logger_name, const filename_t &filename, 
                                           size_t max_file_size, size_t max_files, 
                                           bool rotate_on_open = false)

日志記錄器工廠類:封裝了 日志記錄器類對象 的構(gòu)建 和 配置過程
有了日志記錄器工廠類,我們不需要關(guān)心 日志記錄器類對象 的構(gòu)建 和 配置過程,可以通過API接口一鍵構(gòu)造 日志記錄器類對象

spdlog::basic_logger_mt()接口 的 第三個參數(shù) truncate 的功能:

行為適用場景
true若日志文件已存在,清空文件內(nèi)容,從頭開始寫入新日志。需要覆蓋舊日志的場景(如臨時調(diào)試)
false (默認(rèn))若日志文件已存在,追加新日志到文件末尾;若文件不存在則創(chuàng)建新文件。長期運(yùn)行的程序需保留歷史日志的場景
  • 創(chuàng)建 同步日志記錄器對象

采用默認(rèn)工廠,創(chuàng)建的都是 同步日志記錄器對象

(1)創(chuàng)建 向標(biāo)準(zhǔn)輸出寫入日志 的同步日志記錄器對象

// 使用stdout_color_mt接口,只需指定 要創(chuàng)建的日志記錄器對象的名字,
// 它就會創(chuàng)建 指定名字的日志記錄器對象,并返回指向該對象的智能指針
auto log = spdlog::stdout_color_mt("sync_logger");

(2)創(chuàng)建 向指定文件寫入日志 的同步日志記錄器對象

// 使用basic_logger_mt接口,需指定 要創(chuàng)建的日志記錄器對象的名字 和 文件,
// 它就會創(chuàng)建 向指定文件寫入日志的 指定名字的日志記錄器對象,并返回指向該對象的智能指針
auto file_log = spdlog::basic_logger_mt("file_sync_logger", "log.txt");
  • 創(chuàng)建 異步日志記錄器對象

要創(chuàng)建異步日志記錄器對象,需要顯式指定 工廠類型(spdlog::async_factory)

(1)創(chuàng)建 向標(biāo)準(zhǔn)輸出寫入日志 的異步日志記錄器對象

auto log = spdlog::stdout_color_mt<spdlog::async_factory>("sync_logger");

(2)創(chuàng)建 向指定文件寫入日志 的異步日志記錄器對象

auto file_log = spdlog::basic_logger_mt<spdlog::async_factory>("file_sync_logger", "log.txt");

6. 全局接口

namespace spdlog {
	// 日志刷新策略-每隔 N 秒刷新一次
	void flush_every(std::chrono::seconds interval);
	// 設(shè)置輸出等級(只輸出 高于或等于 此等級的日志)
	void set_level(level::level_enum log_level);
	// 設(shè)置刷新策略(指定一個日志等級,一旦有 高于或等于指定等級的日志,立刻刷新日志信息)
	void flush_on(level::level_enum log_level);
	// 自定義 日志輸出格式
	void set_pattern(const std::string& pattern);
}

注:全局配置的 優(yōu)先級低于 日志記錄器對象的專屬配置!

spdlog 采用作用域逐級覆蓋的配置策略:

  • 全局配置(spdlog::set_level()、spdlog::flush_on()、spdlog::set_pattern())

影響所有未單獨(dú)配置的日志記錄器,作為默認(rèn)值存在。

  • 日志記錄器專屬配置 (logger->set_level()、logger->flush_on()、logger->set_pattern())

每個日志器對象獨(dú)立配置,優(yōu)先級高于全局配置。

四、spdlog 的使用

1. 通過全局接口配置,創(chuàng)建同步日志器 (向標(biāo)準(zhǔn)輸出寫日志)

要使用spdlog庫,在你的 C++ 源文件中必須包含 spdlog 的頭文件:

#include <spdlog/spdlog.h>
  • 通過全局接口配置,創(chuàng)建同步日志器 (向標(biāo)準(zhǔn)輸出寫日志)
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h> // 包含 spdlog::stdout_color_mt() 的實(shí)現(xiàn)
int main()
{
    // 1. 全局配置
    spdlog::flush_on(spdlog::level::level_enum::info);
    // 設(shè)置輸出等級(只輸出 高于或等于 info等級的日志)
    spdlog::set_level(spdlog::level::level_enum::info);
    // 自定義 日志輸出格式
    spdlog::set_pattern("%Y-%m-%d %H:%M:%S [%t] [%-8l] %v");
    // 日志刷新策略-每隔 1 秒刷新一次
    spdlog::flush_every(std::chrono::seconds(1));
    // 2. 創(chuàng)建同步日志器(向標(biāo)準(zhǔn)輸出寫日志)
    auto log = spdlog::stdout_color_mt("sync_logger");
    // 3. 使用同步日志器 向標(biāo)準(zhǔn)輸出寫日志
    log->trace("你好!{}", "中國");     // {}是占位符,不區(qū)分?jǐn)?shù)據(jù)類型
    log->debug("你好!{}","中國");
    log->info("你好!{}","中國");
    log->warn("你好!{}","中國");
    log->error("你好!{}","中國");
    log->critical("你好!{}","中國");
    return 0;
}

注:spdlog庫依賴 fmt庫,所以鏈接時,還需要顯式指定fmt庫

2. 創(chuàng)建同步日志器 (向指定文件寫日志),并使用同步日志器的專用配置接口

#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h> // 包含 spdlog::basic_logger_mt() 的實(shí)現(xiàn)
int main()
{
    // 1. 全局配置
    // 日志刷新策略-每隔 1 秒刷新一次
    spdlog::flush_every(std::chrono::seconds(1));
    // 2. 創(chuàng)建同步日志器(向當(dāng)前目錄下的log.txt文件 寫日志)
    auto file_log = spdlog::basic_logger_mt("sync_logger", "log.txt");
    // 使用同步日志器的專用配置接口
    file_log->flush_on(spdlog::level::level_enum::info);
    file_log->set_level(spdlog::level::level_enum::info);
    file_log->set_pattern("%Y-%m-%d %H:%M:%S [%t] [%-8l] %v");
    // 3. 使用同步日志器 向指定文件寫日志
    file_log->trace("你好!{}", "中國");     // {}是占位符,不區(qū)分?jǐn)?shù)據(jù)類型
    file_log->debug("你好!{}","中國");
    file_log->info("你好!{}","中國");
    file_log->warn("你好!{}","中國");
    file_log->error("你好!{}","中國");
    file_log->critical("你好!{}","中國");
    return 0;
}

3. 創(chuàng)建異步日志器 (向指定文件寫日志)

#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h> // 包含 spdlog::basic_logger_mt() 的實(shí)現(xiàn)
#include <spdlog/async.h>                 // 包含 spdlog::async_factory工廠類的實(shí)現(xiàn)
int main()
{
    // 1. 全局配置
    // 日志刷新策略-每隔 1 秒刷新一次
    spdlog::flush_every(std::chrono::seconds(1));
    // 初始化全局線程池 的任務(wù)隊(duì)列數(shù) 和 線程數(shù)量
    spdlog::init_thread_pool(4096, 2);
    // 2. 顯式指定工廠類, 創(chuàng)建異步日志器(向當(dāng)前目錄下的log.txt文件 寫日志)
    // 創(chuàng)建異步日志器對象時,需要指定 線程池實(shí)例,
    // basic_logger_mt接口 創(chuàng)建異步日志器對象時,會指定 全局線程池實(shí)例, 
    // 如果之前未初始化全局線程池的配置,全局線程池實(shí)例采用默認(rèn)配置:8192隊(duì)列 + 1線程
    auto file_log = spdlog::basic_logger_mt<spdlog::async_factory>("sync_logger", "log.txt");
    // 使用異步日志器的專用配置接口
    file_log->flush_on(spdlog::level::level_enum::info);
    file_log->set_level(spdlog::level::level_enum::info);
    file_log->set_pattern("%Y-%m-%d %H:%M:%S [%t] [%-8l] %v");
    // 3. 使用異步日志器 向指定文件寫日志
    file_log->trace("你好!{}", "中國");     // {}是占位符,不區(qū)分?jǐn)?shù)據(jù)類型
    file_log->debug("你好!{}","中國");
    file_log->info("你好!{}","中國");
    file_log->warn("你好!{}","中國");
    file_log->error("你好!{}","中國");
    file_log->critical("你好!{}","中國");
    return 0;
}

到此這篇關(guān)于高性能C++ 日志實(shí)戰(zhàn):spdlog 核心架構(gòu)解析與最佳實(shí)踐指南的文章就介紹到這了,更多相關(guān)C++ 日志 spdlog內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++模擬實(shí)現(xiàn)stack和Queue的操作示例

    C++模擬實(shí)現(xiàn)stack和Queue的操作示例

    這篇文章主要介紹了C++模擬實(shí)現(xiàn)stack和Queue的操作示例,文中通過代碼示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-06-06
  • 深入淺出理解C語言初識結(jié)構(gòu)體

    深入淺出理解C語言初識結(jié)構(gòu)體

    C?數(shù)組允許定義可存儲相同類型數(shù)據(jù)項(xiàng)的變量,結(jié)構(gòu)是?C?編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許你存儲不同類型的數(shù)據(jù)項(xiàng),本篇讓我們來了解C?的結(jié)構(gòu)體
    2022-02-02
  • VS2019和VS2022項(xiàng)目兼容性問題的解決

    VS2019和VS2022項(xiàng)目兼容性問題的解決

    在VS2019中打開被VS2022打開過的項(xiàng)目時出現(xiàn)兼容性問題,可以通過修改項(xiàng)目解決方案文件(.sln)和項(xiàng)目文件(.vcxproj)中的版本號來解決
    ,下面就來介紹一下,感興趣的可以了解一下
    2024-12-12
  • 嵌入式C實(shí)戰(zhàn)項(xiàng)目開發(fā)技巧:對一個有規(guī)律的數(shù)組表進(jìn)行位移操作的方法

    嵌入式C實(shí)戰(zhàn)項(xiàng)目開發(fā)技巧:對一個有規(guī)律的數(shù)組表進(jìn)行位移操作的方法

    今天小編就為大家分享一篇關(guān)于嵌入式C實(shí)戰(zhàn)項(xiàng)目開發(fā)技巧:對一個有規(guī)律的數(shù)組表進(jìn)行位移操作的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • C語言關(guān)鍵字之a(chǎn)uto register詳解

    C語言關(guān)鍵字之a(chǎn)uto register詳解

    這篇文章主要為大家介紹了C語言關(guān)鍵字之a(chǎn)uto register,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • C++利用map實(shí)現(xiàn)并查集

    C++利用map實(shí)現(xiàn)并查集

    這篇文章主要為大家詳細(xì)介紹了C++利用map實(shí)現(xiàn)并查集,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • C++右移運(yùn)算符的一個小坑及解決

    C++右移運(yùn)算符的一個小坑及解決

    文章指出右移運(yùn)算符處理負(fù)數(shù)時左側(cè)補(bǔ)1導(dǎo)致死循環(huán),與除法行為不同,強(qiáng)調(diào)需注意補(bǔ)碼機(jī)制以正確統(tǒng)計(jì)二進(jìn)制1的個數(shù)
    2025-09-09
  • c++程序字符型的實(shí)例講解

    c++程序字符型的實(shí)例講解

    在本篇文章里小編給大家整理的是一篇關(guān)于
    2020-02-02
  • C++?std::thread?使用方法

    C++?std::thread?使用方法

    這篇文章主要介紹了C++?std::thread?如何使用,C++中的std::thread類提供了一種方便的多線程編程方式,在使用std::thread類時,我們需要注意線程間的同步和通信問題,以確保多個線程之間的正確協(xié)同工作需要的朋友可以參考下
    2023-03-03
  • Opengl?ES之FBO幀緩沖對象使用詳解

    Opengl?ES之FBO幀緩沖對象使用詳解

    這篇文章主要為大家介紹了Opengl?ES之FBO幀緩沖對象使用詳解,<BR>有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09

最新評論

花垣县| 海兴县| 卢龙县| 唐海县| 郑州市| 广河县| 富平县| 西华县| 琼海市| 昌平区| 文安县| 吉木乃县| 桓台县| 商都县| 淅川县| 通河县| 屏山县| 柳州市| 天柱县| 大丰市| 西盟| 鲜城| 宁强县| 行唐县| 镇远县| 江北区| 阿鲁科尔沁旗| 桑日县| 台东县| 凤凰县| 商河县| 巫溪县| 寻甸| 商水县| 甘孜| 临沂市| 剑阁县| 琼中| 民权县| 邻水| 富宁县|