1. 程式人生 > 程式設計 >聊聊nacos client的ServerHttpAgent

聊聊nacos client的ServerHttpAgent

本文主要研究一下nacos client的ServerHttpAgent

HttpAgent

nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/http/HttpAgent.java

public interface HttpAgent {
    /**
     * start to get nacos ip list
     * @return Nothing.
     * @throws NacosException on get ip list error.
     */
    void start() throws NacosException;

    /**
     * invoke http get method
     * @param path http path
     * @param headers http headers
     * @param paramValues http paramValues http
     * @param encoding http encode
     * @param read
TimeoutMs http timeout * @return HttpResult http response * @throws IOException If an input or output exception occurred */ HttpResult httpGet(String path,List<String> headers,List<String> paramValues,String encoding,long readTimeoutMs) throws IOException; /** * invoke http post method * @param path http path * @param headers http headers * @param paramValues http paramValues http * @param encoding http encode * @param read
TimeoutMs http timeout * @return HttpResult http response * @throws IOException If an input or output exception occurred */ HttpResult httpPost(String path,long readTimeoutMs) throws IOException; /** * invoke http delete method * @param path http path * @param headers http headers * @param paramValues http paramValues http * @param encoding http encode * @param read
TimeoutMs http timeout * @return HttpResult http response * @throws IOException If an input or output exception occurred */ HttpResult httpDelete(String path,long readTimeoutMs) throws IOException; /** * get name * @return String */ String getName(); /** * get namespace * @return String */ String getNamespace(); /** * get tenant * @return String */ String getTenant(); /** * get encode * @return String */ String getEncode(); } 複製程式碼
  • HttpAgent定義了start、httpGet、httpPost、httpDelete、getName、getNamespace、getTenant、getEncode方法

ServerHttpAgent

nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java

public class ServerHttpAgent implements HttpAgent {

    private static final Logger LOGGER = LogUtils.logger(ServerHttpAgent.class);

    /**
     * @param path          相對於web應用根,以/開頭
     * @param headers
     * @param paramValues
     * @param encoding
     * @param readTimeoutMs
     * @return
     * @throws IOException
     */
    @Override
    public HttpResult httpGet(String path,long readTimeoutMs) throws IOException {
        final long endTime = System.currentTimeMillis() + readTimeoutMs;
        final boolean isSSL = false;

        String currentServerAddr = serverListMgr.getCurrentServerAddr();
        int maxRetry = this.maxRetry;

        do {
            try {
                List<String> newHeaders = getSpasHeaders(paramValues);
                if (headers != null) {
                    newHeaders.addAll(headers);
                }
                HttpResult result = HttpSimpleClient.httpGet(
                    getUrl(currentServerAddr,path),newHeaders,paramValues,encoding,readTimeoutMs,isSSL);
                if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR
                    || result.code == HttpURLConnection.HTTP_BAD_GATEWAY
                    || result.code == HttpURLConnection.HTTP_UNAVAILABLE) {
                    LOGGER.error("[NACOS ConnectException] currentServerAddr: {},httpCode: {}",serverListMgr.getCurrentServerAddr(),result.code);
                } else {
                    // Update the currently available server addr
                    serverListMgr.updateCurrentServerAddr(currentServerAddr);
                    return result;
                }
            } catch (ConnectException ce) {
                LOGGER.error("[NACOS ConnectException httpGet] currentServerAddr:{},err : {}",ce.getMessage());
            } catch (SocketTimeoutException stoe) {
                LOGGER.error("[NACOS SocketTimeoutException httpGet] currentServerAddr:{}, err : {}",stoe.getMessage());
            } catch (IOException ioe) {
                LOGGER.error("[NACOS IOException httpGet] currentServerAddr: " + serverListMgr.getCurrentServerAddr(),ioe);
                throw ioe;
            }

            if (serverListMgr.getIterator().hasNext()) {
                currentServerAddr = serverListMgr.getIterator().next();
            } else {
                maxRetry --;
                if (maxRetry < 0) {
                    throw new ConnectException("[NACOS HTTP-GET] The maximum number of tolerable server reconnection errors has been reached");
                }
                serverListMgr.refreshCurrentServerAddr();
            }

        } while (System.currentTimeMillis() <= endTime);

        LOGGER.error("no available server");
        throw new ConnectException("no available server");
    }

    @Override
    public HttpResult httpPost(String path,long readTimeoutMs) throws IOException {
        final long endTime = System.currentTimeMillis() + readTimeoutMs;
        boolean isSSL = false;

        String currentServerAddr = serverListMgr.getCurrentServerAddr();
        int maxRetry = this.maxRetry;

        do {

            try {
                List<String> newHeaders = getSpasHeaders(paramValues);
                if (headers != null) {
                    newHeaders.addAll(headers);
                }

                HttpResult result = HttpSimpleClient.httpPost(
                    getUrl(currentServerAddr,currentServerAddr,result.code);
                } else {
                    // Update the currently available server addr
                    serverListMgr.updateCurrentServerAddr(currentServerAddr);
                    return result;
                }
            } catch (ConnectException ce) {
                LOGGER.error("[NACOS ConnectException httpPost] currentServerAddr: {},ce.getMessage());
            } catch (SocketTimeoutException stoe) {
                LOGGER.error("[NACOS SocketTimeoutException httpPost] currentServerAddr: {}, err : {}",stoe.getMessage());
            } catch (IOException ioe) {
                LOGGER.error("[NACOS IOException httpPost] currentServerAddr: " + currentServerAddr,ioe);
                throw ioe;
            }

            if (serverListMgr.getIterator().hasNext()) {
                currentServerAddr = serverListMgr.getIterator().next();
            } else {
                maxRetry --;
                if (maxRetry < 0) {
                    throw new ConnectException("[NACOS HTTP-POST] The maximum number of tolerable server reconnection errors has been reached");
                }
                serverListMgr.refreshCurrentServerAddr();
            }

        } while (System.currentTimeMillis() <= endTime);

        LOGGER.error("no available server,currentServerAddr : {}",currentServerAddr);
        throw new ConnectException("no available server,currentServerAddr : " + currentServerAddr);
    }

    //......
}
複製程式碼
  • ServerHttpAgent實現了HttpAgent介面,其httpGet、httpPost、httpDelete方法的結構大體相同,都是以do while做迴圈,迴圈條件為距離開始執行時間不超過readTimeoutMs
  • 迴圈開始之前會通過serverListMgr.getCurrentServerAddr()方法獲取currentServerAddr,迴圈體內則通過HttpSimpleClient的相應方法執行請求,如果返回的HTTP Code為HTTP_INTERNAL_ERROR、HTTP_BAD_GATEWAY、HTTP_UNAVAILABLE則列印error日誌,否則執行serverListMgr.updateCurrentServerAddr(currentServerAddr),然後返回
  • 如果出現異常或者沒有提前返回,則判斷serverListMgr.getIterator().hasNext(),如果為true則使用serverListMgr.getIterator().next()更新currentServerAddr,為false則遞減maxRetry,然後執行serverListMgr.refreshCurrentServerAddr()

小結

ServerHttpAgent實現了HttpAgent介面,其httpGet、httpPost、httpDelete方法的結構大體相同,都是以do while做迴圈,迴圈條件為距離開始執行時間不超過readTimeoutMs

doc