@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;
   }


Но что-то мне это не далось. Прошу, знатоков, помочь с проблемой.
  • Вопрос задан
  • 113 просмотров
Пригласить эксперта
Ответы на вопрос 2
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}, и тогда не будет потенциальных пересечений маршрутов и будет куда проще писать конфиг.
Ответ написан
@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
Ответ написан
Ваш ответ на вопрос

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

Войти через TM ID
Похожие вопросы
SaveTime Москва
от 140 000 до 200 000 руб.
COSMOS Москва
от 120 000 до 150 000 руб.
Foach Санкт-Петербург
от 80 000 до 100 000 руб.