Showing posts with label compression. Show all posts
Showing posts with label compression. Show all posts

Using CDN caching with GraphQL

Introduction

Hi, today we'll see how-to do a CDN GraphQL caching system in some quick, easy and dirty steps. The idea came to me to make this article because the other day I was reading a Blog post about some reasons you should not use GraphQL in production. I've been using it for a bit on production websites and I disagree with some of the arguments presented in the paper.

One of them was that you cannot do CDN caching with GraphQL because almost no CDN manage POST body cache management. That's why I'll show you in this article how you could (but shouldn't) implement GraphQL GET request caching to do (almost) the same as a JSON REST API.

Creating a simple GraphQL server

So let's begin by creating a GraphQL server with a really simple schema offering a simple hello world field. I used Koa (because it is better than express :troll:) and expose a /graphql endpoint.

const Koa = require('koa');
const Router = require('koa-router');
const graphqlHTTP = require('koa-graphql');

const {buildSchema} = require('graphql');

const app = new Koa();
const router = new Router();

const schema = buildSchema(`
  type Query {
    hello: String
  }
`);

const root = {
  hello: () => {
    return 'Hello world!';
  },
};

router.all('/graphql', graphqlHTTP({
 schema,
 rootValue: root,
 graphiql: true
}))

app.use(router.routes()).use(router.allowedMethods())

app.listen(4000)

Then we do a graphql query to see if it works. Annnnnd Yes.

curl -X GET "http://0.0.0.0:4000/graphql?query=%7Bhello%7D"
{"data":{"hello":"Hello world!"}}

As you can see I'm passing a query parameter to define which GraphQL action I want to do on server.

How-to

Actually our caching could already work as is, as GraphQL query is passed on GET method and not on POST. But, because GraphQL queries can be very big, the default option is to use POST. The solution to still use GET request is to compress the query using lz-string in order to not have any problem while passing our queries.

So to do that, we'll create a fake client that will add query string compression and force GET request.

const rp = require('request-promise');
const LZString = require('lz-string');

function prepareQuery(query) {
 return LZString.compressToBase64(query);
}

async function sendQuery() {
 return rp({
  method: 'GET',
  uri: 'http://0.0.0.0:4000/graphql',
  qs: {
   query: prepareQuery('{hello}')
  }
 })
}

sendQuery()
 .then(res => console.log(res))

So the query will now look like this :


REQUEST emitting complete http://0.0.0.0:4000/graphql?query=N4CwpgNhD2C%2BQ%3D%3D%3D
{"data":{"hello":"Hello world!"}}

Now to handle this type of query we need to add some reaaaally simple logic to our GraphQL middleware that will decode the query before sending it to our schema treatment routine. This is done by using the function handler that is executed at the very beginning of GraphQL koa middleware.

router.all('/graphql', graphqlHTTP((request, response, ctx) => {
 const decodedQuery = LZString.decompressFromBase64(request.query.query);
 ctx.query = {query: decodedQuery};
 return {
  schema,
  rootValue: root,
  graphiql: true
 }
}))

As you can see it very simple and straightforward to make it happen. So why isn't it the default GraphQL implementation ?

Conclusion

Actually GraphQL implementations, I'm mainly talking about Apollo Server, as it is the one I know most, implement caching a very different way. By caching received data on client side, they optimized the requesting process, because clients manage locally their own caches you can avoid a lot of useless requests to the server.

The other drawback of this CDN server caching is that GraphQL queries may slightly change and therefore create lot of cache entries for each clients.

To conclude, I'd say this implementation could be useful on some specific cases where clients always do the same requests and you cannot add client caching system (on some legacy system) but it should be avoided as much as possible as it is not the most efficient way to do GraphQL query caching.

Go see my website for some more data about who am I : https://www.flyersweb.org

H.264 Decoder in javascript

Une performance impressionnante de la part de Michael Bebenita qui a eu l'idée de convertir le code en C du décodeur vidéo H.264 de Android en Javascript. Bien sûr le script est encore en phase de test mais donne des résultats intéressant. En effet le script tourne aux alentours des 20 FPS sous la nightly build de Firefox. Malheureusement les résultats ne sont vraiment pas les mêmes sur les versions stables de Chrome ou Firefox. Le script s'appel Broadway et il est prévu d'utiliser WebGL pour tirer partie de la puissance du GPU.

Vous pouvez accéder à la démonstration à cette adresse : devongovett.github.com/Broadway.

Compression Gzip

Bonjour, bonjour,

Ca fait un petit moment que j'ai pas eu le temps de poster sur mon blog, j'ai donc décidé de me racheter

Introduction

Courant Mars, Google a mis en production une nouvelle version de son site comme vous avez été nombreux à le voir. Ce changement inclus également une modification de l'algorithme d'indexation de Google. En effet, l'algorithme appelé MayDay a été mis en place suivi, plus récemment, par l'algorithme Caffeine.

Ces modifications de l'indexation ont eu des effets sur le référencement de nombreux sites car Google a modifié ses critères de classement. De nouveaux critères entres maintenant en jeu. Parmi ceux-là il y a maintenant la vitesse de réponse du serveur.

Nous allons voir aujourd'hui comment améliorer ce critère à l'aide d'un technique de compression à la volée.

Module Gzip/Deflate

La compression des données à la volée permet de diminuer la taille des données transférées entre votre navigateur et le serveur. En effet, grâce à cette technique, votre navigateur reçoit les données HTML compressée par Gzip et les décompresse pour les afficher.

Cette technique peut vous premettre de gagner jusqu'à 8 secondes de temps de réponse. Le seul bémol de cette technique est qu'elle nécessite un serveur d'assez bonne qualité puisque le processeur est plus utilisé.

Pour activer Gzip, rien de plus simple installez mod_deflate pour Apache 2.x et mod_gzip pour Apache 1.x.

Activez ensuite le module dans votre httpd.conf : LoadModule deflate_module modules/mod_deflate.so

Et ajoutez la règle suivante dans le : AddOutputFilterByType DEFLATE text/html. Ce qui compressera les fichiers HTML.

Vous pouvez également ajouter des règles pour d'autres types de fichiers comme les MP3 ou PDF mais sachez qu'il peut y avoir des incompatibilités avec ces formats.

PHP Zlib

Vous pouvez également activer ce module grâce à PHP. Vous aurez besoin avant tout que l'extension Zlib de PHP soit installée.

Ajoutez le code suivant en tout début de page : ob_start("ob_gzhandler");

Le handler ob_gzhandler est un alias facilitant l'activation de la compression gzip. L'inconvénient de cette technique est le même que précédemment, cela aura pour effet d'utiliser plus le processeur de votre serveur.

Autre optimisation

Vous pouvez également forcer le taux de rafraîchissement du cache de vos visiteurs grâce à l'entête Expires. Ainsi vos visiteurs ne chargeront vos images que lors de leur première visite. Le point négatif de ce dispositif est que le client doit vider son cache pour que son navigateur prenne en compte les modifications que vous avez apportées.

L'entête Expires prend comme argument une date d'expiration. Si la date est antérieure à la date courante, le cache sera mis à jour. Attention, les dates supérieures à un an par rapport à la date courante ne sont pas conseillées.

En Php pour utiliser l'entête Expires, rien de plus simple, vous utilisez la fonction header : header("Expires: ".gmdate('D, d M Y H:i:s', time()+(60*60*24).' GMT'); .

Nous définissons donc une date d'expiration de 60 secondes * 60 minutes * 24 heures soit 1 journée. Ainsi durant une journée vos visiteurs ne mettrons pas à jour leur cache.

Conclusion

Il existe de nombreuses techniques d'optimisation du temps de réponse de votre serveur web. On peut citer l'optimisation des fichiers CSS et JavaScript mais aussi l'optimisation de vos requêtes SQL.

De nombreux développeur oublient de prendre ce paramètre en compte lors du développement d'un site internet or ces optimisations deviennent de plus en plus indispensables aux vues des exigences des moteurs de recherche actuels.

Voilà, voilà, sur ce je vous souhaite une très bonne soirée.

A+, Flyers.

Most seen