@DiGiTAll

Nginx + GoLang: как разрулить кому что?

Есть небольшой сайт на laravel. Обслуживается Nginx со следующим конфигом:

Текущий конфиг
server {
	server_name mysite.com www.mysite.com;
	charset UTF-8;
	index index.php;
	disable_symmysites if_not_owner from=$root_path;
	include /etc/nginx/vhosts-includes/*.conf;
	include /etc/nginx/vhosts-resources/mysite.com/*.conf;
	access_log /var/www/httpd-logs/mysite.com.access.log;
	error_log /var/www/httpd-logs/mysite.com.error.log notice;
	ssi on;
	return 301 https://$host:443$request_uri;
	set $root_path /var/www/mysite/data/www/mysite.com/public;
	root $root_path;
	listen 185.0.0.0:80;
	location / {
	 try_files $uri $uri/ /index.php?$query_string;
		location ~ [^/]\.ph(p\d*|tml)$ {
			try_files /does_not_exists @php;
		}
	}
	location @php {
		fastcgi_index index.php;
		fastcgi_param PHP_ADMIN_VALUE "sendmail_path = /usr/sbin/sendmail -t -i -f webmaster@mysite.com";
		fastcgi_pass unix:/var/www/php-fpm/mysite.sock;
		fastcgi_split_path_info ^((?U).+\.ph(?:p\d*|tml))(/?.+)$;
		try_files $uri =404;
		include fastcgi_params;
	}
	gzip on;
	gzip_comp_level 2;
	gzip_disable "msie6";
	gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
}
server {
	server_name mysite.com www.mysite.com;
	ssl_certificate "/var/www/httpd-cert/mysite/mysite.com_le1.crtca";
	ssl_certificate_key "/var/www/httpd-cert/mysite/mysite.com_le1.key";
	ssl_ciphers EECDH:+AES256:-3DES:RSA+AES:!NULL:!RC4;
	ssl_prefer_server_ciphers on;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	add_header Strict-Transport-Security "max-age=31536000;";
	ssl_dhparam /etc/ssl/certs/dhparam4096.pem;
	charset UTF-8;
	index index.php;
	disable_symmysites if_not_owner from=$root_path;
	include /etc/nginx/vhosts-includes/*.conf;
	include /etc/nginx/vhosts-resources/mysite.com/*.conf;
	access_log /var/www/httpd-logs/mysite.com.access.log;
	error_log /var/www/httpd-logs/mysite.com.error.log notice;
	ssi on;
	set $root_path /var/www/mysite/data/www/mysite.com/public;
	root $root_path;
	listen 185.0.0.0:443 ssl;
	location / {
	 try_files $uri $uri/ /index.php?$query_string;
		location ~ [^/]\.ph(p\d*|tml)$ {
			try_files /does_not_exists @php;
		}
	}
	location @php {
		fastcgi_index index.php;
		fastcgi_param PHP_ADMIN_VALUE "sendmail_path = /usr/sbin/sendmail -t -i -f webmaster@mysite.com";
		fastcgi_pass unix:/var/www/php-fpm/mysite.sock;
		fastcgi_split_path_info ^((?U).+\.ph(?:p\d*|tml))(/?.+)$;
		try_files $uri =404;
		include fastcgi_params;
	}
	gzip on;
	gzip_comp_level 2;
	gzip_disable "msie6";
	gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
}

При этом все возможные роуты на сайте известны и вряд ли будут изменяться.
Допустим такие:
  • mysite.com/
  • mysite.com/index.php
  • mysite.com/admin/*
  • mysite.com/blog/*
  • mysite.com/static_page_1
  • mysite.com/articles/category/*


Это всё работает отлично. Но ситуация осложнена. По адресам вида mysite.com/[a-zA-Z0-9]{2,7} идёт очень много (до 2-3К RPS с обращениями в базу) специфического трафика, который нужно обрабатывать. Под каждый запрос "запускать" Laravel совсем не вариант.
И производительность падает до неприличия, и железо всё задействуется. Для решения задач был написан небольшой
сервер на golang, который слушает 8181 порт на том же сервере. Он ожидает данные по адресу 185.0.0.0:8181/?data=[a-zA-Z0-9]{2,7} и молниеносно их обрабатывает. Т.е. проблема с производительностью решилась.
Осталось подружить Nginx, Laravel и Go.

Т.е. Nginx должен "отобрать" все роуты Laravel (они заранее известны, меняться если будут, то крайне редко), а остальное "пропустить" дальше. Адреса остального (те самые mysite.com/[a-zA-Z0-9]{2,7}) нужно отправить на обработку решением на Go.

Попробовал разные варианты с конструкциями типа:

location @go-server {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_pass http://185.0.0.0:8181;
   }


Но что-то мне это не далось. Прошу, знатоков, помочь с проблемой.
  • Вопрос задан
  • 187 просмотров
Решения вопроса 1
@ghostiam
На Go писатель, серверов пинатель.
добавить перед `location / {`
location ~ "^/([a-zA-Z0-9]{2,7})$" {
	proxy_set_header X-Real-IP $remote_addr;
	proxy_pass http://185.0.0.0:8181/?data=$1;
}


либо

location ~ "^/([a-zA-Z0-9]{2,7})$" {
	try_files /does_not_exists @go-server;
}

location @go-server {
	proxy_set_header X-Real-IP $remote_addr;
	proxy_pass http://185.0.0.0:8181/?data=$1;
}


5c34dee16cecb533160256.png
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
kotomyava
@kotomyava
Системный администратор
location ~* ^/[a-z0-9]{2,7}$ {
  proxy_set_header X-Real-IP $remote_addr;
  proxy_pass http://185.0.0.0:8181;
}


Также, могут понадобиться локейшен(ы) выше этого, если есть url, которые укладываются в эту регулярку, но не должны обрабатываться go обработчиком. Из вашего сообщения туда влезают только /admin и /blog:

location ~* ^/(admin|blog) {
  try_files $uri $uri/ @backend;
}


Важно: Это пример показывающий подход, а не окончательный конфиг.

А вообще, лучше сделать префикс, чтобы url go обработчика начинались с его, например: mysite.com/go/[a-zA-Z0-9]{2,7}, и тогда не будет потенциальных пересечений маршрутов и будет куда проще писать конфиг.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Social Systems Москва
от 50 000 до 100 000 руб.
Social Systems Москва
от 80 000 до 160 000 руб.
SaveTime Москва
от 160 000 руб.
20 марта 2019, в 01:07
1000 руб./за проект
20 марта 2019, в 00:27
2000 руб./за проект
19 марта 2019, в 23:14
6000 руб./за проект