-
Active MQ dans le cloud – suite
Comme vous avez pu le lire dans le précédent article je n’étais pas arrivé au bout de l’exercice pour déployer ActiveMQ sur des offres PAAS. Et bien c’est chose faite, ça marche !
Mon erreur a été de me focaliser sur un problème réseau entre les VM (configuration, firewall…) En fait le problème était au niveau de l’ouverture des sockets. J’ai donc modifié le code du TCPConnector d’Active MQ pour l’adapter à mes contraintes.
Il faut juste changer le bind dans org.apache.activemq.transport.tcp.TcpTransportServer
public void bind() throws IOException { URI bind = getBindLocation(); String host = bind.getHost(); host = (host == null || host.length() == 0) ? "localhost" : host; InetAddress addr = InetAddress.getByName(host);en
public void bind() throws IOException { URI bind = getBindLocation(); InetAddress addr = InetAddress.getLocalHost();C’est plus restrictif, mais suffisant pour mon cas.
J’ai repackagé cela dans un protocole tcpcloud et hop ça fonctionne sur cloudbees du premier coup. Maintenant ma charge est partagée sur les n instances (n=2 pour le moment comme j’utilise l’offre gratuite).
Pour CloudFoundry j’ai eu un peu plus de mal car même si je note dans le fichier de config « localhost », il passe le nom de la machine au runtime. Ca doit être le même système qui remplace l’url et le login/pass de la base de données. Ce côté un peu magique me dérange. Je dois aussi dépendre de leur lib cloudfoundry-runtime pour trouver l’adresse IP de la VM. En plus leur beau plug-in eclipse ne fonctionne pas sur Eclipse Indigo
Je vais pouvoir partir en vacances sereinement !
-
Active MQ dans le cloud
En ce moment je regarde pour développer une plateforme de push notification iPhone. Le but est d’offrir une surcouche applicative plus simple à utiliser que les sockets d’Apple. Un peu comme le service offert par urbanairship.
Ce qu’il faut bien comprendre avec le push d’Apple, c’est que pour envoyer une notification à 400 000 iPhone il faut ouvrir une socket chez eux et envoyer 400 000 trames avec un token différent par iPhone. En sachant qu’Apple peut banir une IP serveur si on envoie plus de 200 messages par seconde, il est important de répartir la charge sur plusieurs serveurs (ou au moins plusieurs IP publiques).
Donc j’ai pensé à mettre en place une architecture MOM :
Avec cette architecture on peut ajouter des Brokers JMS en fonction de la charge à absorber. L’idée est de profiter au maximum des services de cloud computing et offrant la possibilité d’ajouter/retirer au runtime des VM avec un Broker. C’est donc pour héberger cette solution que j’ai creusé les différentes offres de cloud computing (cf ce post). Mais c’est au moment du déploiement que j’ai rencontré des difficultés (bah oui comme d’habitude en fait…).
Le code qui va envoyer les messages JMS doit connaitre la liste de Broker. Or comme nous sommes dans le cloud, cette liste peut être modifiée au bon vouloir de l’administrateur. Pire je ne connais même pas forcément à l’avance les IP des Broker que je vais ajouter.
Donc imaginez si dans la configuration client je définis une URI du type :
failover:(tcp://primary:61616,tcp://secondary:61616)
Il va falloir modifier le code du client à chaque ajout d’un nouveau Broker. C’est donc impossible. Heureusement pour ce genre de cas Active MQ propose un système de multicast. Ce qui donne au niveau URI du client :
discovery:(multicast://default)
Là c’est magique sur mon serveur en local ça marche très bien. Et oui mais non
Sur les offres cloud le multicast (sur UDP) n’est pas souvent supporté. Sur Amazon EC2 (donc sur CloudBees) et CloudFoundry (VMWare) impossible de faire fonctionner le multicast.Donc comment faire ? Le client JMS a besoin de récupérer une liste de Broker. Il faut donc que chaque Broker vienne se faire connaitre au moment de leur lancement. Comme j’ai déjà un BDD autant l’utiliser pour référencer ces Brokers. J’ai donc développer un module de multicast via une BDD : multicasdb.
Donc on arrive sur une architecture comme celle-ci :
Pour le faire je me suis beaucoup inspiré du code du multicast UDP. Ca fonctionne bien sur mes serveurs de test mais là encore je tombe sur des problèmes spécifiques aux serveurs cloud : l’adresse du serveur. Comme c’est le même war qui est déployé sur tous les serveurs la configuration du broker doit être générique. Pas de pb : j’utilise localhost comme nom de serveur :Donc oui je peux utiliser cette configuration sur tous les serveurs, mais si je persiste « localhost:8080″ en base le client ne pourra pas y accéder depuis un autre serveur. Donc il faut que mon code trouve l’IP du serveur pour le persister au runtime.
Aujourd’hui même si le code n’est pas finalisé, il fonctionne. Malheureusement j’ai toujours des problèmes pour l’héberger.
Chez Cloudbees la communication tcp entre VM est bloquée. Même si leur support affirme que ça peut fonctionner j’ai toujours des erreurs : java.net.ConnectException: Connection refused
Chez CloudFoundry j’ai même eu du mal à obtenir l’IP des VM. Le code qui fonctionne sur Cloudbees retourne 127.0.0.1 comme IP chez CloudFoundry. Pour trouver cette IP il faut utiliser un SDK fourni. Mais là encore :Connection refused
Bilan
Au final je n’ai pas réussi à faire fonctionner mon code comme je le voulais. Par contre cette petite expérience m’a permis de faire mes premiers pas sur 2 offres de cloud intéressantes. Aujourd’hui je trouve CloudFoundry beaucoup plus agréable à utiliser que CloudBees. Son SDK est très simple et en 20 secondes je peux redéployer une version. Avec CloudBees j’ai beaucoup de mal avec le SDK. Déjà c’est basé sur un script Ant… Alors il y a aussi un plug-in maven mais je n’ai pas pu l’utiliser en mode « Delta » du coup il faut uploader totalement mon War à chaque modification : 10 minutes. Je trouve aussi le plug-in Eclipse de CloudFoundry mieux fait. Par contre CloudBees possède une vrai interface d’administration web et son offre DEV@Cloud est vraiment intéressante. Un bon point pour les 2 : la réactivité du support. Une réponse dans la journée, pour mon compte gratuit de test, c’est vraiment bien (n’est ce pas Nicolas
)Pour revenir à mon problème initial, je vais continuer à creuser ce problème de communication inter VM et si je n’avance pas je vais revoir l’architecture. Peut-être persister les messages à envoyer: c’est moins performant mais ça peut aussi répondre à un besoin de suivi de diffusion.
La phase d’intégration d’un projet est toujours sous estimée J’ai vu des projets où cette phase était même plus importante en terme d’homme/jour que la phase de développement. Mais pour un hébergement dans le cloud il faut vraiment prendre cette problématique dès le début de la conception. C’est loin d’être un détail
-
Dans Ton Cloud
Depuis 2 semaines je regarde différentes solutions de cloud computing.
Dans un premier temps j’ai regardé les offres « bas niveau » :
C’est une offre abordable mais qui est en test depuis plus d’un an. C’est une facturation « Pay as you go » mais il manque deux fonctionnalités importantes : le load balancing et le clonage d’instance. L’adresse IP des instances change à chaque arrêt/relance ce qui peut être génant.
L’offre cloud la plus célèbre, j’ai arrêté l’inscription au moment d’entrer un numéro de carte bleue. Impossible de faire sans et comme le détail des tarifs est assez flou j’ai préféré ne pas le faire.
Le site So privé est fermé pour ouvrir OUTSCALE.
L’offre la plus intéressante pour le moment, load-Balancing clonage de VM, « Pay as you go ». Il manque juste des images un peu plus complètes avec par exemple un tomcat ou mysql.
Grosse pub pour leur VM à 1 Euro mais c’est uniquement des VM Windows -> Fail
Obtenir une VM avec un OS c’est bien, malheureusement je ne suis pas ingé système mais développeur Java donc si je pouvais utiliser des offres clouds faites pour déployer un war je gagnerais du temps. Et c’est exactement ce que propose Cloud Foundry et CloudBees. Oui Google App Engine le fait aussi mais dans mon cas j’ai besoin d’ouvrir une socket vers un serveur distant et donc GAE est out
C’est l’offre de VM Ware et Spring Source en version Beta pour le moment. En quelques minutes j’ai mis en ligne l’exemple Hello Word. Le plus long c’est de recevoir l’email d’inscription. Le SDK s’installe en 2 minutes grace à ruby (gem est pré-installé sur Mac).
Après le Hello Word j’ai déployé un war plus complexe très rapidement. Le plug-in eclipse est aussi très bien fait, on peut voir les ressources consommées par les applications, ajouter des instances (2 max pour le moment), les arrêter. Par contre j’ai eu un problème au niveau de l’affichage des logs. Sur Eclipse ce n’était pas à jour contrairement à ce qu’affichait la commande « vmc logs ».
Là encore CloudBees propose une solution pour déployer du code Java simplement. Le plus par rapport à Cloud Foundry c’est l’offre DEV@cloud qui propose une solution de GConf (GIT ou SVN) et une plate-forme d’intégration continue Jenkins. Ils sont placés pour Jenkins puisque Kohsuke Kawaguchi a intégré leur équipe.
RUN@cloud est proche de l’offre de Cloud Foundry en se limitant au Java. Le plus c’est le monitoring des instances et la possibilité d’uploader un war depuis l’interface web. Par contre j’ai trouvé le SDK et le plug-in eclipse beaucoup moins faciles à utiliser comparés à ceux de Cloud Foundry.
Le gros problème de ces deux solutions, pour héberger mon application, c’est qu’elles ne supportent pas le multicast UDP. Je vais faire un autre poste plus tard pour détailler mon problème.
Conclusion
J’ai bien aimé tester ces offres rapidement et gratuitement. On peut enfin déployer du code java facilement. Avant il fallait louer un serveur privé pour pouvoir installer un serveur tomcat et ce n’était pas une solution économique (minimum 15 Euros par mois). Maintenant en quelques minutes notre war est disponible sur le net.
Après peut-on utiliser CloudBees ou Cloud Foundry pour déployer une application pro? C’est à voir puisque je n’ai pas regardé comment affiner la configuration du serveur d’application. En tout cas c’est très prometteur.
Autres articles :
- Premiers pas sur CloudBees par Benoit Courtine
- Blog de Xebia : Lancement du projet PAAS cloud foundry de spring source
- Blog d’octo : Et si nous definissions simplement le cloud computing
-
Recrutement Ippon vraiment original
Je viens de tomber sur une offre emploi super bien faite d’Ippon Technologies sur l’excellent site de Nicolas Martignole : l’express board. (bon ok je suis un poil à la bourre elle date de Février…)
******************************************************************************
Chez Ippon Technologies, nous cherchons des consultants capables de lire cette offre d’emploi :
https://github.com/ippontech/IpponRecrute
******************************************************************************
Julien Dubois (passé de SpringSource à Ippon Technologies récemment) a même poussé le vis en encodant le texte de l’annonce dans le code. Il faut donc l’exécuter pour la lire.
Bravo Julien, j’adore l’idée !
-
Peut-on réussir un forfait ?
Plus je travaille avec des SSII et plus je trouve que les projets gérés au forfait se passent mal. Les torts sont souvent partagés, mais je constate plusieurs causes d’échec :
Le client est incapable de rédiger un cahier des charges
Là je sais de quoi je parle, j’ai souvent le rôle de client en ce moment
Le besoin évolue, n’est pas forcément clair et donc il est très dur de rédiger un cahier des charges exhaustif. Le client est obsédé par la garantie de réalisation qu’apporte le forfait, alors qu’il est incapable d’exprimer correctement son besoin. Pire je vois de plus en plus de forfait où on demande au prestataire de rédiger le cahier des charges : on rêve.
Les acheteurs : price killer
Oui c’est une bonne chose de tirer les prix vers le bas, mais il faut aussi rester raisonnable. Comment voulez-vous travailler sereinement avec des prestataires à qui on a mis le couteau sous la gorge. Pourquoi pas des enchères inversées pendant qu’on y est ? -souvenir-
Le réflexe « perdant – perdant »
J’ai l’impression d’être le seul à demander aux SSII d’augmenter leur chiffrage quand j’ai l’impression que c’est un peu juste. Une fois j’en parlais à un chef de projet, il m’a même répondu : « Ne leur dis rien, s’ils se plantent c’est pour leur pomme ! ». On sait très bien que ça ne se passe pas comme cela. A un moment si le prestataire s’est vraiment planté, c’est le projet qui va en pâtir (qualité de code, test unitaire, bug..)
L’inter-contrat
Même si les commerciaux sont les spécialistes pour vous faire de beaux discours sur leur « cellule forfait » avec des personnes dédiées. Il ne faut pas se leurrer, le forfait c’est l’idéal pour occuper une personne en inter-contrat. Le problème pour le projet c’est que l’on n’a jamais les mêmes développeurs en face. C’est dur d’assurer une continuité des développements.
Junior en solo
C’est un peu lié au problème des prix tirés vers le bas mais je vois de plus en plus de débutants seuls sur des projets. J’ai absolument rien contre les débutants mais il faut les encadrer. Le problème c’est qu’en SSII des développeurs avec 10 ans d’expérience c’est super rare. Et oui, on vend plus cher un mauvais chef de projet qu’un bon développeur avec de l’expérience.
Le Mythe du forfait de service
Depuis un certain temps on nous a mis en place des « forfaits de services ». Alors ça c’est encore une belle invention d’acheteur qui n’a pas du travailler dans le monde du développement. En gros le principe c’est d’envoyer une demande par email et d’attendre le livrable 2 mois plus tard. Vous ne savez pas qui travaille sur le projet, c’est une boite noire. Et donc on retombe dans les travers des deux précédents points et on va avoir des développeurs Flex juniors qui vont coder du J2EE.
Des solutions ?
Je sors justement d’une expérience forfait un peu difficile. A la signature du contrat tout est beau, c’est une société avec qui je travaille souvent, ils mettent en avant le fait qu’il sont CMMI niveau 3, on parle même d’intégration continue avec Hudson. Bref on est en confiance. Au final on nous livre du code Java d’une qualité affligeante (si si c’est le bon mot quand je trouve des noms de variable avec des accents), zéro test unitaire et cerise sur le gâteau le livrable ne compile pas car il manque des sources.
Malgré tout ça je vais continuer à travailler avec cette société. Car déjà elle n’est pas la seule responsable de cet « échec » mais surtout je pense que c’est avant tout un problème de mauvaise personne au mauvais endroit.
Mais comment faire en sorte que la future prestation se passe bien :
Travailler gagnant – gagnant
Partager les risques avec le prestataire, s’impliquer dans le chiffrage, travailler ensemble.
Choisir les intervenants
Il faut vraiment intégrer que la réussite d’un projet n’est pas lié à la société mais bien aux personnes qui réalisent. Faire passer des entretiens est donc primordial pour sélectionner son équipe. C’est le seul moyen d’être sûr que l’on va pas mettre un Flexeur à gérer des transactions JTA ( oui oui c’est du vécu…).
Faire des revues de code périodiquement
Les chefs de projets qui regardent la qualité du code livré sont rares, mais le faire à la livraison c’est surtout trop tard. Il est très important de bien suivre la qualité du code tout au long de la vie du projet pour s’assurer que ça ne diverge pas.
Et non coder un « proto » n’autorise pas à faire n’importe quoi ! (si je retrouve le gars qui a codé la gestion des transactions à la main dans un filtre HTTP je l’étripe
Conclusion
C’est bête à dire mais pour réussir il faut juste travailler en bonne intelligence avec le prestataire. Arrêter ce rapport maitre/esclave qui ne peut que mal finir et discuter d’égal à égal.
Le client devrait passer plus de temps sur son expression de besoins que sur les petites lignes du contrat cadre. Arrêtez d’être obsédé par la garantie de résultat et de date de livraison complètement illusoire pour vous reconcentrer sur l’essentiel : le produit.
Le développement agile permet de résoudre beaucoup de problèmes. Mais quand je vois que l’on demande à des prestataires de travailler de façon Agile mais en gardant un cadre type forfait avec engagement de résultat, c’est complètement antinomique !
-
Profiling SQL
C’est une étape souvent négligée par les projets utilisant des librairies de mapping objet. Mais faire de l’Hibernate c’est bien, regarder les requêtes générées sur la base c’est mieux.
J’ai le souvenir d’un vieux projet utilisant des EJB Entity 2 où à un moment on ajoutait un objet dans une liste. En regardant les requêtes on s’est aperçu que le conteneur chargeait toute la liste avant de faire l’insert. C’était complètement inutile.
Donc comment étudier correctement les requêtes ? Déjà si vous utilisez hibernate mettez la property « show_sql » à true de temps en temps. Après pour avoir plus d’informations j’utilise p6spy et IronEye SQL.
p6Spy est une librairie qui remplace votre driver de base de données. C’est en quelque sorte un driver proxy de BDD. IronEye apporte juste une vue graphique des informations récoltées par p6spy. Pour trouver de la doc c’est un peu dur www.p6spy.com ne fonctionne plus mais j’ai trouvé un site expliquant la mise en place de p6spy et de IronSql.
Par contre ce sont deux outils un peu « vieux ». p6spy n’a pas été mis à jour depuis 2003 et pour IronEye SQL la société IronGrid a disparu. Comme il est maintenant impossible de trouver IronEye en téléchargement je vous propose la version 1.2.359 que j’avais heureusement conservée : ironeyesql-installer-1_2_359.jar. (fonctionne que sur Windows chez moi). Le site sourceForge de p6spy est toujours up.
Sans refaire la doc, installer p6spy c’est simple, il faut juste remplacer le nom de votre driver jdbc par com.p6spy.engine.spy.P6SpyDriver et de mettre le nom du vrai driver dans le fichier spy.properties : realdriver = oracle.jdbc.driver.OracleDriver. Pour utiliser IronEye il faut en plus activer un port d’écoute dans le spy.properties :
module.monitor=com.irongrid.monitor.server.MonitorFactory
monitorport=2000Et voilà ! vous pouvez observer toutes les requêtes faites sur votre base. IronSQL va les regrouper, les compter et calculer le temps moyen d’exécution.
Sans être DBA vous allez très vite voir quelles requêtes sont faites souvent et les plus longues à s’exécuter. Très pratique pour voir si un cache L2 fonctionne bien ou si on a oublié un index sur une table.
Un exemple concret que j’ai corrigé hier :
Dans un service REST on passe en paramètre l’id d’un objet. C’est un service de monitoring appelé par du matériel pour lui passer des infos et s’assurer qu’il est encore en vie (du polling à défaut de push en gros)
Truc t = trucDao.getById(tid); t.setLastAccess(now);
Assez logique en java avec hibernate, mais l’objet t n’est jamais utilisé après. Le problème c’est qu’au niveau SQL on a un SELECT qui récupère toutes les informations de l’objet pour ensuite faire un UPDATE. Si en plus vous avez configuré des associations de votre objet en lazzy, ça peut être vraiment problématique.
J’ai changé ce code par :
trucDao.updateDateById(tid, now);
Maintenant il ne reste que la requête UPDATE. Lorsque l’on sait que nous allons avoir plusieurs milliers de « Truc » et qu’ils font cette requète toutes les 15 secondes. Je vous laisse calculer le gain en perf. Dans la même fonction j’ai aussi trouvé une requête SQL faite uniquement pour un log debug : no comment.



