acl庫使用FAQ

一、基礎問題

1、acl 庫是啥、主要包含哪些功能?

acl 工程是一個跨平臺(支持LINUX,WIN32,Solaris,MacOS,FreeBSD)的網絡通信庫及服務器編程框架,同時提供更多的實用功能庫。通過該庫,用戶可以非常容易地編寫支持多種模式(多線程、多進程、非阻塞、觸發器、UDP方式、協程方式)的服務器程序,WEB 應用程序,數據庫應用程序。此外,該庫還提供了常見應用的客戶端通信庫(如:HTTP、SMTP、ICMP、redis、disque、memcache、beanstalk、handler socket),常見流式編解碼庫:XML/JSON/MIME/BASE64/UUCODE/QPCODE/RFC2047 等。

2、acl 庫支持哪些平臺?

目前主要支持 Linux/Windows/Macos/Freebsd/Solaris(x86)。

3、acl 庫主要包含幾個庫?

主要包括:lib_acl(用 C 語言寫的基礎庫)、lib_protocol(用 C 語言寫的一些網絡應用協議庫)、lib_acl_cpp(用 C++ 語言編寫,封裝了 lib_acl/lib_protocol 兩個庫,同時增加更多實用的功能庫)、 lib_fiber(用C 語言編寫的支持高性能、高併發的網絡協程庫)、lib_rpc(用C++語言編寫的封裝了 google protobuf 網絡庫)。

4、acl 庫有哪些外部依賴庫?

lib_acl/lib_protocol/lib_fiber 僅依賴系統基礎庫;lib_acl_cpp 庫的 db 模塊依賴於 mysql 客戶端庫、sqlite 庫,stream 流模塊依賴於 polarssl 庫(該庫源碼附在 acl/resource 目錄下),另外,在 UNIX/LINUX 平臺下還需要壓縮庫 --- libz 庫(一般 LINUX 會自帶該壓縮庫);lib_rpc 依賴於 protobuf 庫。

5、沒有這些第三方庫 acl 能否使用?

可以。默認情況下,沒有這些第三方庫編譯和使用 acl 庫是沒有問題的,只是不能使用 mysql/sqlite/ssl/protobuf 功能。

6、acl 庫的源碼下載位置在哪兒?

github:https://github.com/acl-dev/acl/

oschina: https://git.oschina.net/acl-dev/acl/

sourceforge:https://sourceforge.net/projects/acl/

 

二、編譯&使用問題

1、acl 庫的編譯過程?

acl 庫的編譯過程請參考:acl 的編譯與使用 博客。

2、Linux 平臺下庫的編譯順序問題?

lib_acl 庫是 acl 庫中的基礎庫,其它庫均依賴於該庫,庫的依賴順序爲:lib_protocol 依賴於 lib_acl,lib_acl_cpp 依賴於 lib_acl 和 lib_protocol,lib_fiber 依賴於 lib_acl,lib_rpc 依賴於 lib_acl/lib_protocol/lib_acl_cpp。因此當應用在連接 acl 庫時,需要注意連接的順序爲:-l_acl_cpp -l_protocol -l_acl。

3、Unix/Linux 平臺下編譯 acl 庫時的編譯選項是什麼?

在 Unix/Linux 平臺下編譯 acl 庫時需要指明 gcc 的編譯選項,acl 庫自帶的 Makefile 會自動識別操作系統而選擇不同的編譯選項,下面列出不同 Unix 平臺的不同編譯選項(當前版本已自動識別系統類型,無需添加如下編譯選項):

3.1、Linux 平臺:-DLINUX2

3.2、MacOS 平臺:-DMACOSX

3.3、FreeBSD 平臺:-DFREEBSD

3.4、Solaris(x86) 平臺:-DSUNOS5

4、請給出 Linux 平臺下最簡單的一個 Makefile?

下面是使用 acl 的三個庫的最簡單的編譯選項(因爲排版問題,當拷貝下面內容至 Makefile 時,需要注意將每行前空格手工轉成 TAB 鍵):

fiber: main.o
	g++ -o fiber main.o \
		-L./lib_acl_cpp/lib -l_acl_cpp \
		-L./lib_protocol/lib -l_protocol \
		-L./lib_acl/lib -l_acl \
		-lz -lpthread -ldl
main.o: main.cpp
	g++ -O3 -Wall -c main.cpp -DLINUX2 \
		-I./lib_acl/include \
		-I./lib_acl_cpp/include

5、Linux 平臺下找不到 -lz 庫怎麼辦?

一般 Unix/Linux 平臺下系統會自帶 libz.a 或 libz.so 壓縮庫,如果找不到該庫,則可以在線安裝或採用編譯安裝 zlib 庫,針對 Centos 和 Ubuntu 可分別通過以下方式在線安裝(均需切換至 root 身份):

5.1、Centos:yum install zlib-devel

5.2、Ubuntu:apt-get install zlib1g.dev

6、Linux 平臺下 acl 庫能打包成一個庫嗎?

可以。在 acl 目錄下運行:make build_one 則可以將 lib_acl/lib_protocol/lib_acl_cpp 打包成一個完整的庫 -- lib_acl.a/lib_acl.so,則應用最終使用時可以僅連接這一個庫即可。

7、Linux 平臺下如何使用 ssl 功能?

如果使用上面統一的 acl 庫,則可以在 acl 根目錄下編譯時運行:make build_one polarssl=on;

如果使用三個庫:lib_acl.a,lib_protocol.a,lib_acl_cpp.a,則在編譯前需要先指定環境變量:export ENV_FLAGS=HAS_POLARSSL,然後分別編譯這三個庫;

然後進行 acl/resource 目錄,解壓 polarssl-1.2.19-gpl.tgz,然後進入 polarssl-1.2.19 目錄運行:make 編譯後在 resource/polarssl-1.2.19/library 目錄得到 libpolarssl.a 庫;

最後在編譯應用時將 libpolarssl.a 連接進你的工程中即可。

8、Linux 下如何使用 mysql 功能?

lib_acl_cpp 庫是以動態加載方式加載 mysql 動態庫的,所以在編譯 lib_acl_cpp 時,mysql 功能就已經被編譯進去 acl 庫中了。用戶僅需要將 mysql 動態庫通過函數 acl::db_handle::set_loadpath 註冊進 acl 庫中即可;

至於 mysql 客戶端庫,用戶可以去 mysql 官方下載或在 acl/resource 目錄下編譯 mysql-connector-c-6.1.6-src.tar.gz。

 

三、各個功能模塊的使用問題

(一)、網絡通信

(二)、HTTP 模塊

1、acl HTTP 服務器是否支持斷點下載功能?

支持。acl HTTP 模塊支持斷點續傳功能,一個支持斷點下載的服務器示例參照:acl\app\wizard_demo\httpd_download。

2、acl HTTP 服務器是否支持文件上傳功能?

支持。參考示例:acl\app\wizard_demo\httpd_upload。

3、acl HTTP 模塊是否支持服務器/客戶端兩種模式?

支持。目前 acl 的 HTTP 協議模塊同時支持客戶端及服務端模式,即你既可以使用 acl HTTP 編寫客戶端程序,又可以編寫服務器程序,其中 acl 中的 http_request/http_request_pool/http_request_manager 類用來編寫客戶端程序,http_response/HttpServlet/HttpServletRequest/HttpServeletResponse 用來編寫服務器程序。

4、acl HTTP 模塊是否支持 websocket 通信協議?

支持。可以參考示例:lib_acl_cpp\samples\websocket。

5、acl HTTP 模塊是否支持 session?

支持。acl HTTP 模塊當用在服務器編程時支持 session 存儲,目前支持使用 memcached 或 redis 存儲 session 數據。

 

(三)、Redis 模塊

1、acl redis 庫是否支持集羣功能?

答案:是,acl redis 客戶端庫同時支持集羣和單機方式的 redis-server。

2、acl redis 庫是如何劃分的?

acl redis 客戶端庫主要分爲兩類:命令類和連接類,其中的命令類主要有:redis_key, redis_string, redis_hash, redis_list, redis_set, redis_zset, redis_cluster, redis_geo, redis_hyperloglog, redis_pubsub, redis_transaction, redis_server, redis_script, 這些類都繼承於基類 redis_command,同時子類 redis 又繼承了所有這些命令類,以便於用戶可以直接使用 acl::redis 操作所有的 redis 客戶端命令;redis_client, redis_client_pool, redis_client_cluster 爲通信連接類,命令類對象通過這些連接類對象與 redis-server 進行交互,redis_client 爲單連接類,redis_client_pool 爲連接池類,這兩個類僅能在非集羣模式的 redis-server 環境中使用,不支持 redis-server 的集羣模式,必須使用 redis_client_cluster 連接集羣模式的 redis-server,同時 redis_client_cluster 也兼容非集羣模式的連接。

3、acl redis 庫中的哪些類對象操作是線程安全的?

acl redis 庫中的所有命令類對象及 redis_client 單連接類對象不能同時被多個線程使用(就象 std::string 一樣不能跨線程使用);redis_client_pool,redis_client_cluster 兩個連接類對象是線程操作安全的,同一個對象可以被多個線程同時使用。

4、acl redis 客戶庫當連接斷開時是否會重連?

acl redis 庫中的連接類中:redis_client,redis_client_pool,redis_client_cluster 三個連接類對象當檢測到網絡連接異常斷開時會嘗試自動重連,上層使用者無需考慮連接斷開重試的情況。

 

(四)、協程模塊

1、協程裏面的非阻塞是什麼原理的,比如我現在需要訪問數據庫,這個動作肯定是個阻塞的操作,如果有10個協程進行數據庫訪問,這個非阻塞是怎麼理解了?

協程方式在底層將系統的 IO API(read/write 等)都 hook 了,數據庫操作也要調用這些API,所以表面上的阻塞式DB操作在協程底層的IO也會被轉爲非阻塞模式。

2、acl 協程庫是否支持多線程?

acl 協程庫支持多線程方式,只是支持的方式與 go 語言有所不同。用戶可以創建多個線程,每個線程一個協程調度器,線程之間的協程調度是相互隔離的,正如多進程與多線程之間的關係一樣(每個進程內可以啓動多個線程,但進程之間的線程的調度過程是隔離的),在每個線程內部可以創建大量 acl 協程,每個協程均由其所屬的線程內的協程調度器調度運行。

3、acl 協程庫如何支持多核 CPU?

正如 2)所說,用戶可以啓動多個線程,每個線程一個 acl 協程調度器,每個協程調度器負責調度與其同屬相同線程的協程運行狀態。

4、acl 協程裏針對 mysql 客戶端庫的協程化是否修改了 mysql 庫的源碼?

沒有。mysql 客戶端庫使用的系統 IO API 爲 read/write/poll,而 acl 協程庫 HOOK 了系統底層的 IO 過程,因此當將用戶程序與 mysql 庫及 acl 協程庫一起編譯後,mysql 庫的 IO 過程直接被 acl 協程庫 HOOK 的 API 接管,從而將 mysql 客戶端庫協程化而無須修改一行 mysql 庫代碼。

5、acl 協程庫支持域名解析功能嗎?

支持。很多 C/C++ 實現的協程庫並未實現 gethostbyname(_r) 函數,導致用戶在使用協程編程遇到域名解析時還需要藉助單獨的線程來完成,acl 庫本身從 DNS 協議層次實現了域名解析過程,acl 協程庫基於此功能模塊 HOOK 了系統的 gethostbyname(_r) API 而無須藉助第三方函數庫或起單獨的線程完成域名解析。

6、acl 協程庫的系統 errno 號如何處理?

acl 協程庫實現了協程安全的 errno 號,正如之前使用多線程編程時 errno 可以與每個線程綁定一樣,在 acl 協程庫裏 errno 也是與每個 acl 協程進行綁定的。因此,當你調用 strerror(errno) 時也是協程安全的。

7、如果啓動的協程過多,會不會對於後端例如 mysql 之類服務造成併發壓力?如何避免?

當啓動用協程較多且都需要 mysql 操作時的確會造成 mysql 服務器的併發壓力。爲避免此併發壓力,acl 協程庫提供了協程信號量,用來針對後端不支持高併發的服務提供連接保護。

 

(五)、服務器模塊

1、有幾種服務器編程模型?均有何特點?

目前 acl 庫中提供:進程池模型、線程池模型、非阻塞模型、協程模型、UDP 通信模型、觸發器模型。其中各個編程模型的特點如下:

進程池模型:每個進程處理一個客戶端連接,當需要處理多個連接時則需要啓動多個進程,此模型的最大缺點是併發度低,優點是編程簡單;

線程池模型:由多個線程組成線程池處理大量的客戶端連接,只有當某個連接有數據可讀時該連接纔會與一個線程綁定,處理完畢則線程歸還給線程池,此模型的優點是啓動少數線程便處理較大併發,缺點是需要注意線程編程時的線程安全問題;

非阻塞模型:一個進程內僅有一個工作線程,通過採用非阻塞通信方式可以支持非常大的客戶端併發連接,優點是資源消耗小、支持大併發、性能高,缺點是編程複雜度高;

協程模型:每個客戶端連接與一個協程綁定,每個進程內一個工作線程,每個線程內可以創建大量的協程,優點是支持大併發、性能高、編程簡單、應用場景比較廣,缺點是佔用內存要比非阻塞模型高;

UDP通信模型:支持簡單的 UDP 通信方式;

觸發器模型:常用在定時任務的應用場景中。

以上的服務模型均可啓動多個進程,通過配置文件的配置項來決定啓動進程的數量。

2、acl_master 的作用是什麼?支持哪些平臺?

acl_master 爲由以上各個服務器編寫的服務進程的控制管理程序, acl_master 啓動、停止各個服務子進程,控制子進程的啓動數量及預啓動策略,監控子進程的異常情況;acl_master 有點類似於 LINUX 下的 xinetd 服務進程,不同之處是 acl_master 功能更完善強大,支持服務子進程的常駐留、半駐留,而 xinetd 則只針對一個連接創建一個進程,不能用於高併發的服務應用場景。

目前 acl_master 進程僅支持 LINUX/MACOS/FREEBSD/SOLARIS(X86)等 UNIX 平臺,不支持 WINDOWS 平臺。

3、沒有 acl_master 控制管理,服務子進程是否可以單獨運行?

可以。在沒有 acl_master 的情況下,由以上各個服務模型編寫的服務程序可以通過手工方式啓動。啓動方式一般爲:./xxxx alone xxxx.cf,這樣服務程序便以 alone 模式啓動運行,具體情況可以參考 main.cpp 裏的啓動方式;在 WINDOWS 平臺下只能是以 alone 模式手工啓動運行。

4、手工模式下運行時遇到 “idle timeout -- exiting, idle” 怎麼辦?

因爲  acl 的服務器編程模型均支持半駐留方式(即運行空閒一段時間或處理連接次數達到設定值後會自動退出,這樣的好處是:可以定期通過進程退出釋放可能存在的資源泄露,另一方面便於用戶在開發時通過 valgrind 進行內存檢查),如果讓進程不退出,可以在 alone 模式下給服務程序傳遞啓動配置文件,如啓動方式爲:./xxxx alone xxxx.cf(傳遞方式可以看 main.cpp 和相關頭文件),不同的服務器模型分別採取下面不同的配置項:

進程池模型:將配置項 single_use_limit 和 single_idle_limit 設爲 0;

線程池模型:將配置項 ioctl_use_limit 和 ioctl_idle_limit 設爲 0;

非阻塞模型:將配置項 aio_use_limit 和 aio_idle_limit 設爲 0;

協程模型:將配置項 fiber_use_limit 和 fiber_idle_limit 設爲 0;

UDP通信模型:將配置項 udp_use_limit 和 udp_idle_limit 設爲 0;

觸發器模型:將配置項 trigger_use_limit 設爲。

5、acl_master 控制模式下,服務子進程如何預啓動多個進程?

需要修改每個服務子進程的配置文件,將配置項:master_maxproc 及 master_prefork 設置成要啓動的進程數(設置值需相同),同時需要將 xxx_use_limit 及 xxx_idle_limit 配置項設成 0 以防止子進程空閒退出,xxx_use_limit 及 xxx_idle_limit 的依每種服務器模型而不同,具體可參考上面(4)中的說明。

6、acl_master 控制模式下,如何只監聽內網地址?

在 acl_master 模式下,可以將 master_service 配置項支持模糊匹配方式,即可以將監聽地址寫成 192.168.*.*:xxx 或 10.0.*.*:xxx 方式,這樣 acl_master 會自動掃描服務器所有的網卡地址,但只監聽服務匹配條件的內網地址,這樣爲統一部署提供方便。

 

(六)、郵件&mime模塊

。。。

 

微博:http://weibo.com/zsxxsz

qq 羣:242722074

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章