HTTP-запрос нормальный, но изменение https-запроса происходит часто SocketTimeoutException

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

первый шаг: инициализация 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 введите здесь описание изображения

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


person 肖竞航    schedule 26.06.2018    source источник


Ответы (1)


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

person 肖竞航    schedule 02.07.2018