淺談軟件工程中的Shim

什么是Shim

Shim一詞的原本含義是“墊片”或者“楔子”艇抠,而首先將這個(gè)詞應(yīng)用到軟件工程領(lǐng)域的似乎是微軟漆魔。根據(jù)Wikipedia的總結(jié):

A shim is a library that transparently intercepts API calls and changes the arguments passed, handles the operation itself or redirects the operation elsewhere. Shims can be used to support an old API in a newer environment, or a new API in an older environment. Shims can also be used for running programs on different software platforms than they were developed for.

按照這個(gè)釋義互躬,Shim是一種(小型的)庫(kù)耍共,負(fù)責(zé)透明地?cái)r截API調(diào)用苗傅,并更改其參數(shù)滑潘,或?qū)⑵滢D(zhuǎn)發(fā)至其他組件,或者自行處理查近。它用于在新環(huán)境中支持舊API(或反過(guò)來(lái))眉踱,以及使程序能夠在非特定支持的平臺(tái)上運(yùn)行。下面舉兩個(gè)栗子簡(jiǎn)單說(shuō)明下Shim在不同場(chǎng)景下的實(shí)現(xiàn)霜威。

Kubernetes中的Shim

熟悉K8s的看官可能會(huì)立即想起該體系中的containerd-shim組件谈喳,它作為containerd與OCI運(yùn)行時(shí)交互的中間層發(fā)揮作用。

展開來(lái)講戈泼,當(dāng)Kubelet請(qǐng)求containerd來(lái)創(chuàng)建容器時(shí)婿禽,并不會(huì)由containerd直接來(lái)操作,而是創(chuàng)建一個(gè)叫做containerd-shim的進(jìn)程大猛,且containerd-shim會(huì)進(jìn)一步啟動(dòng)containerd-shim-runc-v2進(jìn)程并立即退出扭倾。這樣,containerd-shim-runc-v2就和containerd脫離了關(guān)系(因?yàn)閏ontainerd-shim-runc-v2的父進(jìn)程此時(shí)為systemd)挽绩,而通過(guò)runc啟動(dòng)的容器進(jìn)程父進(jìn)程為containerd-shim-runc-v2膛壹,負(fù)責(zé)后續(xù)接管容器內(nèi)虛擬OS的管理和狀態(tài)上報(bào)。

也就是說(shuō)唉堪,即使containerd守護(hù)進(jìn)程異常退出模聋,容器也不會(huì)受影響,將兩者解耦開來(lái)就是containerd-shim最重要的作用巨坊。

Flink Hive Catalog中的Shim

Shim支持不同API版本這一方面的話撬槽,我們可以參考一下Flink(當(dāng)然其他很多開源組件也同理)的設(shè)計(jì)思路。

我們知道趾撵,F(xiàn)link 1.14支持從1.0.0~3.1.2各版本的Hive侄柔,而橫跨這么多版本的Hive API底層邏輯勢(shì)必不會(huì)完全一致共啃,如果將全部版本的Hive依賴都引入進(jìn)來(lái),也一定會(huì)造成沖突暂题,這里就需要Shims發(fā)揮作用移剪。在代碼中,HiveShim是一個(gè)接口薪者,定義了所有需要做兼容性支持的方法纵苛,如下圖所示。

該接口的實(shí)現(xiàn)類就從HiveShimV100一直命名至HiveShimV312言津,每個(gè)類都會(huì)override對(duì)應(yīng)版本出現(xiàn)變更的方法攻人。例如,alterPartition()方法對(duì)應(yīng)1.0.0版本的實(shí)現(xiàn)是:

    @Override
    public void alterPartition(
            IMetaStoreClient client, String databaseName, String tableName, Partition partition)
            throws InvalidOperationException, MetaException, TException {
        String errorMsg = "Failed to alter partition for table %s in database %s";
        try {
            Method method =
                    client.getClass()
                            .getMethod(
                                    "alter_partition", String.class, String.class, Partition.class);
            method.invoke(client, databaseName, tableName, partition);
        } catch (InvocationTargetException ite) {
            // ...
        } catch (NoSuchMethodException | IllegalAccessException e) {
            // ...
        }
    }

而由于Hive Metastore提供的API alter_partition() 方法的簽名發(fā)生了變化悬槽,對(duì)應(yīng)2.1.0版本的實(shí)現(xiàn)是:

    @Override
    public void alterPartition(
            IMetaStoreClient client, String databaseName, String tableName, Partition partition)
            throws InvalidOperationException, MetaException, TException {
        String errorMsg = "Failed to alter partition for table %s in database %s";
        try {
            Method method =
                    client.getClass()
                            .getMethod(
                                    "alter_partition",
                                    String.class,
                                    String.class,
                                    Partition.class,
                                    EnvironmentContext.class);
            method.invoke(client, databaseName, tableName, partition, null);
        } catch (InvocationTargetException ite) {
            // ...
        } catch (NoSuchMethodException | IllegalAccessException e) {
            // ...
        }
    }

顯然怀吻,由于Flink環(huán)境并不能事先確定外部Hive的版本,所以全部的Shim方法都需要依賴反射調(diào)用初婆。另外蓬坡,為了保持向后兼容性,Shim實(shí)現(xiàn)類從低版本到高版本會(huì)自然形成鏈?zhǔn)嚼^承關(guān)系磅叛,如下圖所示屑咳。

在Flink App啟動(dòng)時(shí),HiveShimLoader組件會(huì)根據(jù)Catalog定義時(shí)傳入的hive-version參數(shù)或者自動(dòng)探測(cè)到的Hive版本加載特定的HiveShim弊琴,不再贅述兆龙。

不用Shim的場(chǎng)景?

在Flink Connector體系內(nèi)也能找到這類場(chǎng)景访雪,如ES Connector就使用了3個(gè)不同的module來(lái)實(shí)現(xiàn):flink-connector-elasticsearch5详瑞、flink-connector-elasticsearch6flink-connector-elasticsearch7

造成這種不同選擇的原因有二:一是ES版本并不像Hive版本那么細(xì)分,即使6.x和7.x之間有大量的重復(fù)代碼也在可接受的范圍內(nèi)臣缀;二是5.x采用Transport Client進(jìn)行通信,而6.x和7.x采用REST High Level Client進(jìn)行通信泻帮,相當(dāng)于破壞了統(tǒng)一的接口規(guī)約(統(tǒng)一接口的示例如上文中Hive的IMetaStoreClient)精置,在這基礎(chǔ)上再使用反射調(diào)用會(huì)更加復(fù)雜,得不償失锣杂。

Iceberg基于同樣的考慮脂倦,在0.13版本之后也對(duì)Spark和Flink做了非Shim化的支持,看官可以去GitHub看看元莫。

vs 適配器模式赖阻?

在筆者看來(lái),Shim是適配器模式的一種另辟蹊徑的實(shí)現(xiàn)方式踱蠢。參考GoF對(duì)適配器模式的解說(shuō):

The adapter design pattern solves problems like:

  • How can a class be reused that does not have an interface that a client requires?
  • How can classes that have incompatible interfaces work together?
  • How can an alternative interface be provided for a class?

The adapter design pattern describes how to solve such problems:

  • Define a separate adapter class that converts the (incompatible) interface of a class (adaptee) into another interface (target) clients require.
  • Work through an adapter to work with (reuse) classes that do not have the required interface.

用上文HiveCatalog的例子套用這個(gè)定義火欧,HiveShim就是適配器本體棋电,而Hive的原生API就是被適配者(adaptee),各個(gè)不同版本的HiveShim實(shí)現(xiàn)的方法就是目標(biāo)接口(target)苇侵。一家之言赶盔,僅供參考。

The End

晚安晚安榆浓。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末于未,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子陡鹃,更是在濱河造成了極大的恐慌烘浦,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萍鲸,死亡現(xiàn)場(chǎng)離奇詭異闷叉,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)猿推,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門片习,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人蹬叭,你說(shuō)我怎么就攤上這事藕咏。” “怎么了秽五?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵孽查,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我坦喘,道長(zhǎng)盲再,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任瓣铣,我火速辦了婚禮答朋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘棠笑。我一直安慰自己梦碗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布蓖救。 她就那樣靜靜地躺著洪规,像睡著了一般。 火紅的嫁衣襯著肌膚如雪循捺。 梳的紋絲不亂的頭發(fā)上斩例,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音从橘,去河邊找鬼念赶。 笑死础钠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的晶乔。 我是一名探鬼主播珍坊,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼正罢!你這毒婦竟也來(lái)了阵漏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤翻具,失蹤者是張志新(化名)和其女友劉穎履怯,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裆泳,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡叹洲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了工禾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片运提。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖闻葵,靈堂內(nèi)的尸體忽然破棺而出民泵,到底是詐尸還是另有隱情,我是刑警寧澤槽畔,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布栈妆,位于F島的核電站,受9級(jí)特大地震影響厢钧,放射性物質(zhì)發(fā)生泄漏鳞尔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一早直、第九天 我趴在偏房一處隱蔽的房頂上張望寥假。 院中可真熱鬧,春花似錦霞扬、人聲如沸昧旨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蒋得,卻和暖如春级及,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背额衙。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工饮焦, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怕吴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓县踢,卻偏偏與公主長(zhǎng)得像转绷,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子硼啤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容