Traffic mirroring by NGINX mirror module
Tags: api, mirroring, nginx
Published: 2019-12-23 21:08:19

---
title: Traffic mirroring by NGINX mirror module
published: true
description: Traffic mirroring by NGINX mirror module
tags: #api #mirroring #nginx
cover_image: https://thepracticaldev.s3.amazonaws.com/i/zwmuewnnjg4cigmphiu8.jpg
---

Hi everyone.

A few months ago I've decided to work on migrating one of our company services from Php to Go services because of no engineers to continue to develop or support our endpoints, the new endpoints were coming by developers using Go instead. As for me, I have good enough experience in Ruby/Go/JS but I don't think I wanted to increase in pretty old endpoints written for years ago. 

Let's say if you have high load usage of your services what is the best way to make the migration. The idea came to me while I was reading the docs from Nginx website about the mirror module ( [https://nginx.org/en/docs/http/ngx_http_mirror_module.html](https://nginx.org/en/docs/http/ngx_http_mirror_module.html) ). 

Probably it would be a reasonable way to use it in my case. To make the prototype I used docker-compose where I put all of my services in one place and attached log during the making the basic requests. 

The simplified version below:

    version: "3"
    
    services:
      entry:
        image: nginx
        volumes:
         - ./v2/nginx.template:/etc/nginx/conf.d/default.conf
        links:
          - v1
          - v2_backend
        ports:
         - "80:80"
        environment:
         - NGINX_PORT=80
        command: /bin/bash -c "exec nginx -g 'daemon off;'"
    
      v1:
        image: nginx
        volumes:
         - ./v1/nginx.template:/etc/nginx/conf.d/default.conf
        links:
          - v1_backend
        expose:
         - "80"
        environment:
         - NGINX_PORT=80
        command: /bin/bash -c "exec nginx -g 'daemon off;'"
    
      v1_backend:
        image: example-image1:latest
        expose:
          - "9000"
    
      v2_backend:
        image: example-image2:latest
        expose:
          - "5000"

`v1/nginx.template` is Php Nginx configuration file that's using FastCGI.

    upstream backend {
      server v1_backend:9000;
    }
    
    server {
        listen       80;
        server_name  _;
        root /var/www/html;
    
        location / {
            try_files $uri $uri/ @rewrite;
        }
    
        location @rewrite {
          rewrite ^/(.*)$ /index.php?q=$1 last;
        }
    
        error_page  404              /404.html;
        error_page   500 502 503 504  /50x.html;
    
        location ~ .php$ {
            try_files  $uri =404;
    
            fastcgi_pass   backend;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
            include        fastcgi_params;
    
            fastcgi_max_temp_file_size 0;
    
            fastcgi_buffers 32 256k;
        }
    }

`v2/nginx.template` is Go Nginx template to serve our new v2 API and attaching mirror to feed our V2 API

    upstream v1.backend {
        server v1;
    }
    
    upstream v2.backend {
        server v2_backend:5000;
    }
    
    server {
        listen 80;
        server_name _;
    
        location / {
          mirror /mirror;
          mirror_request_body on;
    
          proxy_pass http://v1.backend;
        }
    
        location = /mirror {
          internal;
    
          proxy_pass http://v2.backend$request_uri;
          proxy_set_header X-SERVER-PORT $server_port;
          proxy_set_header X-SERVER-ADDR $server_addr;
          proxy_set_header X-Original-URI $request_uri;
          proxy_set_header HOST $http_host;
          proxy_set_header X-REAL-IP $remote_addr;
        }
    }

I think it's the basic example of how to achieve the goal by having the primary APP like in my case it was Php application and Go app as V2 API. 

`mirror /mirror;` - is an instruction to use location `/mirror` as the next step to process request than upstream it to v2 backend and we are ready to verify the traffic from the console application.

Once V2 application is working fine we can fully remove the V1 and replace Nginx template by the new version without `mirror`.

Thank you for reading!