官术网_书友最值得收藏!

2.1.2 物理隔離

物理隔離是將所有壓測(cè)數(shù)據(jù)寫入獨(dú)立的數(shù)據(jù)區(qū)域的方法,這一數(shù)據(jù)區(qū)域與真實(shí)的數(shù)據(jù)庫(kù)(或表)在物理上完全隔離,從而最大限度規(guī)避了數(shù)據(jù)污染風(fēng)險(xiǎn),清理數(shù)據(jù)也比較方便。

要做到物理隔離,軟件系統(tǒng)需要具備兩項(xiàng)基礎(chǔ)能力:壓測(cè)流量打標(biāo)與透?jìng)?,以及影子?kù)/表的支持。

壓測(cè)流量打標(biāo)與透?jìng)鞑煌谶壿嫺綦x中的數(shù)據(jù)實(shí)體內(nèi)打標(biāo),我們現(xiàn)在需要在流量中打標(biāo),以區(qū)分真實(shí)請(qǐng)求和壓測(cè)請(qǐng)求。壓測(cè)流量打標(biāo)與透?jìng)骶唧w的做法如圖2.2所示,在用戶訪問請(qǐng)求的HTTP頭中置入一個(gè)特殊的壓測(cè)標(biāo)識(shí),當(dāng)流量進(jìn)入內(nèi)網(wǎng)并在各服務(wù)和中間件之間傳遞時(shí),我們需要確保這一標(biāo)識(shí)始終能夠完整透?jìng)?,最終抵達(dá)數(shù)據(jù)層,數(shù)據(jù)層根據(jù)流量類型將數(shù)據(jù)寫入隔離區(qū)域(如影子表)或正常區(qū)域(如真實(shí)表)。在圖2.2中,我們可以看到壓測(cè)流量的傳遞路徑(紅色路徑),因此壓測(cè)流量打標(biāo)與透?jìng)饔址Q為“流量染色”。

圖2.2 壓測(cè)流量打標(biāo)與透?jìng)?/p>

在這一過程中有兩點(diǎn)要格外注意。首先,在請(qǐng)求跨線程傳遞和請(qǐng)求協(xié)議轉(zhuǎn)換的時(shí)候我們也要保證壓測(cè)標(biāo)識(shí)能夠透?jìng)鳎词箟簻y(cè)標(biāo)識(shí)的存放位置發(fā)生了改變,例如,HTTP流量進(jìn)入內(nèi)網(wǎng)后轉(zhuǎn)換成RPC(Remote Procedure Call)流量,此時(shí)需要將HTTP頭中的壓測(cè)標(biāo)識(shí)轉(zhuǎn)移至RPC請(qǐng)求的上下文中,避免丟失。其次,當(dāng)請(qǐng)求經(jīng)過異步化中間件(如消息隊(duì)列)時(shí),壓測(cè)標(biāo)識(shí)也應(yīng)當(dāng)傳遞無誤,例如,針對(duì)消息隊(duì)列,當(dāng)帶有壓測(cè)標(biāo)識(shí)的生產(chǎn)者推送消息時(shí),我們需要將壓測(cè)標(biāo)識(shí)轉(zhuǎn)存至數(shù)據(jù)中,以免丟失,當(dāng)異步服務(wù)消費(fèi)消息時(shí),再將該標(biāo)識(shí)恢復(fù)至消費(fèi)者的請(qǐng)求體或上下文中繼續(xù)傳遞。

上述工作涉及不少技術(shù)“改造”點(diǎn),其中涉及中間件的改造工作將在2.2節(jié)中講解,這里我們先來了解一下跨線程壓測(cè)標(biāo)識(shí)透?jìng)鞯募夹g(shù)實(shí)現(xiàn)方案,我們以阿里巴巴開源的TransmittableThreadLocal為例介紹基于Java語言的實(shí)現(xiàn)過程。

我們知道,Java語言提供的ThreadLocal對(duì)象可以存儲(chǔ)當(dāng)前線程的共享變量,但它無法應(yīng)對(duì)跨線程的情況,此時(shí)TransmittableThreadLocal就有了用武之地。在TransmittableThreadLocal中設(shè)有一個(gè)Holder來保存每個(gè)線程所持有的所有ThreadLocal對(duì)象,并在線程提交的時(shí)候進(jìn)行上下文的復(fù)制,這樣就能夠保證變量在各線程間正確地傳遞。

我們通過以下代碼進(jìn)一步展示TransmittableThreadLocal的能力。這段代碼很簡(jiǎn)單,首先創(chuàng)建一個(gè)TransmittableThreadLocal對(duì)象,然后在父線程中設(shè)置一個(gè)名為perftest的變量作為壓測(cè)標(biāo)識(shí),在子線程中嘗試獲取這個(gè)變量。

public class ThreadTest {
       private static ThreadLocal<String> TTL = new TransmittableThreadLocal<>();
       public static void main(String[] args) throws InterruptedException {
              new Thread(() -> {
                     // 在父線程中設(shè)置標(biāo)識(shí)
                     TTL.set(“perftest”);
                     new Thread(() -> {
                            // 在子線程中輸出標(biāo)識(shí)
                            System.out.println(TTL.get());
                     }).start();
              }).start();
       }
}

如圖2.3所示,我們成功在子線程中得到了這一變量,實(shí)現(xiàn)了壓測(cè)標(biāo)識(shí)透?jìng)鞯男Ч?/p>

圖2.3 壓測(cè)標(biāo)識(shí)由父線程透?jìng)髦磷泳€程

具備了壓測(cè)流量打標(biāo)與透?jìng)鞯哪芰螅覀冊(cè)賮硖接懹白訋?kù)/表的支持,這部分內(nèi)容比較多而且相對(duì)獨(dú)立,我們專門用2.1.3節(jié)進(jìn)行講述。

主站蜘蛛池模板: 阜康市| 梁河县| 武安市| 大同市| 游戏| 福建省| 赤水市| 阿合奇县| 仙游县| 黄梅县| 巧家县| 安徽省| 衡东县| 高雄县| 平谷区| 肇州县| 汝城县| 广宗县| 舟曲县| 子长县| 前郭尔| 新和县| 临猗县| 彭阳县| 合山市| 邵武市| 田阳县| 平原县| 佛教| 车致| 湛江市| 静乐县| 长泰县| 西宁市| 即墨市| 长宁区| 尉氏县| 大竹县| 吴桥县| 钟祥市| 贵德县|