国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁 微信小程序 微信開發(fā) 微信是如何用libco支撐8億用戶的

微信是如何用libco支撐8億用戶的

Nov 21, 2016 pm 01:35 PM

 導(dǎo)語

  ibco是微信后臺大規(guī)模使用的c/c++協(xié)程庫,2013年至今穩(wěn)定運(yùn)行在微信后臺的數(shù)萬臺機(jī)器上。libco在2013年的時候作為騰訊六大開源項(xiàng)目首次開源,我們最近做了一次較大的更新,同步更新在https://github.com/tencent/libco?上。libco支持后臺敏捷的同步風(fēng)格編程模式,同時提供系統(tǒng)的高并發(fā)能力。

  libco支持的特性

  無需侵入業(yè)務(wù)邏輯,把多進(jìn)程、多線程服務(wù)改造成協(xié)程服務(wù),并發(fā)能力得到百倍提升;

  支持CGI框架,輕松構(gòu)建web服務(wù)(New);

  支持gethostbyname、mysqlclient、ssl等常用第三庫(New);

  可選的共享?xiàng)DJ剑瑔螜C(jī)輕松接入千萬連接(New);

  完善簡潔的協(xié)程編程接口

  – 類pthread接口設(shè)計(jì),通過co_create、co_resume等簡單清晰接口即可完成協(xié)程的創(chuàng)建與恢復(fù); – 類__thread的協(xié)程私有變量、協(xié)程間通信的協(xié)程信號量co_signal (New); – 非語言級別的lambda實(shí)現(xiàn),結(jié)合協(xié)程原地編寫并執(zhí)行后臺異步任務(wù) (New); – 基于epoll/kqueue實(shí)現(xiàn)的小而輕的網(wǎng)絡(luò)框架,基于時間輪盤實(shí)現(xiàn)的高性能定時器;

  libco產(chǎn)生的背景

  早期微信后臺因?yàn)闃I(yè)務(wù)需求復(fù)雜多變、產(chǎn)品要求快速迭代等需求,大部分模塊都采用了半同步半異步模型。接入層為異步模型,業(yè)務(wù)邏輯層則是同步的多進(jìn)程或多線程模型,業(yè)務(wù)邏輯的并發(fā)能力只有幾十到幾百。隨著微信業(yè)務(wù)的增長,系統(tǒng)規(guī)模變得越來越龐大,每個模塊很容易受到后端服務(wù)/網(wǎng)絡(luò)抖動的影響。

  異步化改造的選擇

  為了提升微信后臺的并發(fā)能力,一般的做法是把現(xiàn)網(wǎng)的所有服務(wù)改成異步模型。這種做法工程量巨大,從框架到業(yè)務(wù)邏輯代碼均需要做一次徹底的改造,耗時耗力而且風(fēng)險(xiǎn)巨大。于是我們開始考慮使用協(xié)程。

  但使用協(xié)程會面臨以下挑戰(zhàn):

  業(yè)界協(xié)程在c/c++環(huán)境下沒有大規(guī)模應(yīng)用的經(jīng)驗(yàn);

  如何控制協(xié)程調(diào)度;

  如何處理同步風(fēng)格的API調(diào)用,如Socket、mysqlclient等;

  如何處理已有全局變量、線程私有變量的使用;

  最終我們通過libco解決了上述的所有問題,實(shí)現(xiàn)了對業(yè)務(wù)邏輯非侵入的異步化改造。我們使用libco對微信后臺上百個模塊進(jìn)行了協(xié)程異步化改造,改造過程中業(yè)務(wù)邏輯代碼基本無修改。至今,微信后臺絕大部分服務(wù)都已是多進(jìn)程或多線程協(xié)程模型,并發(fā)能力相比之前有了質(zhì)的提升,而libco也成為了微信后臺框架的基石。

  libco框架

  libco在框架分為三層,分別是接口層、系統(tǒng)函數(shù)Hook層以及事件驅(qū)動層。

2020.jpg
  同步風(fēng)格API的處理

  對于同步風(fēng)格的API,主要是同步的網(wǎng)絡(luò)調(diào)用,libco的首要任務(wù)是消除這些等待對資源的占用,提高系統(tǒng)的并發(fā)性能。一個常規(guī)的網(wǎng)絡(luò)后臺服務(wù),我們可能會經(jīng)歷connect、write、read等步驟,完成一次完整的網(wǎng)絡(luò)交互。當(dāng)同步的調(diào)用這些API的時候,整個線程會因?yàn)榈却W(wǎng)絡(luò)交互而掛起。

  雖然同步編程風(fēng)格的并發(fā)性能并不好,但是它具有代碼邏輯清晰、易于編寫的優(yōu)點(diǎn),并可支持業(yè)務(wù)快速迭代敏捷開發(fā)。為了繼續(xù)保持同步編程的優(yōu)點(diǎn),并且不需修改線上已有的業(yè)務(wù)邏輯代碼,libco創(chuàng)新地接管了網(wǎng)絡(luò)調(diào)用接口(Hook),把協(xié)程的讓出與恢復(fù)作為異步網(wǎng)絡(luò)IO中的一次事件注冊與回調(diào)。當(dāng)業(yè)務(wù)處理遇到同步網(wǎng)絡(luò)請求的時候,libco層會把本次網(wǎng)絡(luò)請求注冊為異步事件,本協(xié)程讓出CPU占用,CPU交給其它協(xié)程執(zhí)行。libco會在網(wǎng)絡(luò)事件發(fā)生或者超時的時候,自動的恢復(fù)協(xié)程執(zhí)行。

  大部分同步風(fēng)格的API我們都通過Hook的方法來接管了,libco會在恰當(dāng)?shù)臅r機(jī)調(diào)度協(xié)程恢復(fù)執(zhí)行。

  千萬級協(xié)程支持

  libco默認(rèn)是每一個協(xié)程獨(dú)享一個運(yùn)行棧,在協(xié)程創(chuàng)建的時候,從堆內(nèi)存分配一個固定大小的內(nèi)存作為該協(xié)程的運(yùn)行棧。如果我們用一個協(xié)程處理前端的一個接入連接,那對于一個海量接入服務(wù)來說,我們的服務(wù)的并發(fā)上限就很容易受限于內(nèi)存。為此,libco也提供了stackless的協(xié)程共享?xiàng)DJ?,可以設(shè)置若干個協(xié)程共享同一個運(yùn)行棧。同一個共享?xiàng)O碌膮f(xié)程間切換的時候,需要把當(dāng)前的運(yùn)行棧內(nèi)容拷貝到協(xié)程的私有內(nèi)存中。為了減少這種內(nèi)存拷貝次數(shù),共享?xiàng)5膬?nèi)存拷貝只發(fā)生在不同協(xié)程間的切換。當(dāng)共享?xiàng)5恼加谜咭恢睕]有改變的時候,則不需要拷貝運(yùn)行棧。


  libco協(xié)程的共享協(xié)程棧模式使得單機(jī)很容易接入千萬連接,只需創(chuàng)建足夠多的協(xié)程即可。我們通過libco共享?xiàng)DJ絼?chuàng)建1千萬的協(xié)程(E5-2670 v3 @ 2.30GHz * 2, 128G內(nèi)存),每10萬個協(xié)程共享的使用128k內(nèi)存,整個穩(wěn)定echo服務(wù)的時候總內(nèi)存消耗大概為66G。

  協(xié)程私有變量

  多進(jìn)程程序改造為多線程程序時候,我們可以用__thread來對全局變量進(jìn)行快速修改,而在協(xié)程環(huán)境下,我們創(chuàng)造了協(xié)程變量ROUTINE_VAR,極大簡化了協(xié)程的改造工作量。

  因?yàn)閰f(xié)程實(shí)質(zhì)上是線程內(nèi)串行執(zhí)行的,所以當(dāng)我們定義了一個線程私有變量的時候,可能會有重入的問題。比如我們定義了一個__thread的線程私有變量,原本是希望每一個執(zhí)行邏輯獨(dú)享這個變量的。但當(dāng)我們的執(zhí)行環(huán)境遷移到協(xié)程了之后,同一個線程私有變量,可能會有多個協(xié)程會操作它,這就導(dǎo)致了變量沖入的問題。為此,我們在做libco異步化改造的時候,把大部分的線程私有變量改成了協(xié)程級私有變量。協(xié)程私有變量具有這樣的特性:當(dāng)代碼運(yùn)行在多線程非協(xié)程環(huán)境下時,該變量是線程私有的;當(dāng)代碼運(yùn)行在協(xié)程環(huán)境的時候,此變量是協(xié)程私有的。底層的協(xié)程私有變量會自動完成運(yùn)行環(huán)境的判斷并正確返回所需的值。

  協(xié)程私有變量對于現(xiàn)有環(huán)境同步到異步化改造起了舉足輕重的作用,同時我們定義了一個非常簡單方便的方法定義協(xié)程私有變量,簡單到只需一行聲明代碼即可。

  gethostbyname的Hook方法

  對于現(xiàn)網(wǎng)服務(wù),有可能需要通過系統(tǒng)的gethostbyname API接口去查詢DNS獲取真實(shí)地址。我們在協(xié)程化改造的時候,發(fā)現(xiàn)我們hook的socket族函數(shù)對gethostbyname不適用,當(dāng)一個協(xié)程調(diào)用了gethostbyname時會同步等待結(jié)果,這就導(dǎo)致了同線程內(nèi)的其它協(xié)程被延時執(zhí)行。我們對glibc的gethostbyname源碼進(jìn)行了研究,發(fā)現(xiàn)hook不生效主要是由于glibc內(nèi)部是定義了__poll方法來等待事件,而不是通用的poll方法;同時glibc還定義了一個線程私有變量,不同協(xié)程的切換可能會重入導(dǎo)致數(shù)據(jù)不準(zhǔn)確。最終gethostbyname協(xié)程異步化是通過Hook __poll方法以及定義協(xié)程私有變量解決的。

  gethostbyname是glibc提供的同步查詢dns接口,業(yè)界還有很多優(yōu)秀的gethostbyname的異步化解決方案,但是這些實(shí)現(xiàn)都需要引入一個第三方庫并且要求底層提供異步回調(diào)通知機(jī)制。libco通過hook方法,在不修改glibc源碼的前提下實(shí)現(xiàn)了的gethostbyname的異步化。

  協(xié)程信號量

  在多線程環(huán)境下,我們會有線程間同步的需求,比如一個線程的執(zhí)行需要等待另一個線程的信號,對于這種需求,我們通常是使用pthread_signal 來解決的。在libco中,我們定義了協(xié)程信號量co_signal用于處理協(xié)程間的并發(fā)需求,一個協(xié)程可以通過co_cond_signal與co_cond_broadcast來決定通知一個等待的協(xié)程或者喚醒所有等待協(xié)程。

  總結(jié)

  libco是一個高效的c/c++協(xié)程庫,提供了完善的協(xié)程編程接口、常用的Socket族函數(shù)Hook等,使得業(yè)務(wù)可用同步編程模型快速迭代開發(fā)。隨著幾年來的穩(wěn)定運(yùn)行,libco作為微信后臺框架的基石發(fā)揮了舉足輕重的作用。

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機(jī)

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強(qiáng)大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級代碼編輯軟件(SublimeText3)