29. Juni 2008

Trennung von Memcache und Web Server

Memcache (memcached) nimmt meiner Datenbank fantastisch viel Arbeit ab. Alle Objekte sind im Memcache, kein Code greift direkt auf die Datenbank zu. Die Datenbank wird dadurch um eine Größenordung entlastet. Was die Datenbank leisten müsste sieht man dann, wenn der Cache leer ist. Dann geht alles direkt auf die DB bis der Cache wieder gefüllt (warm) ist.

Der Memcache ist ein verteilter Speicher. Er ist verteilt über mehrere Rechner. Will man keine Rechner extra für den Memcache abstellen, dann verwendet man traditionell die Webserver auch als Memcache-Server. Das heißt nicht, dass es schneller wird, weil die meisten Zugriffe nicht lokal sind, aber billiger weil man keine extra Rechner braucht. Die Webserver hat man ja sowieso. Die Standardvorgehensweise ist also: 10 Webserver hinter einem Loadbalancer. Auf jedem Webserver ein memcached. Das wird deshalb empfohlen, weil Webserver vor allem CPU brauchen (CPU bound) und der Memcache vor allem Speicher (memory bound). Man kann also die jeweils "andere" Ressource auch noch nutzen.

Soweit die Standardvorgehensweise. Tatsache ist aber, dass bei PHP/Apache basierten Webservern (LAMP!) Webserver meistens auch memory bound sind. Apache und PHP werden nämlich normalerweise im Prefork-Modus verwendet. Also viele Apache Prozesse, jeder mit einer eigenen PHP-Runtime. Bei einer großen Applikation braucht ein so ein Apache/PHP Prozess schnell mal 16 MB Speicher. Der geteilte Speicher der verwendeten DLLs fällt kaum ins Gewicht. Das sind fast alles Daten. Ein Standardserver vom letzen Jahr hat 2 GB Speicher, 2 Cores. Will man 100 Apache Prozesse laufen lassen, bekommt man 16 MB x 100 = 1,6 GB. Da bleibt nicht mehr viel für den Memcache, der auch sein 1 GB pro Rechner haben sollte. Schließlich sind ja 1 Mio. User und zig Millionen Objekte im Cache. Dieses Jahr sind es 4 GB und 4 Cores, aber man erwartet auch 200 Prozesse pro Rechner, also auch nicht besser. Apache und Memcache konkurrieren um den Speicher.

Und es wird noch schlimmer. Apache und Memcache haben in der Standardkonfiguration unterschiedliche Verfügbarkeitsanforderungen. Webserver hinter dem Loadbalancer können ab und zu mal ausfallen. Der Loadbalancer merkt das schnell und nimmt sie aus dem Lastverteilungsverbund. Alle Daten, alle Sessions sind im Memcache und damit stets transferierbar. Aber: vom Memcache-Verbund darf kein einziger Rechner ausfallen. Selbst wenn man das schnell merkt und ihn aus dem Verbund nimmt, bedeutet der Ausfall eines einzigen Memcache-Servers einen 50% Cache-Flush. Memcache-Clients berechnen aus dem Key und den verfügbaren Memcache-Servern auf welchem Server die gefragten Daten liegen und holen sie direkt dort. Fällt ein Server aus, dann ändert sich die Zuordnung der Keys zu den Memcache-Servern. Die Daten bleiben dort gespeichert, aber die Clients finden sie nicht mehr und nehmen an, dass sie nicht da sind. Es gibt alternative Zuordnungsalgorithmen, die verhindern, dass sich alle Keys umsortieren. Das ist bitter nötig in großen Memcache-Clustern (Facebook: man spricht von 800 Rechnern mit viel Speicher). Denn dann fällt immer einer aus oder es kommt einer dazu.

Aber trotzdem reicht das nicht, denn Webserver sind manchmal überlastet und fallen für den Loadbalancer effektiv aus. Wenn auf dem gleichen Rechner ein memcached läuft und der auch nicht mehr antworten kann, dann fällt ein Teil (20% oder 10%) des Caches aus. Das treibt die Datenbank sofort zu Höchstleistungen und propagiert das Überlastproblem vom Frontend-Rechner zur DB. Das kann schnell die Performance des Gesamtsystems zerstören. Denn braucht die DB 1 h bei leerem Cache um den Cache zu füllen, dann führt der Ausfall von 1 aus 5 Memcaches immerhin zu 1h / 5 = 12 Minuten Überlast auf der DB. Das hört sich nicht gut an, denn eigentlich ist es das Ziel überhaupt keine Spannungssituationen zu erzeugen bloß weil ein Webserver ausfällt.

Webserver arbeiten viel mit der Festplatte. Das ist im high-performance Bereich auch zu vermeiden, aber ist trotzdem Standard im Medium-Segment. Geht die Festplatte kaputt steht der Webserver. Memcache arbeitet nur mit Speicher, überhaupt nicht auf der Platte. Steht die Platte kann er weiterarbeiten. Es ist unsinnig den Memcache von der Festplatte des Webservers abhängen zu lassen. Eigentlich sollte der Memcache-Server vom Netz booten und ohne Platte arbeiten. Ein Teil weniger was kaputt gehen kann, und zwar das häufigste.

Webserver und Memcache haben sehr unterschiedliche Profile und sollten deshalb nicht die Rechner teilen. Webserver (sollen nicht, aber) dürfen ausfallen, deshalb Software RAID-1. Memcaches (tun es, aber) dürfen nicht ausfallen, deshalb entweder RAID-Controller, damit die Platte im Betrieb getauscht werden kann oder gar keine Platte. Webserver so bemessen, damit sie CPU und Speicher Last tragen können. Separate Memcache-Server bemessen, so dass alle zusammen alle Daten der Applikation speichern können, die innerhalb der TTL der Cache-Items anfallen.

happy_coding()

27. Juni 2008

Danke Adobe für TCP Port 843

Vor ein paar Tagen den ersten erntzunehmenden Konkurrenten von weblin entdeckt: ROCKETON. Der ROCKETON ist im in Flash 9 programmiert und ROCKETON schreibt, dass man Port 843 outgoing öffnen muss.

Von der Hilfeseite: "Since our application uses Adobe Flash, we must abide by their security policy. In order for Adobe Flash to work in a multiuser environment, you must have port 843 open. Please ask your system administrator to make sure port 843 is not being blocked."

Auf Port 843 liegt ein Policyfile für Flash. Die Datei muss jeder anbieten, der mit Flash 9 Socketverbindungen zu anderen Hosts benutzen will. Das Policyfile muss auf dem Server liegen zu dem verbunden werden soll und zwar auf Port 843. Nu ist mir nicht ganz klar warum ROCKETON Socketverbindungen benutzt, da ROCKETON eigentlich HTTP-long-polling verwendet, aber sie werden es schon wissen.

Was mich aber wieder einmal gewundert hat ist der Port 843, den Adobe für Flash 9 erfunden hat. Klar, mit Socketverbindungen kann man allerhand Unfug treiben. Java benutzt ja auch das für Security eigentlich ungeeignete DNS, um Applets nicht auf beliebige Adressen verbinden zu lassen. Dass das nur ehrliche und hart arbeitende Normalbürger behindert, aber nicht echte Schlimmfinger ist inzwischen bekannt (Stichwort: DNS Rebinding Attacks). Flash dagegen läßt sogar Verbindungen zu anderen Rechnern zu, aber nur wenn dort das Policyfile verfügbar ist. Leider liegt das Policyfile nicht auf den üblichen Ports 80 oder 443. Diese Ports sind meistens offen, haben schon einen Webserver und man müsste nur eine Datei hinlegen. Nein, man muss extra ein Programm laufen lassen auf Port 843, das die Datei hergibt. Und noch schlimmer: der Port ist in Firmen-Intranets meistens nicht offen. Das heißt, Software in Flash 9, die im Labor und bei normalen Benutzern geht, versagt typischerweise im Büro von Kooperationspartnern und Journalisten. D.h. immer wenn man im Business-Development jemand eine Vorführung machen will geht es nicht. Zuhause aber schon. Danke Adobe.

Warum ist das so. Warum nicht Port 80? Vermutlich ist es Adobes Absicht, dass Socketconnections im Firmenumfeld nicht gehen, damit Attacken, wie DNS Rebindung und Portscanning nicht funktionieren. Nette Idee, um private Rechner von Firmenrechnern zu unterscheiden, aber irgendwie auch ganz schön doof und vor allem ziemlich nervend, wenn man mit Flash tolle Sachen machen will. Ja, sie können es machen. Flash gehört ihnen und wir müssen es ja auch nicht benutzen. Aber irgendwie habe ich das Gefühl, dass es bessere Schutzmechanismen geben muss, als DNS, Stringvergleiche und gesperrte Ports.

24. Mai 2008

Weblin Whiteboard oder: User finden alles

Jemand hat das Whiteboard in weblin entdeckt und User erschreckt. Das Whiteboard kann einfache Grafiken auf Webseiten produzieren, die dann alle im Raum sehen. Kommt man zu spät in den Raum, sieht man es nicht, weil es nur wie Chat als Message vorbeisaust. Wenn es keinen Protokollbot gibt, der die Messages speichert und wieder abspielt, sind die Whiteboard-Messages transient (flüchtig). Die Grafik liegt über allen anderen Fenstern, so dass man den Eindruck bekommt, dass sie auf allen Seiten ist. Ist sie aber nicht, sondern nur in dem Raum wo sie gemacht wurde. Übrigens wenn es nervt: Rechtsklick auf den Rand, oben steht wer es gemacht hat und unten steht "Löschen".

Der Whiteboard Code ist in weblin noch drin und eigentlich nicht erreichbar. Aber natürlich zu Debugzwecken dann doch. Das zeigt wieder mal, dass User alles finden. Security by Obscurity hat keine Chance.

Es gibt einfach so wahnsinnig viele User, die sich so engagiert mit dem Thema befassen. Die kennen das System oft besser als Entwickler. Entwickler benutzen das System weniger, als User. Natürlich kennen Entwickler den Teil den sie gemacht haben sehr gut, aber Entwickler sind trotzdem meistens keine Poweruser. Entwickler kennen die Theorie, User die Praxis. Entwickler programmieren einzelne Features und bedenken dabei manchmal auch Zusammenhänge. Aber User erkennen Muster im Verhalten von Software, die die Entwickler nicht explizit programmiert haben. Vielmehr sind entstehen Wechselwirkungen mehrerer Features, die sich durch sehr intensive Beschäftigung zu einem Muster verbinden.

Das gilt genauso für Games, wo diese Bedienungsmuster im High-End Bereich ein wichtiger Teil des Gameplays werden. Das gilt auch für alle anderen Programme, wie in diesem Fall weblin, mit denen sich User intensiv und lange beschäftigen. Manche Leute lernen das Programm einfach durch intensive Benutzung seiner Features, andere durch Analyse von Code, Protokoll und Reaktionen.

Weiter so Leute, zeigt den Entwicklern was "Wisdom of the Crowds" heisst.

RSS-Feeds: eine Fehlentwicklung - warum XMPP besser gewesen wäre

Ich bin ja wirklich ein Fan von RSS-Feed-Readern. Inzwischen besuche ich gar keine Blogs mehr, sondern lese nur noch die Feeds im Reader. Echt toll, dass die Nachrichten zu mir kommen, statt dass ich alle Websites abklappern muss.

Schade nur...

...dass die Nachrichten gar nicht zu mir kommen, sondern dass meine Software sie abholen muss. Ich muss zwar nicht alle Websites abklappern, aber mein RSS-Client schon. Der schaut ständig nach ob es was neues gibt (polling). Dabei sollt er eigentlich benachrichtigt werden. Der Begriff RSS-Feed ist glatt gelogen. RSS-Feeds sollten RSS-Fetch heißen. Nochmal: Die Nachrichtenquelle sollte eine Nachricht an meinen Reader schicken, statt dass mein Reader alle 10 Minuten nachschaut ob etwas neues da ist. Traffoc-mässig echt eine Schweinerei und nur im Zeitalter von Torrent und Videodownloads gerade noch tragbar.

Diese Fehlentwicklung liegt natürlich daran, dass der ganze RSS-Mechanismus auf Web-Technologien aufbaut, die wegen HTTP per se nur Request-Response können. Dabei gibt es etablierte Technologien mit denen man einen echten News-Feed aufbauen könnte, z.B. XMPP/Jabber.

Was besser gewesen wäre

Bei XMPP ist mein Client ständig mit meinem Server verbunden. Andere Server können jederzeit zu meinem Server Kontakt aufnehmen und dieser schickt dann alles an mich weiter. Wenn ich einen News-Feed haben will, dann registriere ich mich mit meiner Adresse bei der Nachrichtenquelle. Die Nachrichtenquelle schickt mir dann immer eine Mitteilung, dass etwas neues da ist (mit Titel und Zusammenfassung). Mein Reader zeigt es mir sofort (!) an und ich kann die Nachricht lesen. Kein "Pollen", keine Verzögerung, kein unnötiger Traffic.

Jetzt mal ehrlich...

...RSS ist Really Stupid Syndication. Diese Art von News-Pollen gehört in den Mülleimer der Geschichte. Die Zeit ist reif für ein Message-basiertes News-System. Die Technik ist verfügbar: XMPP und andere IM.

Aber inzwischen gibt es so viel Content der die schlechte alte Technik benutzt, dass wir noch lange damit leben werden müssen. Und mit Web-basierten RSS-Readern entspannt sich auch die Lage beim Traffic, weil ein Betreiber (z.B. Google) die Feeds für alle gemeinsam abfragt. Und wenn es komplizierter gewesen wäre, dann hätte es sich vielleicht nicht so durchgesetzt und es wäre weniger Content verfügbar.

Lesen Sie auch bald wieder hier: "Web und Request-Response: eine Fehlentwicklung - warum ein Mesh und Messaging besser gewesen wäre".

23. Mai 2008

Simple Remote Procedure Call - Response Format

SRPC-Response Format is an extension to SRPC. It specifies a request parameter which selects a response format.
This is primarily intended for the REST variant of SRPC where the SRPC parameters are in the request URI and the result is the response body. Usually, the response body carries a data structure. But it is not clear in which format the data is encoded. A "Format" parameter in the request can select if the response is encoded as XML, JSON, WDDX, etc.

  1. Format=<one of: json, php, wddx, xml, yaml, etc.>

Example:

  1. Format=xml

XML Example: HTTP query:

  1. C: GET /srpc.php?Method=GetPrices&Symbol=GOOG&Date=1969-07-21&Format=xml HTTP/1.1

HTTP response (with a sample XML as a the result value):

  1. S: HTTP/1.1 200 OK
  2. S: Content-type: text/xml
  3. S:
  4. S: <?xml version="1.0"?>
  5. S: <prices>
  6. S: <price time="09:00">121.10</price>
  7. S: <price time="09:05">121.20</price>
  8. S: </prices>

JSON Example: HTTP query:

  1. C: GET /srpc.php?Method=GetPrices&Symbol=GOOG&Date=1969-07-21&Format=json HTTP/1.1

HTTP response (with a sample JSON as the result value):

  1. S: HTTP/1.1 200 OK
  2. S: Content-type: application/json
  3. S:
  4. S: {
  5. S: "prices": [
  6. S: { "time": "09:00", "value": "121.10" },
  7. S: { "time": "09:05", "value": "121.20" }
  8. S: ]
  9. S: }

12. Mai 2008

Wege aus der kleinen Coderkrise

Jeder Coder kennt die kleine Krise, wennn man zu lange an einem Programmierproblem hängt, dass eigentlich schnell erledigt sein sollte. Manchmal ist es ein Algorithmus, der sich nicht schön in geschlossener Form ausdrücken lassen will. Manchmal ist es eine Lösung die sich standhaft weigert auch alle Grenzfälle abzudecken. Manchmal ist es eine Komplexität, die sich nicht beherrschen lässt. Die Lösung der Krise wäre für den Coder ein Riesenschritt, für den Rest der Welt nicht. Meistens ist es sogar so, dass der Rest der Welt das Problem nicht sieht, weil es "nicht wirklich ein Problem sei kann" oder es "am Ende ja sowieso geht, wozu also aufregen?". Trotzdem bereitet es dem Coder schlaflose Nächte, Haareraufen, Hirnzermartern, Überstunden.

Im Nachhinein gesehen ist die Lösung dann doch meistens entweder "ziemlich einfach", "offensichtlich" oder "ein Hack". Jedenfalls ist es gelöst. Der Coder ist glücklich. Aber sonst interessiert sich keiner dafür.

OK, das war bisher nur Gerede. Diese zwei Absätz helfen keinem. Damit das ganze noch Hand und Fuss bekommt also hier meine Lösungsansätze. Natürlich hängt die konkrete Lösung sehr stark vom Problem hab. Deshalb hier nur Lösungsstrategien, keine Lösungen. Wie immer bei "Patterns": bitte keine Wunder erwarten. Hier steht nur was der vernünftige Coder eh' schon immer gemacht hat.

Wolfspel'z Wege aus der kleinen Coderkrise:

1. Display State

Short: Replace the display of state transitions with a display of the state.

Description: If a system has a complex state and if the state is displayed, then state transitions can be shown by changing the display according to the state transition. But sometimes there are too many possible transitions, similar, but different transitions, transition variants, so that changing the display to reflect the change of the model might be too complicated. Also: testing is very difficult, because all transitions (e.g. by user input) must be tested. If anything changes, then testing all transitions must be repeated. It is difficult to keep a the display consistent with the model, because changes are applied to both. They do not depend on each other. A model-view architecture surely helps, but introducing MVC might be a disruptive architecture change. So, the simpler solution is to redraw the complete display on each model change. If a state transition changes the model, then just repaint the screen.

Variant: If repainting is not feasible, e.g. in case of HTML user interfaces, then rearranging all elements to reflect the model's state is equivalent.

Comments: The downside of this approach is that it might be bad for performance. Applicability depends, but it might give you time for a real solution, especially if there is a deadline. (Let performance issues come back as a bug report :-)

Example:
If the code reads:
model.changeSomething();
display.showChanges();
model.changeSomethingElse();
display.showOtherChanges();


Change it to:
model.changeSomething();
display.showAll();
model.changeSomethingElse();
display.showAll();


2. Perturbation Theory

Short: If special cases prevent a closed solution, then treat them separately.

Description: An algorithmic solution might be difficult, because of context dependencies, special cases, or edge cases. They can make the algorithm complex. Complex algorithms are not good. algorithms should fit on a small page. A solution is to create the core algorithm as if there were no special cases. Then fix the remaining cases separately. A typical solution then starts with the core algorithm. If that is understood and tested, then work around it. The core algorithms could be followed by an additional code section that "fixes" wrong results of the core for special cases. There can ba multiple consecutive such fix-sections. Try to identify the core and then classes of deviations from the core. Then make all individual code sections starting with the core. Do not try to mix special cases into the core algorithm.

Comment: This approach is known as Perturbation Theory in physics. The first order solution is linear and understandable. Higher order solutions add special detail, but are more difficult to comprehend. Therefore they are split fom the first order and added later when the first order works.

3. Simplification

Short: Reduce complexity if possible.

Description: Structure is usually a good thing. But structure also makes solutions more complex. A single layer of hierarchy might make a problem just the bit too complex for the coder to understand it easily enough to derive a simple solution. If you strip away complexity, then you use features or potential features. Even features you might need or find cool or need in the future or might need in the future. Ask yourself: could it be simpler? The answer "no" is forbidden, because anything can be simpler even though you might loose something. The question is: do you loose something that you really need NOW. It might be, that you can even generalize and undo the simplification later. The problem is now. It must be solved now. Do not solve future problems. Just try not to inhibit future extensions while doing the simple thing.

Application:
Ask:
- could it be simpler? - the answer is "yes, but..."
- what would be missing?
- does it hurt now?
- does it hurt later? if yes, does it damage the structure so sverely, that it can not be fixed later.
Typical questions:
- is the hierarchy required, could it be flat? (remember XML-namespaces? XML is simple, namespaces build on top of flat names.)
- do I really need the full implementation or is a solid API with a fake implementation behind good enough?
- does it really have to be a dynamic registry or could we hardwire the modules and just pretend to use a dynamic list?

Then, get rid of it.

4. Start Over

Short: Throw it away and do it again (applies only to small pieces).

Description: Sometimes we produce much code over time. Sometimes very quickly, because a problem has many special cases. Sometimes code accumulates slowly. Anyhow, the result is not understood anymore with all side effects. Each additional feature which must be added, can be a nightmare. Either for the coder who wants to guarantee that "the old mess + the new feature" is still working or for the user who gets random behaviour occasionally. All these are symptoms for a system that is out of control. The same applies to algorithms. This is about solving small problems, not about systems. In case of systems there is no easy way to redo everything. But algorithms and few pages of implementation can be recreated. A new implementation might even get rid of the ballast that was added, but is not used anymore.

Comment: Start Over is a valid last resort to comply to the holy principle of "understand what you are doing". You must completely understand what you are coding and what it does to the data and to users. If you do not understand what you are changing or trying to fix, then you should make it so that you understand, even if that means to write it again in your own words.

Application:
Select code, copy to temp file, press delete.
Kids: do not try this at home.

5. Be Quick

Short: Do not spend much time on the solution. Find a solution quickly.

Description: Do not spend more than 30 minutes on a single algorithm. Do not think too long about a solution. They do not pay you for thinking. They pay you for coding. Programmers spend their time writing I/O, error handling, initialization, synchronization, testing. There is no time to brood for hours, because there is so much else to to. Maybe you can find a solution instead of squeezing it out. A similar problem has already been solved. There is a library for it. There is a software pattern. There is a similar service, that must have had a similar problem. Find the similarity and find out how they have done it.

Application:
Generalize your problem. What is the core of it. What are you really doing. Abstract from your class names and marketing labels. Then try Google.

6. Problem Elimination

Short: Change the problem, if the solution is too difficult

Description: There are all kinds of difficult problems. Most can be reduced to a series of smaller problems. But some withstand reduction, because "everything depends on everything else" and "a small change makes a big difference somewhere else", especially if the "somewhere else" is the marketing department. If a problem has too many (or unclear) requirements, then it might end up in a complex solution after a long time that does not benefit anyone, especially not future coding performance. A complex solution is an indication for a difficult problem. The possibility to create a good code structure indicates a good problem. On the other hand, the lack of a cool code solution indicates lack of a good problem. The problem might not be understood. Simplify the problem. Check what you really need. Use external solution proposals as a description of the real problem, rather than an implementation guideline. Re-create the real problem and make up your own solution.

Comment: It might be necessary to convince the product owner that what she really wants is something different than she talked about.

Application:
Analyze proposed solutions.
Find the core of the problem or find a better problem.
Convince them to change the task.

_happy_coding()

10. Mai 2008

Schach mit Google Docs

Man kann ein ge-share-tes Google Spreadsheet als Schachbrett benutzen. Alle (beide) Teilnehmer können live sehen was der andere macht.

Gezogen wird mit "Ausschneiden" und "Einfügen". Auf farbige Schachfelder verzichten wir deshalb lieber, sonst kopiert man den Hintergrund mit.

Die Spieler sind als weblins da und können chatten. Das wäre sogar in Google Docs gegangen mit "Chat about this spreadsheet". Aber Sprechblasen sind netter.