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 ).
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!