Проблема производительности Java ssl в связи с загрузками
В настоящее время я работаю над небольшим быстрым клиентом и получил некоторые проблемы с производительностью при загрузке файлов.
После тысячи проверок я локализовал проблему, загрузив файлы через ssl.
Обычные загрузки (http) работают без проблем (или проблем с производительностью). Но загрузка SSL взрывает мой процессор... одно ядро загружается до 100 % (для одного потока)
Я написал небольшой тестовый класс без всей моей программы и могу подтвердить свои предыдущие наблюдения.
package testDownload;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class Downloader {
public Downloader(boolean sslTrigger) throws IOException {
try {
this.allowSelfSignCerts();
} catch (KeyManagementException | NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
URL url;
// Http Download
if (sslTrigger) {
System.out.println("HTTPS-Mode");
url = new URL("HTTPS LINK");
} else {
System.out.println("HTTP-Mode");
url = new URL("HTTP LINK");
}
URLConnection conn = url.openConnection();
InputStream input = conn.getInputStream();
OutputStream output = new FileOutputStream(new File(System.getProperty("user.home")+System.getProperty("file.separator")+"test.dat"));
ReadableByteChannel inputChannel = Channels.newChannel(input);
WritableByteChannel outputChannel = Channels.newChannel(output);
System.out.println("start download");
this.fastChannelCopy(inputChannel, outputChannel);
inputChannel.close();
outputChannel.close();
System.out.println("finish");
}
private void fastChannelCopy(ReadableByteChannel src, WritableByteChannel dest) throws IOException {
ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
while (src.read(buffer) != -1) {
buffer.flip();
dest.write(buffer);
buffer.compact();
}
buffer.flip();
while (buffer.hasRemaining()) {
dest.write(buffer);
}
}
private void allowSelfSignCerts() throws NoSuchAlgorithmException, KeyManagementException {
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}
}
используемая java-версия
java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
У кого-нибудь есть идея для решения этой проблемы?
1 ответ
Обычные загрузки (http) работают без проблем (или проблем с производительностью). Но загрузка SSL взрывает мой процессор... одно ядро загружается до 100 % (для одного потока)
Это может зависеть от согласованного клиента и сервера шифрования. Очень распространены шифры AES. Но в то время как AES работает быстро со специальным оборудованием, он ужасно медленен и связан с процессором, когда выполняется программно. Исторически аппаратное ускорение не было доступно для Java. Но похоже, что они добавили его в Java 8, хотя только для серверной JVM.
Для получения дополнительной информации см. Ускорение AES для встроенных функций Java и AES-NI по умолчанию?,