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!
Top comments (3)
Hi Alexandr,
I'm trying to apply the nginx mirror module without success, I did exactly what you did, on the mirror server (v2.backend) I find these errors in the error.log:
failed (2: No such file or directory), which leads me to believe that v2 is unable to mirror the folder "/ usr / share / nginx / html" when it receives requests from "server_name_;"
open () "/usr/share/nginx/html/static/imagem.png" failed (2: No such file or directory)
Hi @cafecraft .
Are you sure that you have
/usr/share/nginx/html/static/imagem.png
file inv2.backend
?It's not mirroring the folder, it mirrors the traffic that's coming to v1 and run it for v2 as well. It means if you serve a static file in your case you should have these files for v1 and v2. in my example v1 and v2 are running as separate containers without sharing resources via volumes. if you want to share folders, you can do it by using
volume:
.Example:
Thanks for the answer, I think I understand ... I thought Nginx automatically mirrored static content as there was traffic, so I have to mirror the content of my v1 (backend) to v2 (mirror), the problem that static content v1 is in Zope / Plone which stores in ZODB database.
EDIT: I am downloading the content with HTTrack