1. 程式人生 > >jenkins原始碼分析 —— 傳送遠端請求(二)

jenkins原始碼分析 —— 傳送遠端請求(二)

本文解析jenkins主節點向從節點發送遠端請求過程的原始碼

SendingtheRemoteRequest.png

job執行shell命令入口

入口位於jenkins-core專案下的CommandInterpreter類

public boolean perform(AbstractBuild<?,?> build, Launcher launcher, TaskListener listener) throws InterruptedException {
...
 r = join(launcher.launch().cmds(buildCommandLine(script)).envs(envVars).stdout(listener).
pwd(ws).start());
...
}

通過上面的start方法啟動一個新的程序

跳轉到jenkins-core專案下的launcher類

public Proc start() throws IOException {
    return launch(this);
}

然後呼叫launcher類的內部類RemoteLauncher的launch方法

public Proc launch(ProcStarter ps) throws IOException {
   ...
   return new ProcImpl(getChannel().call(new RemoteLaunchCallable(
ps.commands, ps.masks, ps.envs, in, ps.reverseStdin, out, ps.reverseStdout, err, ps.reverseStderr, ps.quiet, workDir, listener)));
   ...
}

通過Channel.call()傳送遠端請求

通過getChannel().call()呼叫remoting專案(即從節點的slave.jar)的Channel類的call方法

public <V,T extends Throwable> V call(Callable<V,T> callable) throws
IOException, T, InterruptedException {
           ...
            request = new UserRequest<V, T>(this, callable);
            UserResponse<V,T> r = request.call(this);
           return r.retrieve(this, UserRequest.getClassLoader(callable));
           ...
}

然後通過new UserRequest<V, T>(this, callable)方法來序列化callable(傳入的是實現callable介面的RemoteLaunchCallable)並建立位元組陣列

通過new UserReques初始化UserRequest

位於remoting專案UserRequest類的構造方法

   public UserRequest(Channel local, Callable<?,EXC> c) throws IOException {
        exports = local.startExportRecording();
       try {
            request = serialize(c,local);
       } finally {
            exports.stopRecording();
       }

       this.toString = c.toString();
        ClassLoader cl = getClassLoader(c);
        classLoaderProxy = RemoteClassLoader.export(cl,local);
   }

1.通過serialize方法序列化RemoteLaunchCallable並建立位元組陣列

   private byte[] _serialize(Object o, final Channel channel) throws IOException {
        Channel old = Channel.setCurrent(channel);
       try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos;
           if (channel.remoteCapability.supportsMultiClassLoaderRPC())
                oos = new MultiClassLoaderSerializer.Output(channel,baos);
           else
                oos = new ObjectOutputStream(baos);

            oos.writeObject(o);
           return baos.toByteArray();
       } finally {
            Channel.setCurrent(old);
       }
   }

2. 建立一個ClassLoader代理

ClassLoader cl = getClassLoader(c);
classLoaderProxy = RemoteClassLoader.export(cl,local);

3. 回到getChannel().call()方法,傳送UserRequest到slave節點

UserResponse<V,T> r = request.call(this);
return r.retrieve(this, UserRequest.getClassLoader(callable));

通過request.call(this)呼叫remoting專案的Request類的call方法來發送UserRequest

    //Sends this request to a remote system, and blocks until we receives a response.
    public final RSP call(Channel channel) throws EXC, InterruptedException, IOException {
       ...          
       // Channel.send() locks channel, and there are other call sequences
       // (  like Channel.terminate()->Request.abort()->Request.onCompleted()  )
       // that locks channel -> request, so lock objects in the same order
       synchronized(channel) {
           synchronized(this) {
                response=null;

                channel.pendingCalls.put(id,this);
                channel.send(this);
           }
       }
       ...
   }

通過channel.send(this)方法,channel把UserRequest物件寫入輸出流

然後等待response響應

相關推薦

jenkins原始碼分析 —— 傳送遠端請求

本文解析jenkins主節點向從節點發送遠端請求過程的原始碼job執行shell命令入口入口位於jenkins-core專案下的CommandInterpreter類public boolean perform(AbstractBuild<?,?> build,

elasticsearch原始碼分析之啟動過程

最近開始廣泛的使用elasticsearch,也開始寫一些java程式碼了,為了提高java程式碼能力,也為了更加深入一點了解elasticsearch的內部運作機制,所以開始看一些elasticsearch的原始碼了。對於這種廣受追捧的開源專案,細細品讀一定會受益匪淺,

springMVC原始碼分析--動態樣式ThemeResolver

ThemeResolver的體系結構如下:1、介面ThemeResolver中定義的介面是比較簡單的,提供兩個介面:(1)resolveThemeName獲取樣式名(2)setThemeName設定樣式名public interface ThemeResolver { /

雲客Drupal8原始碼分析之實體Entity配置實體基類

配置實體基類是系統定義的一個用於配置實體的抽象基類,繼承自實體基類,完成了配置實體的大部分通用功能,具體的配置實體往往會繼承它,比如使用者角色實體,這樣寫少量程式碼即可,類定義如下: Drupal\Core\Config\Entity\ConfigEntityBase 實

Android4.4.2原始碼分析之WiFi模組

接著上一篇繼續對WiFi原始碼的分析 onResume方法中 6>,首先是呼叫WiFiEnabler的resume方法對switch進行管理 接下來註冊廣播 getActivity().registerReceiver(mReceiver, mFilter);

精盡MyBatis原始碼分析 - MyBatis初始化之載入 Mapper 介面與 XML 對映檔案

> 該系列文件是本人在學習 Mybatis 的原始碼過程中總結下來的,可能對讀者不太友好,請結合我的原始碼註釋([Mybatis原始碼分析 GitHub 地址](https://github.com/liu844869663/mybatis-3)、[Mybatis-Spring 原始碼分析 GitHub 地址

精盡MyBatis原始碼分析 - SQL執行過程之 StatementHandler

> 該系列文件是本人在學習 Mybatis 的原始碼過程中總結下來的,可能對讀者不太友好,請結合我的原始碼註釋([Mybatis原始碼分析 GitHub 地址](https://github.com/liu844869663/mybatis-3)、[Mybatis-Spring 原始碼分析 GitHub 地址

以太坊原始碼分析之 P2P網路、節點發現流程

區塊鏈特輯 :https://blog.csdn.net/fusan2004/article/details/80879343,歡迎查閱,原創作品,轉載請標明!上一篇文章簡單介紹了下一些基礎的型別定義,從這一篇開始我們將描述p2p網路的更多細節。從關於節點的定義來看,其實不同

Java Web亂碼分析及解決方案——POST請求亂碼

引言     GET請求的本質表現是將請求引數放在URL位址列中,form表單的Method為GET的情況,引數會被瀏覽器預設編碼,所以亂碼處理方案是一樣的。對於POST請求亂碼,解決起來要比GET簡單,我們關心的重點是在Request Body中。 請求亂碼——Meth

gitlab+jenkins+maven+docker持續集成——maven安裝配置

jenkins gitlab maven 建議安裝3.3.9版本,最新版本貌似有點問題下載地址:#wget http://apache.fayea.com/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz解壓# tar -zxvf

用GraphX分析伴生網絡

math 需要 期望 在一起 pregel 測試 個數 maps shuf 8. 過濾噪聲邊 在當前的伴生關系中,邊的權重是基於一對概念同時出現在一篇論文中的頻率來計算的。這種簡單的權重機制的問題在於:它並沒有對一對概念同時出現的原因加以區分,有時一對概念同時出現是由於它們

Spark原始碼分析之Spark Shell

https://www.cnblogs.com/xing901022/p/6412619.html 文中分析的spark版本為apache的spark-2.1.0-bin-hadoop2.7。 bin目錄結構: -rwxr-xr-x. 1 bigdata bigdata 1089 Dec

Tomcat配置與優化以及遠端debug

Tomcat IO優化 1.BIO方式 BIO方式適用於連線數目比較小且固定的架構,即阻塞式I/O操作, 基於JAVA的HTTP/1.1聯結器  ,這種方式對伺服器資源要求比較高,併發侷限於應用中,JDK1.4以前的唯一選擇,但程式直觀簡單易理解.一個執行緒處理一個請求。缺點:

Git建立本地分支並關聯遠端分支

建立本地分支git branch 分支名 例如:git branch dev,這條命令是基於當前分支建立的本地分支,假設當前分支是master(遠端分支),則是基於master分支建立的本地分支dev。 切換到本地分支git checkout 分支名 例如:git checkout dev,這條命令表示

Android之測量APP效能-分析和除錯 APK

分析和除錯預構建 APK Android Studio 3.0 允許您分析和除錯 APK,無需先從 Android Studio 專案構建這些 APK。 不過,您需要確保使用可除錯版本的 APK。 要開始除錯 APK,請在 Android Studio Welcome 歡迎螢幕中點選&nbs

【Spark核心原始碼】解析“spark-shell”

接著【初探Spark核心】解析“spark-shell”(一)來看 根據main的執行日誌來看,我們直接看一下org.apache.spark.repl.Main.main方法: main方法中建立了SparkILoop物件,作為引數傳遞給了doMain方法,並呼叫了doMain

雲客Drupal8原始碼分析之外掛系統

以下內容僅是一個預覽,完整內容請見文尾: 至此本系列對外掛的介紹全部完成,涵蓋了系統外掛的所有知識 全文目錄(全文10476字): 例項化外掛 外掛對映Plugin mapping 外掛上下文  

資料分析那點事兒

在之前我們給大家講了講什麼是資料分析以及資料分析的目的,資料分析就是通過使用合適的方法進行統計,統計也不是隨隨便便的統計的,需要找對方法。統計分析方法對收集來的大量資料進行分析,提取有用資訊和形成結論而對資料加以詳細研究和概括總結的過程。而資料分析的目的就是通過分析資料找到企業未來的發展情況。今天就給大家

Java傳送http請求HttpClient

public class HttpClientUtil { public static String doGet(String url, Map<String, String> param, String token) { // 建立Httpclient物件 Closeabl

原始碼分析三、Map3-TreeMap

一、概述 通過IDEA看下TreeMap的繼承關係,繼承抽象父類AbstractMap,實現了NavigableMap介面,SortedMap介面,TreeMap是一種有序的Map,從其實現的介面就能看出來。 那麼,首先來看下實現的兩類介面: SortedMap:實