Archives mensuelles : avril 2014

Apache 2 : modes worker et prefork

Il y a deux tribus, modes pour apache 2 : prefork et worker, affectés au moment de la compilation.

Quelles différences ?

En mode prefork, les requêtes sont traitées par des processus lourds. Le premier processus lancé écoute sur le port 80 (et/ou 443, ou autre), puis dispatche les requêtes sur des processus fils (le nom prefork venant de la méthode C fork qui permet de créer de nouveaux processus sous unix).

Pour traiter 250 connexions simultanées, il faudra donc 251 processus : le processus parent qui écoute et les 250 fils qui traitent.

Dans la configuration, le paramètre ServerLimit limite le nombre de processus pouvant être lancés au maximum. Le paramètre MaxClients limite le nombre de clients pouvant se connecter. Il doit être inférieur ou égal à ServerLimit, l’égalité étant plus logique.

Exemple de configuration :

<IfModule mpm_prefork_module>
    ServerLimit         500
    MaxClients          500
    MaxRequestsPerChild   0
</IfModule>

En mode worker, les requêtes sont traitées par des threads, eux même regroupés dans des processus. On a par exemple 25 thread par processus, et 10 processus. Pour traiter 250 requêtes il faudra 11 processus, et 250 threads. Le MaxClients correspond au nombre de threads total. Il faudra aussi configurer le nombre de processus et le nombre de thread par processus. Le MaxClients peut inférieur au nombre de processus (ServerLimit) multiplié par le nombre de thread (ThreadsPerChild), mais pas supérieur.

Exemple de configuration :

<IfModule mpm_worker_module>
    [...]
    ServerLimit         20
    MaxClients          500
    [...]
    ThreadsPerChild      25
</IfModule>

Lequel utiliser ?

Le mode worker utilisant des processus léger, il est plus performant pour traiter un grand nombre d’utilisateurs : moins de mémoire occupée, context switching plus léger… Or par défaut, apache est installé en mode prefork. Pourquoi ? Pour éviter les problèmes avec certaines librairies PHP qui ne sont pas thread safe.

L’erreur ergonomique de Spotify

Récemment Spotify a mis à jour ses applications Desktop et mobile. Outre un nouveau look basé sur le noir (pour les fans de gothique surement), cette version ajoute un menu « Ma musique », avec des listes de titres, albums, et artistes. Comme iTunes quoi.

Ma musique

Et surtout cette version ajoute un bouton « Enregistrer » qui permet d’ajouter en un clic dans « Ma musique » les albums lorsqu’on parcoure :

Le bouton enregistrer

Ca a l’air super bien!

Sauf que.

Sauf que les albums que l’on avait déjà enregistré en tant que playlists dans l’ancien système n’apparaissent pas dans cette rubrique « ma musique »…

Du coup comme il n’est pas question pour moi de migrer les dizaines d’albums que j’ai déjà sélectionné (je préfère passer mon temps à écrire des posts pour râler), je n’utilise pas ce bouton et j’ajoute les albums en tant que playlist comme avant.

Echec donc pour Spotify. D’autant qu’il n’est pas très difficile de créer un parcours des playlists pour voir lesquelles sont des albums non touchés.

 

Petite astuce logback

Petite astuce avec logback : il est possible d’utiliser des variables dans le fichier de configuration, définies comme variables d’environnement (-D) ou venant d’un fichier de properties paramétré dans le fichier logback.xml. ce fichier peut même provenir du classpath :

par exemple avec dans mon fichier properties :

1
environment=INT

Et la config logback suivante :

1
2
3
4
5
6
7
8
9
10
11
12
13
<property resource="monapp-config.properties" />

    <appender name="monapp" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>/tmp/logs/monapp-${environment}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>/tmp/logs/monapp-${environment}.%d{yyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>

        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>

Je peux faire varier le nom du fichier en fonction de l’environnement (qui peut lui même être filtré par maven mais c’est une autre histoire).