# Http/Https Geschwindigkeit



## jb007 (29. Nov 2007)

Hallo,

ich habe mal eine Frage zur Performance von Http/Https Verbindungen.

In unserer Applikation gibt es zeitlich gesehen große Unterschiede zwischen beiden Protokollen.

Ein Http Request ist in der Regel zehnmal so schnell wie ein Https Request.

Wenn wir lokal in unserem Firmen Netzwerk arbeiten ist das nicht soooo schlimm, aber sobald wir von Extern arbeiten dauert ein Request statt 1 Sekunde ca. 5 Sekunden.

Rufe ich eine URL über den Browser auf (intern oder extern), dann geht das fast viermal so schnell als über unsere Applikation. Ein Unterschied zwischen Http/Https ist dabei kaum zu bemerken.

Ich frage mich jetzt ob das normal ist oder eventuell ein Fehler in unserer Serverkommunikation liegt

Hier mal unser Client:


```
private static URLConnection buildHttpsConnection()
    {
        HttpsURLConnection connection = null;
        
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager()
            {
                public java.security.cert.X509Certificate[] getAcceptedIssuers()
                {
                    return null;
                }

                public void checkClientTrusted(
                    java.security.cert.X509Certificate[] certs, String authType)
                {
                }

                public void checkServerTrusted(
                    java.security.cert.X509Certificate[] certs, String authType)
                {
                }
            }
        };
        
        SSLContext sc = null;

        // Install the all-trusting trust manager
        try
        {
            sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            SSLContext.setDefault(sc);
            
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        }
        catch (Exception e)
        {
            System.out.println("### exception when disabling trust authentication ###");
            e.printStackTrace();
        }
        
        try
        {
            URL url;

            //SSLSocketFactory ssf = sc.getSocketFactory();
            //HttpsURLConnection.setDefaultSSLSocketFactory(ssf);

            HostnameVerifier hv = new HostnameVerifier()
            {
                public boolean verify(String urlHostName, SSLSession session)
                {
                    System.out.println("### Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
                    return true;
                }
            };

            HttpsURLConnection.setDefaultHostnameVerifier(hv);

            url = new URL(getServerUrl());

            // URL connection channel.
            connection = (HttpsURLConnection) url.openConnection();
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            return null;
        }

        return connection;
    }



    public static URLConnection buildHttpConnection()
    {
        URLConnection connection = null;

        URL url;

        try
        {
            url = new URL(getServerUrl());
            connection = url.openConnection();
        }
        catch (MalformedURLException ex)
        {
            ex.printStackTrace();
        }
        catch (IOException ex)
        {
            ex.printStackTrace();
        }

        return connection;
    }



    public static String requestServer()
    {
        String responseString = "";

        URLConnection connection = null;

        //build a connection handler depending on url
        if (getServerUrl().startsWith("https"))
        {
            connection = buildHttpsConnection();
        }
        else
        {
            connection = buildHttpConnection();
        }

        if (connection == null)
        {
            System.out.println("# Connection is null");
            return responseString;
        }

        //
        try
        {
            URL url = new URL(getServerUrl());

            //URLConnection       urlConn;
            DataOutputStream printout;
            DataInputStream input;

            // Let the run-time system (RTS) know that we want input.
            connection.setDoInput(true);
            // Let the RTS know that we want to do output.
            connection.setDoOutput(true);
            // No caching, we want the real thing.
            connection.setUseCaches(false);
            // Specify the content type.
            connection.setRequestProperty("Content-Type", getContentType());
            connection.setRequestProperty("Connection", "close");

            if("true".equals(getAcceptEncoding()))
            {
                System.out.println("# Set encoding");
                connection.setRequestProperty("Accept-Encoding", "gzip, deflate");
            }
            
            if (url.getUserInfo() != null)
            {
                String hostName = url.getHost();

                String authUser = url.getUserInfo().substring(0, url.getUserInfo().lastIndexOf(":"));
                String authPass = url.getUserInfo().substring(url.getUserInfo().lastIndexOf(":") + 1);

                //encode base 64
                String userAuth = authUser + ":" + authPass;
                connection.setRequestProperty("Authorization", "Basic " + Base64.encode(userAuth));
            }

            try
            {
                // Send POST output.
                printout = new DataOutputStream(connection.getOutputStream());

                printout.writeBytes(getRequestString());
                printout.flush();
                printout.close();
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
                return "";
            }

            //obtain the encoding returned by the server
            String encoding = connection.getContentEncoding();

            InputStream inputStream = null;

            //check encoding
            if (encoding != null && encoding.equalsIgnoreCase("gzip"))
            {
                inputStream = new GZIPInputStream(connection.getInputStream());
            }
            else if (encoding != null && encoding.equalsIgnoreCase("deflate"))
            {
                inputStream = new InflaterInputStream(connection.getInputStream(), new Inflater(true));
            }
            else
            {
                inputStream = connection.getInputStream();
            }

            input = new DataInputStream(inputStream);

            String str;

            BufferedReader inputReader = new BufferedReader(new InputStreamReader(input));

            StringBuffer buffer = new StringBuffer();

            while (null != ((str = inputReader.readLine())))
            {
                buffer.append(str);
            }

            input.close();

            return buffer.toString();
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return "";
        }
    }
```

Fällt hier vielleicht Jemandem etwas auf was die Performance beinflußt ?

Vielen Dank schon einmal für eure Antworten.

Gruß Jens


----------



## hupfdule (29. Nov 2007)

HTTPS ist immer deutlich langsamer, da ja eben noch die Verschlüsselung stattfindet. Eure Erkenntnis von wegen 10fache Geschwindigkeit bei HTTP entspricht auch der Theorie. 
Dass ihr im lokalen Netz keine Unterschiede merkt, wundert mich etwas. Könnte daran liegen, dass euer Netz so schnell ist, dass auf die Verzögerung bei HTTPS nicht mehr ankommt.
Allerdings muss ja weiterhin die Verschlüsselung stattfinden und die ist nicht abhängig von der Netzgeschwindigkeit (außer dass da ein paar Pakete mehr hin und her geschickt werden).


----------



## AlArenal (29. Nov 2007)

Neben dem Mehraufwand für die Verschlüsselung ist ja auch der Handshake komplexer und da addieren sich dann eben die Latenzzeiten, die in einem LAN in der Regel deutlich geringer sind, als über Dial-Up/DSL und durch eine Firewall (die ihr hoffentlich habt und die hoffentlich auch zwischen LAN und Server hängt  ).

Was genau heißt denn bei euch "von extern arbeiten"? VPN?


----------



## jb007 (29. Nov 2007)

Hallo,

vielen Dank für die bisherigen Antworten.

@hupfdule
Wieso entspricht der Geschwindigkeitsverlust einer Theorie ?
Gibt es dazu vielleicht irgendwo einen Artikel der das genauer beschreibt ?

Im lokalen Netzwerk sind die Unterschiede zwar auch vorhanden (ist vielleicht falsch rübergekommen)
nur weniger spürbar (man kann noch vernünftig mit der Applikation arbeiten).

Von Extern ist alles nochmals um das 5 fache langsamer und ein Arbeiten kaum möglich....

@AlArenal

Von Extern zu arbeiten bedeutet natürlich über DSL. Eine Firewall haben wir natürlich auch. VPN nutzen wir nicht.

Das die Verschlüsselung Zeit kostet leuchtet ja ein, aber warum kann Firefox das so schnell ?
Warum ist das in Java so langsam ?


Hat sonst noch Jemand einen interessanten Link zu diesem Thema ???

Gruß Jens


----------



## AlArenal (29. Nov 2007)

Nun könnte man sagen, der Firefox ist schneller, weil er nicht in Java  programmiert ist. Das ist natürlich bestenfalls die halbe Wahrheit.

Hast du denn mal nen Profiler angeworfen oder wenigstens Poor-Mans-Profiling-Code eingebaut, um zu schauen an welcher Stelle eure Anwendung die Zeit lässt? Das, zusammen mit einem Mitlauschen des Datenverkehrs (z.B. mit Plugproxy) und Abgleich zwischen intern-intern und extern-intern sollte zunächst mal wertvolle Hinweise auf den Bottleneck liefern.

Ansonsten lässt sich sich von außen gesehen natürlich wunderherrlich orakeln, was da wohl in der Blackbox abgeht.


----------



## jb007 (29. Nov 2007)

@AlArenal

Die Frage die wir uns im Moment stellen, geht hier überhaupt Zeit verloren ???

Was ist normal und was nicht ??

Einen Profiler wollte ich schon einsetzen (Habs mit Netbeans aber noch nicht hinbekommen).

Hier mal die Zeiten in Millisekunden die ich auf meinem System erreiche.
Dabei rufe ich ein PHP Script im lokalen Netzwerk auf, dass nur ein Hallo printed/zurückgibt:

HTTP:
# Beginne Daten zum Server zu senden : 0
# Daten wurden zum Server gesendet : 15
# Server sendet Antwort: 31
# Antwort erhalten: 31
# Response: Hallo

oder

# Beginne Daten zum Server zu senden : 0
# Daten wurden zum Server gesendet : 16
# Server sendet Antwort: 16
# Antwort erhalten: 16
# Response: Hallo

Per HTTPS:

# Beginne Daten zum Server zu senden : 125
# Daten wurden zum Server gesendet : 562
# Server sendet Antwort: 578
# Antwort erhalten: 578
# Response: Hallo

Ich würde sagen, dass die Unterschiede (31 msec bei http und 578 msec bei https) beachtlich sind.

Firefox benötigt bei beiden Protokollen 0,15 Sekunden......!

Könnte Jemand mal zum Vergleich die Zeiten bei sich messen ?

Vielleicht ist der Unterschied zw. http und https ja generell so groß !!!

Gruß Jens


----------



## AlArenal (29. Nov 2007)

Und hast du nun den Traffic abgehorcht, um abzuchecken, ob FF und eure Applikation großartig unterschiedliche Handshakes haben?


----------



## hupfdule (29. Nov 2007)

jb007 hat gesagt.:
			
		

> Wieso entspricht der Geschwindigkeitsverlust einer Theorie ?
> Gibt es dazu vielleicht irgendwo einen Artikel der das genauer beschreibt ?



Ähm, sicherlich. Ich hab nur grad keinen zur Hand. Mit "Theorie" meinte ich, dass das so der Richtwert ist, von dem man ausgehen kann. Ich hatte ihn halt noch im Hinterkopf. Wenn du ein bisschen googelst, wirst du aber sicher auch Artikel finden, die das exakter belegen.


----------



## tuxedo (20. Dez 2007)

Naja, hast du mal probiert Megabyteweise Daten hin und her zu schieben?

Mein jPMdbc DB Treiber kann sowohl HTTP als auch HTTPS. Und bei großen Abfragen welche schonmal um die 10MB betragen hab ich keinen spürbaren Unterschied beim Transfer bemerkt. Gemessen hab ich's nicht. Aber ob ich jetzt 30,031 Sekunden, oder 30,578 Sekunden brauche ist mir hier auch egal. 
Für lauter kleine und schnell aufeinander folgende Abfragen ist das natürlich nicht so der bringer. 

Performance ist also "relativ" zu dem was du mit dem Einsatz von HTTP/HTTPS in einem bestimmten Umfeld bezwecken willst.

Ich kann jedenfalls nicht sagen dass HTTPS einen merklichen Performanceeinbruch gegenüber HTTP hat (bezogen auf meinen Anwendungsfall).

- Alex


----------



## byte (20. Dez 2007)

alex0801 hat gesagt.:
			
		

> Mein jPMdbc DB Treiber kann sowohl HTTP als auch HTTPS. Und bei großen Abfragen welche schonmal um die 10MB betragen hab ich keinen spürbaren Unterschied beim Transfer bemerkt. Gemessen hab ich's nicht. Aber ob ich jetzt 30,031 Sekunden, oder 30,578 Sekunden brauche ist mir hier auch egal.


Sicher dass dabei auch verschlüsselt wird und nicht nur Authentifizierung stattfindet?


----------



## Wildcard (20. Dez 2007)

Bei HTTPS werden auch nicht mehr Daten übertragen als bei HTTP (mit Ausnahme des Handshakes). Solange der Rechner also schneller verschlüsseln als senden kann, dürfte bei größeren Dateien kein großer Unterschied bestehen.


----------



## pyjo (3. Jan 2008)

Hi, das Thema ist zwar schon ein bischen älter, aber ich hätte da noch eine Idee für dich.

Und zwar hatte ich ähnliche Probleme, bei einem Tool, dass etwa im 0,1 bis 0,3 Sekunden Takt Anfragen an den Server stellen musste. Da hatte ich extreme Probleme gehabt, mit den ganzen Auf und Abbau der Verbindung, darunter auch SSL also HTTPS Verbindungen.

Ich bin dann her gegangen und habe angefangen mit persistenten Verbindungen zu arbeiten und habe die Verbindung nur neu aufgebaut, wenn der Server sie getrennt hat 

Firefox arbeitet übrigens sehr ähnlich, daher denke ich, könnte der Geschwindigkeitsboost vom FF hier zu finden sein.

Falls du also viele Verbindungen/Anfragen an den Server hast, versuche diese über eine persistente Verbindung laufen zu lassen. Stichwort: HTTP/1.1 !!


Die Verschlüsselten Verbindungen haben übrigens kein erhöhtes Datenaufkommen auf dem Netz, die einzigen Bremsen sind die Rechner, welche ver- und entschlüsseln müssen! Das ist übrigens bei so gut wie allen Verschlüsselungsmethoden / -theorien so.


mfg pyjo


----------



## AlArenal (3. Jan 2008)

Wohl eher Stichwort "keepalive"...


----------



## Guest (4. Jan 2008)

AlArenal hat gesagt.:
			
		

> Wohl eher Stichwort "keepalive"...


Ist die URL Connection dazu in der Lage? Ich hatte mir damals das HTTP Protokoll selbst programmieren müssen, da ich vor allem auch auf die HTTP Header achten musste. Da brauchte ich aber auch kein SSL


----------



## pyjo (4. Jan 2008)

sry, da war ich mal wieder nicht eingelogt ^^ der letzte Beitrag war von mir...  :roll:


----------

