web-dev-qa-db-fra.com

Optimisation des sites Web basés sur Kohana pour la vitesse et l'évolutivité

Un site que j'ai construit avec Kohana a été critiqué avec une énorme quantité de trafic hier, ce qui m'a obligé à prendre du recul et à évaluer une partie de la conception. Je suis curieux de savoir quelles sont les techniques standard pour optimiser les applications basées sur Kohana?

Je suis également intéressé par l'analyse comparative. Dois-je configurer Benchmark::start() et Benchmark::stop() pour chaque méthode de contrôleur afin de voir les temps d'exécution pour toutes les pages, ou est-ce que je peux appliquer l'analyse comparative globalement et rapidement?

J'utiliserai davantage la bibliothèque Cache dans le temps à venir, mais je suis ouvert à plus de suggestions car je suis sûr que je peux faire beaucoup de choses dont je ne suis tout simplement pas au courant pour le moment.

80
Sampson

Ce que je vais dire dans cette réponse n'est pas spécifique à Kohana, et peut probablement s'appliquer à beaucoup de PHP projets.

Voici quelques points qui me viennent à l'esprit lorsque l'on parle de performances, d'évolutivité, de PHP, ...
J'ai utilisé plusieurs de ces idées en travaillant sur plusieurs projets - et elles ont aidé; donc ils pourraient probablement aider ici aussi.


Tout d'abord, en matière de performances, il y a de nombreux aspects/questions à prendre en compte :

  • configuration du serveur (Apache, PHP, MySQL, autres démons possibles et système); vous pourriez obtenir plus d'aide à ce sujet sur ServerFault, je suppose,
  • Code PHP,
  • Requêtes de base de données,
  • Vous utilisez ou non votre serveur Web?
  • Pouvez-vous utiliser n'importe quel type de mécanisme de mise en cache? Ou avez-vous toujours besoin de plus de données à jour sur le site Web?


Utilisation d'un proxy inverse

La première chose qui pourrait être vraiment utile est d'utiliser un proxy inverse , comme vernis, devant votre serveur web: laissez-le mettre en cache autant de choses que possible , donc uniquement les requêtes qui ont vraiment besoin de PHP/Calculs MySQL (et, bien sûr, quelques autres requêtes, quand elles ne sont pas dans le cache du proxy) le faire à Apache/PHP/MySQL.

  • Tout d'abord, votre CSS/Javascript/Images -- enfin, tout ce qui est statique - n'a probablement pas besoin d'être toujours servi par Apache
    • Ainsi, vous pouvez avoir le cache du proxy inverse tout cela.
    • Servir ces fichiers statiques n'est pas un problème pour Apache, mais moins cela doit fonctionner pour ceux-ci, plus il sera capable de faire avec PHP.
    • N'oubliez pas: Apache ne peut traiter qu'un nombre fini et limité de requêtes à la fois.
  • Ensuite, demandez au proxy inverse de servir autant de pages PHP que possible à partir du cache: il y a probablement des pages qui ne changent pas souvent , et pourraient être servi à partir du cache. Au lieu d'utiliser un cache basé sur PHP, pourquoi ne pas laisser un autre serveur plus léger servir ces (et les récupérer de temps en temps sur le serveur PHP, donc ils sont toujours presque à jour)?
    • Par exemple, si vous avez des flux RSS (nous avons généralement tendance à oublier ceux, en essayant d'optimiser les performances) qui sont demandés très souvent , les avoir en cache pendant quelques minutes pourrait sauver des centaines/milliers de requêtes vers Apache + PHP + MySQL!
    • Idem pour les pages les plus visitées de votre site, si elles ne changent pas pendant au moins quelques minutes (exemple: page d'accueil?), alors, pas besoin de gaspiller le CPU en les régénérant chaque fois qu'un utilisateur les demande.
  • Il y a peut-être une différence entre les pages servies aux utilisateurs anonymes (la même page pour tous les utilisateurs anonymes) et les pages servies aux utilisateurs identifiés ("Bonjour M. X, vous avez de nouveaux messages" , par exemple)?
    • Si tel est le cas, vous pouvez probablement configurer le proxy inverse pour mettre en cache la page qui est servie pour les utilisateurs anonymes (basé sur un cookie, comme le cookie de session, généralement)
    • Cela signifiera qu'Apache + PHP a moins à gérer: uniquement des utilisateurs identifiés - qui pourraient ne représenter qu'une petite partie de vos utilisateurs.

À propos de utilisant un proxy inverse comme cache , pour une application PHP), vous pouvez, par exemple, jeter un œil at Les résultats de référence montrent une augmentation de 400% à 700% des capacités du serveur avec APC et Squid Cache.
(Oui, ils utilisent Squid, et je parlais de vernis - c'est juste une autre possibilité ^^ Le vernis étant plus récent, mais plus dédié à la mise en cache)

Si vous faites cela assez bien et que vous parvenez à arrêter de générer encore et encore trop de pages, peut-être que vous n'aurez même pas à optimiser votre code ;-)
Du moins, peut-être pas dans n'importe quel type de Rush ... Et il est toujours préférable d'effectuer des optimisations lorsque vous n'êtes pas sous trop de pression ...


En guise de remarque: vous dites dans le PO:

Un site que j'ai construit avec Kohana a été critiqué avec une énorme quantité de trafic hier,

C'est le genre de situation soudaine où un reverse-proxy peut littéralement sauver la journée , si votre site Web peut gérer le fait de ne pas être à jour à la seconde :

  • installez-le, configurez-le, laissez-le toujours -- tous les jours normaux - exécuter:
    • Configurez-le pour ne pas garder PHP pages dans le cache; ou seulement pour une courte durée; de ​​cette façon, vous avez toujours des données à jour affichées
  • Et, le jour où vous prenez un effet slashdot ou digg: ​​
    • Configurez le proxy inverse pour garder PHP pages dans le cache; ou pendant une période plus longue; peut-être que vos pages ne seront pas à jour à la seconde, mais cela permettra à votre site Web de survivre au effet de digg!

À propos de cela, Comment puis-je détecter et survivre à être "Slashdotted"? pourrait être une lecture intéressante.


Du côté PHP des choses:

Tout d'abord: utilisez-vous une version récente de PHP ? Il y a régulièrement des améliorations de vitesse, avec de nouvelles versions ;-)
Par exemple, jetez un œil à Benchmark of PHP Branches 3.0 à 5.3-CVS.

Notez que les performances sont une bonne raison d'utiliser PHP 5.3 ( j'ai fait quelques benchmarks (en français) , et les résultats sont excellents) ...
Une autre très bonne raison étant, bien sûr, que PHP 5.2 a atteint sa fin de vie, et n'est plus maintenu !

Utilisez-vous un cache d'opcode?

  • Je pense à APC - Alternative PHP Cache , par exemple ( pecl , manuel ), qui est la solution que j'ai vue le plus utilisée - et qui est utilisée sur tous les serveurs sur lesquels j'ai travaillé.
  • Cela peut vraiment réduire considérablement la charge CPU d'un serveur, dans certains cas (j'ai vu la charge CPU sur certains serveurs passer de 80% à 40%, simplement en installant APC et en activant son opcode-cache fonctionnalité!)
  • En gros, l'exécution d'un script PHP se déroule en deux étapes:
    • Compilation du PHP code source en opcodes (sorte d'équivalent du bytecode de Java)
    • Exécution de ces opcodes
    • APC les garde en mémoire, donc il y a moins de travail à faire chaque fois qu'un PHP script/file est exécuté: récupérez uniquement les opcodes de la RAM et exécutez-les.
  • Vous devrez peut-être jeter un œil à APC options de configuration, au fait
    • il y en a plusieurs, et certains peuvent avoir un impact important sur la vitesse/la charge du processeur/la facilité d'utilisation pour vous
    • Par exemple, désactiver [apc.stat](https://php.net/manual/en/apc.configuration.php#ini.apc.stat) peut être bon pour la charge du système; mais cela signifie que les modifications apportées aux PHP fichiers ne seront pas prises en compte à moins que vous ne vidiez tout l'opcode-cache; à ce sujet, pour plus de détails, voir par exemple To stat ( ) Ou ne pas statuer ()?


Utilisation du cache pour les données

Autant que possible, il vaut mieux éviter de refaire sans cesse la même chose .

La principale chose à laquelle je pense est, bien sûr, les requêtes SQL: beaucoup de vos pages font probablement les mêmes requêtes, et les résultats de certaines d'entre elles sont probablement presque toujours les mêmes ... Ce qui signifie beaucoup de "inutile" requêtes faites à la base de données, qui doit passer du temps à servir les mêmes données encore et encore.
Bien sûr, cela est vrai pour d'autres choses, comme les appels aux services Web, la récupération d'informations sur d'autres sites Web, les calculs lourds, ...

Il pourrait être très intéressant pour vous d'identifier:

  • Quelles requêtes sont exécutées plusieurs fois, renvoyant toujours les mêmes données
  • Quels autres calculs (lourd) sont effectués beaucoup de temps, retournant toujours le même résultat

Et stockez ces données/résultats dans une sorte de cache, afin qu'ils soient plus faciles à obtenir - plus rapide - et vous n'avez pas à vous rendre sur votre serveur SQL pour "rien".

Les grands mécanismes de mise en cache sont, par exemple:

  • [~ # ~] apc [~ # ~] : en plus de l'opcode-cache dont j'ai parlé plus tôt, il permet de stocker des données en mémoire ,
  • Et/ou memcached ( voir aussi ), ce qui est très utile si vous avez littéralement beaucoup de données et/ou si utilisez plusieurs serveurs , tel qu'il est distribué.
  • bien sûr, vous pouvez penser aux fichiers; et probablement de nombreuses autres idées.

Je suis presque sûr que votre framework contient des éléments liés au cache; vous savez probablement déjà que, comme vous l'avez dit "J'utiliserai la bibliothèque Cache plus à temps à venir" dans l'OP ;-)


Profilage

Maintenant, une bonne chose à faire serait d'utiliser l'extension Xdebug au profil votre application : elle permet souvent de trouver assez facilement quelques points faibles - du moins, s'il y a une fonction qui prend beaucoup de temps.

Configuré correctement, il générera des fichiers de profilage pouvant être analysés avec certains outils graphiques, tels que:

  • KCachegrind: mon préféré, mais ne fonctionne que sur Linux/KDE
  • Wincachegrind pour Windows; il fait un peu moins de choses que KCacheGrind, malheureusement - il n'affiche généralement pas de graphes d'appels.
  • Webgrind qui fonctionne sur un serveur PHP webserver, donc fonctionne n'importe où - mais a probablement moins de fonctionnalités.

Par exemple, voici quelques captures d'écran de KCacheGrind:

KCacheGrind : main screen
(source: Pascal-martin.fr )
KCacheGrind : Callgraph exported as an image
(source: Pascal-martin.fr )

(BTW, le callgraph présenté sur la deuxième capture d'écran est généralement quelque chose que ni WinCacheGrind ni Webgrind ne peuvent faire, si je me souviens bien ^^)


(Merci @Mikushi pour le commentaire) Une autre possibilité que je n'ai pas beaucoup utilisée est le xhprof = extension: elle aide également au profilage, peut générer des callgraphs - mais est plus légère que Xdebug, ce qui signifie que vous devriez pouvoir l'installer sur un serveur de production.

Vous devriez pouvoir l'utiliser seul XHGui, ce qui aidera à la visualisation des données.


Du côté SQL des choses:

Maintenant que nous avons parlé un peu de PHP, notez qu'il est plus que possible que votre goulot d'étranglement ne soit pas le côté PHP des choses , mais la base de données un ...

Au moins deux ou trois choses, ici:

  • Vous devez déterminer:
    • Quelles sont les requêtes les plus fréquentes de votre application
    • Si ceux-ci sont optimisés (en utilisant les bons index , principalement?), en utilisant le EXPLAIN instruction, si vous utilisez MySQL
    • si vous pouvez mettre en cache certaines de ces requêtes (voir ce que j'ai dit plus tôt)
  • Votre MySQL est-il bien configuré? Je ne sais pas grand-chose à ce sujet, mais certaines options de configuration peuvent avoir un certain impact.

Pourtant, les deux choses les plus importantes sont:

  • N'allez pas dans la base de données si vous n'avez pas besoin de: mettre en cache autant que vous le pouvez !
  • Lorsque vous devez accéder à la base de données, utilisez des requêtes efficaces: utilisez des index; et profil!


Et quoi maintenant?

Si vous lisez encore, qu'est-ce qui pourrait être optimisé?

Eh bien, il y a encore de la place pour des améliorations ... Quelques idées orientées architecture pourraient être:

  • Passer à une architecture à n niveaux:
    • Mettez MySQL sur un autre serveur (2-tier: un pour PHP; l'autre pour MySQL)
    • Utilisez plusieurs PHP serveurs (et répartissez la charge entre les utilisateurs)
    • Utilisez une autre machine pour les fichiers statiques, avec un serveur Web plus léger, comme:
      • lighttpd
      • ou nginx - celui-ci devient de plus en plus populaire, btw.
    • Utilisez plusieurs serveurs pour MySQL, plusieurs serveurs pour PHP et plusieurs reverse-proxies devant ceux-ci
    • Bien sûr: installez memcached les démons sur n'importe quel serveur qui a n'importe quelle quantité de RAM libre, et utilisez-les pour mettre en cache autant que vous le pouvez/cela a du sens.
  • Utiliser quelque chose de "plus efficace" qu'Apache?
    • J'entends de plus en plus souvent parler de nginx, ce qui est censé être génial quand il s'agit de PHP et sites Web à grand volume; je ne l'ai jamais utilisé moi-même, mais vous pourriez trouver des articles intéressants à ce sujet sur le net;

Eh bien, peut-être que certaines de ces idées sont un peu exagérées dans votre situation ^^
Mais, quand même ... Pourquoi ne pas les étudier un peu, juste au cas où? ;-)


Et qu'en est-il de Kohana?

Votre question initiale portait sur l'optimisation d'une application qui utilise Kohana ... Eh bien, j'ai publié quelques idées qui sont vraies pour toute PHP application ... Ce qui signifie qu'ils sont également vrais pour Kohana ;-)
(Même si ce n'est pas spécifique ^^)

J'ai dit: utilisez le cache; Kohana semble prendre en charge certains mise en cache (Vous en avez parlé vous-même, donc rien de nouveau ici ...)
S'il y a quelque chose qui peut être fait rapidement, essayez-le ;-)

J'ai également dit que vous ne devriez rien faire qui ne soit pas nécessaire; y a-t-il quelque chose d'activé par défaut dans Kohana dont vous n'avez pas besoin?
En parcourant le net, il semble qu'il y ait au moins quelque chose à propos du filtrage XSS; avez-vous besoin de ça?

Pourtant, voici quelques liens qui pourraient être utiles:


Conclusion?

Et, pour conclure, une simple pensée:

  • Combien cela coûtera à votre entreprise de vous payer 5 jours? -- considérant que c'est un laps de temps raisonnable pour faire de bonnes optimisations
  • Combien coûtera à votre entreprise l'achat (payer?) un deuxième serveur et sa maintenance?
  • Que faire si vous devez augmenter votre taille?
    • Combien cela vous coûtera-t-il de passer 10 jours? plus? optimiser chaque partie possible de votre application?
    • Et combien pour quelques serveurs de plus?

Je ne dis pas que vous ne devriez pas optimiser: vous devriez certainement!
Mais optez pour des optimisations "rapides" qui vous rapporteront d'abord de grosses récompenses : l'utilisation d'un cache d'opcode peut vous aider à obtenir entre 10 et 50 pour cent de réduction sur la charge CPU de votre serveur ... Et la configuration ne prend que quelques minutes ;-) De l'autre côté, passer 3 jours pour 2 pour cent ...

Oh, et, btw: avant de faire quoi que ce soit: mettre en place des éléments de surveillance , pour que vous sachiez quelles améliorations ont été apportées, et comment!
Sans surveillance, vous n'aurez aucune idée de l'effet de ce que vous avez fait ... Pas même si c'est une véritable optimisation ou pas!

Par exemple, vous pouvez utiliser quelque chose comme RRDtool + cactus.
Et montrer à votre patron des graphismes sympas avec une perte de charge CPU de 40% est toujours génial ;-)


Quoi qu'il en soit, et pour vraiment conclure: amusez-vous!
(Oui, l'optimisation est amusant!)
(Ergh, je ne pensais pas que j'écrirais autant ... J'espère qu'au moins certaines parties de ceci sont utiles ... Et je devrais me souvenir de cette réponse: cela pourrait être utile d'autres fois ...)

211
Pascal MARTIN

Utilisez XDebug et WinCacheGrind ou WebCacheGrind pour profiler et analyser l'exécution lente du code.

WebCacheGrind
(source: jokke.dk )
WinCacheGrind

6
Alix Axel

Kohana est prêt à l'emploi très très rapide, sauf pour l'utilisation d'objets de base de données. Pour citer Zombor "Vous pouvez réduire l'utilisation de la mémoire en vous assurant que vous utilisez l'objet de résultat de la base de données au lieu des tableaux de résultats." Cela fait une énorme différence de performance sur un site qui est critiqué. Non seulement il utilise plus de mémoire, mais il ralentit l'exécution des scripts.

De plus, vous devez utiliser la mise en cache. Je préfère Memcache et l'utilise dans mes modèles comme ceci:

public function get($e_id)
{
    $event_data = $this->cache->get('event_get_'.$e_id.Kohana::config('config.site_domain'));

    if ($event_data === NULL)
    {
        $this->db_slave
            ->select('e_id,e_name')
            ->from('Events')
            ->where('e_id', $e_id);

        $result = $this->db_slave->get();
        $event_data = ($result->count() ==1)? $result->current() : FALSE;

        $this->cache->set('event_get_'.$e_id.Kohana::config('config.site_domain'), $event_data, NULL, 300); // 5 minutes
    }

    return $event_data;
}

Cela augmentera également considérablement les performances. Les deux techniques ci-dessus ont amélioré les performances d'un site de 80%.

Si vous avez donné plus d'informations sur l'endroit où vous pensez que se trouve le goulot d'étranglement, je suis sûr que nous pourrions vous donner de meilleures idées.

Consultez également yslow (google it) pour d'autres conseils de performance.

5
ae.

Code de profil avec XDebug .

Utilisez beaucoup de mise en cache. Si vos pages sont relativement statiques, le proxy inverse peut être le meilleur moyen de le faire.

5
Kornel

Strictement lié à Kohana (vous l'avez probablement déjà fait, ou pas):

En mode production:

  1. Activer la mise en cache interne (cela ne mettra en cache que les résultats de Kohana :: find_file, mais cela peut en fait beaucoup aider.
  2. Désactiver le profileur

Juste mes 2 cents :)

1
Tamás Pap

Je suis totalement d'accord avec les réponses XDebug et la mise en cache. Ne regardez pas dans la couche Kohana pour l'optimisation avant d'avoir identifié vos plus grands goulots d'étranglement de vitesse et d'échelle.

XDebug vous dira où vous passez le plus de temps et identifiera les "points chauds" dans votre code. Conservez ces informations de profilage afin de pouvoir référencer et mesurer les améliorations de performances.

Exemple de problème et de solution: Si vous constatez que vous créez à chaque fois des objets coûteux à partir de la base de données, qui ne changent pas vraiment souvent, vous pouvez envisager de les mettre en cache avec Memcached ou un autre mécanisme. Tous ces correctifs de performances prennent du temps et ajoutent de la complexité à votre système, alors assurez-vous de vos goulots d'étranglement avant de commencer à les corriger.

0
Ozten