HTTP-запрос нормальный, но изменение https-запроса происходит часто SocketTimeoutException - PullRequest
0 голосов
/ 26 июня 2018

Недавно я пытался изменить http на https, но результат не был столь радостным из-за частых тайм-аутов запросов после перехода на https, что вызвало у меня очень плохой пользовательский опыт; Мое текущее решение - использовать пул потоков для выполнения запросов синхронизации okhttp, что является нормальным для запросов http. Я хочу решение, спасибо!

первый шаг: init okhttpclient

 public static class MyHttpUtils{
    private static  MyHttpUtils myHttpUtils;

    private OkHttpClient okHttpClient;

    private MyHttpUtils(){
        initClient();
    }

    private void initClient() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.writeTimeout(60_000, TimeUnit.MILLISECONDS);
        builder.connectTimeout(60_000,TimeUnit.MILLISECONDS);
        builder.readTimeout(60_000,TimeUnit.MILLISECONDS);
        HttpsUtils httpsUtils = HttpsUtils.getInstance();

        HttpsUtils.SSLParams sslParams = httpsUtils.getSslSocketFactory();
        builder.sslSocketFactory(sslParams.sSLSocketFactory,sslParams.trustManager)
                .hostnameVerifier(httpsUtils.hostnameVerifier());//check hostname
        okHttpClient = builder.build();
    }


    public static MyHttpUtils getInstance(){
        if(myHttpUtils == null){
            synchronized (MyHttpUtils.class){
                if(myHttpUtils == null){
                    myHttpUtils = new MyHttpUtils();
                }
            }
        }
        return  myHttpUtils;
    }

    public OkHttpClient getOkHttpClient() {
        return okHttpClient;
    }
}

Второй шаг: создание пула потоков

public static class  ThreadPool{
    private static  ThreadPool threadPool = new ThreadPool();

    private ExecutorService service = new ThreadPoolExecutor(0 /* corePoolSize */,
            Integer.MAX_VALUE /* maximumPoolSize */, 60L /* keepAliveTime */, TimeUnit.SECONDS,
            new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp ConnectionPool", true));

    public static ThreadPool getInstance(){
        return threadPool;
    }

    public void  execute(Runnable runnable){
        service.execute(runnable);
    }
}

Третий шаг: создать Runnable

private Runnable  createRunnable(){
   return new Runnable() {
       @Override
       public void run() {

           try {
               okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder();
               requestBuilder.url(url).tag(this).build();
               okhttp3.Request request = requestBuilder.build();
               okhttp3.Response response = client.newCall(request).execute();
               if(response.code() == 200){
                  synchronized (this){
                      successSum++;
                  }
                   Log.e(MainActivity.class.getSimpleName(),"success="+successSum);
                   Log.e("myResult","result="+response.body().string());
               }else{
                  synchronized (this){
                      failSum++;
                  }
                   Log.e(MainActivity.class.getSimpleName(),"failSum="+failSum+"==code="+response.code());
               }
           } catch (IOException e) {
               client.connectionPool().evictAll();
              synchronized (this){
                  exceptionSum++;
              }
               Log.e(MainActivity.class.getSimpleName(),"exceptionSum="+exceptionSum+"==msg="+ e.toString());
           }
       }
   };
}

четвертый шаг: отправить запрос

@Override
public void onClick(View view) {
    switch (view.getId()){
        case R.id.btn_request:
            successSum = 0;
            failSum = 0;
            exceptionSum = 0;
            int i = 10;
            while (i>0){
                requestSync();
                i--;
            }

            break;
    }
}

Метод: requestSync ()

private void requestSync(){
    ThreadPool.getInstance().execute(createRunnable());
}

окончательный результат: происходит SocketTimeoutException enter image description here

Я использовал образцы данных при тестировании, и процент успешных запросов составил около 60%; этот результат делает мое приложение очень недружелюбным, но я не уверен, почему это так, я надеюсь получить решение, спасибо

1 Ответ

0 голосов
/ 02 июля 2018

Эта проблема была решена. Поскольку используется запрос синхронного режима, ssl будет блокировать подключение других потоков к хосту при возникновении рукопожатия. Решение состоит в том, чтобы напрямую изменить синхронный режим на асинхронный режим.

...