1. 程式人生 > >Okhttp攔截器實現軟負載

Okhttp攔截器實現軟負載

開發十年,就只剩下這套架構體系了! >>>   

問題

Okhttp Client需要在不同的伺服器ip之間訪問介面。

思路

在攔截器中,發現介面服務不可用的情況下面,替換備用的ip服務地址,再次訪問後臺介面。

Interceptor

package com.zyl.interceptor;

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.IOException;
import java.util.List;

public class RetryAndChangeIpInterceptor implements Interceptor {
    protected static final Log logger = LogFactory.getLog(RetryAndChangeIpInterceptor.class);
    private int RetryCount;
    private String FirstIP;
    private List<String> SERVERS;

    public RetryAndChangeIpInterceptor(String firsrIP, List<String> sERVERS, int tryCount) {
        FirstIP = firsrIP;
        SERVERS = sERVERS;
        RetryCount = tryCount;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        // try the request
        IOException exception = null;
        Response response = null;
        try {
            response = doRequest(chain, request);
        } catch (IOException e) {
            exception = e;
        }
        int tryCount = 0;
        String url = request.url().toString();
        while ((response == null || !response.isSuccessful()) && tryCount <= RetryCount) {
            url = switchServer(url);
            Request newRequest = request.newBuilder().url(url).build();
            logger.debug("intercept : Request is not successful - " + tryCount);
            tryCount++;
            // retry the request
            try {
                response = doRequest(chain, newRequest);
            } catch (IOException e) {
                exception = e;
            }
        }
        if (response == null || !response.isSuccessful()) {
            if (exception != null) {
                throw exception;
            } else if (response != null) {
                throw new IOException(String.format("介面響應程式碼:%s", response.code()));
            } else {
                throw new IOException();
            }
        }
        return response;
    }

    private Response doRequest(Chain chain, Request request) throws IOException {
        return chain.proceed(request);
    }

    private String switchServer(String url) {
        String newUrlString = url;
        if (url.contains(FirstIP)) {
            for (String server : SERVERS) {
                if (!FirstIP.equals(server)) {
                    newUrlString = url.replace(FirstIP, server);
                    break;
                }
            }
        } else {
            for (String server : SERVERS) {
                if (url.contains(server)) {
                    newUrlString = url.replace(server, FirstIP);
                    break;
                }
            }
        }
        return newUrlString;
    }
}

OkHttp3

List<String> serverList = new ArrayList<>();
serverList.add("10.158.17.61");
OkHttpClient okhttpClient = new OkHttpClient.Builder()
        .addInterceptor(new RetryAndChangeIpInterceptor("10.158.17.60", serverList, 1))//新增失敗重試及重定向攔截器
        .retryOnConnectionFailure(true)//允許失敗重試
        .connectTimeout(10, TimeUnit.SECONDS)
        .readTimeout(10, TimeUnit.SECONDS)
        .build();

String url = "http://10.158.17.60:80/hello";
Request requestOk = new Request.Builder()
        .url(url)
        .get()
        .build();
responseOk = okhttpClient.newCall(requestOk).execute();

總結

okhttp的攔截器機制靈活,okhttp本身也支援多ip,翻了半天只看關於okhttp路由的文件資料,沒有找到具體的使用。

參考