0. 背景
一個實際的應用環(huán)境中需要同時部署多個站點,所以選擇同時使用nginx和apache衙解,使用apache web容器同時部署2個站點鲤妥,使用nginx進行轉發(fā)。但由于網(wǎng)站是使用react或vue開發(fā)的苍姜,一個使用了hash router,一個使用的是history router悬包,中途遇到一個問題是當使用的是history路由時,如果當前而在不是index頁面馍乙,瀏覽器刷新后會出現(xiàn)404錯誤
1. 應用運行環(huán)境
操作系統(tǒng):CentOS Linux release 7.6.1810 (Core)
Web容器:Apache/2.4.6 (CentOS)
nginx:nginx/1.16.0
2. Apache多站點部署快捷方法
方法一:同域名下多個站點
本質上仍是一個網(wǎng)站布近,通過二級目錄的方式劃分成2個不同的站點
方法二:不同域名多個站點
本質是是通過Apache的VirtualHost實現(xiàn)垫释,具體配置詳細說明如下:
由于在我的應用環(huán)境中向外是通過nginx做轉發(fā),所以這里說明通過VirtualHost基本端口號實現(xiàn)多站點的配置過程
-
在/etc/httpd/conf/httpd.conf中增加以下內容
Listen 8080 Listen 8090 #以上將在VirtualHost配置中使用 LoadModule rewrite_module modules/mod_rewrite.so #上一行配置的作用在后續(xù)解決刷新404問題中的一步
-
在/etc/httpd/conf.d/下新建host.conf文件撑瞧,文件在配置以下內容
<VirtualHost localhost:8080> ServerAdmin root@localhost ServerName localhost:8091 DocumentRoot "網(wǎng)站A根目錄" DirectoryIndex index.html <Directory "網(wǎng)站A根目錄"> Options Indexes Includes FollowSymlinks AllowOverride All Require all granted </Directory> ErrorLog /var/log/httpd/err_8080.log LogLevel warn CustomLog /var/log/httpd/err_8080_access.log combined </VirtualHost> <VirtualHost localhost:8090> ServerAdmin root@localhost ServerName localhost:8090 DocumentRoot "網(wǎng)站B根目錄" DirectoryIndex index.html <Directory "網(wǎng)站B根目錄"> Options Indexes Includes FollowSymlinks AllowOverride All Require all granted </Directory> ErrorLog /var/log/httpd/err_8090.log LogLevel warn CustomLog /var/log/httpd/err_8090_access.log combined </VirtualHost>
3. nginx轉發(fā)配置
這里假設A網(wǎng)站分配域名為a.me.com棵譬,B網(wǎng)站分配域名是b.me.com
詳細配置如下:
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
underscores_in_headers on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
#將http請求轉發(fā)到https
server {
listen 80;
server_name a.me.com;
return 301 https://$server_name$request_uri;
}
server {
listen 80;
server_name b.me.com;
return 301 https://$server_name$request_uri;
}
# HTTPS server
#
server {
listen 443 ssl;
server_name a.me.com;
root html;
index index.html index.htm;
ssl_certificate 對應域名ssl證書路徑;
ssl_certificate_key 對應域名ssl證書key路徑;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location ~* / {
client_max_body_size 100M;
proxy_pass http://localhost:8080;
add_header Cache-Control 'max-age=0';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location / {
root html;
index index.html index.htm;
}
}
server {
listen 443 ssl;
server_name b.me.com;
root html;
index index.html index.htm;
ssl_certificate 對應域名ssl證書路徑;
ssl_certificate_key 對應域名ssl證書key路徑;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location ^~ /h5/ {
proxy_pass http://localhost:8090;
add_header Cache-Control 'max-age=0';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~* / {
client_max_body_size 100M;
proxy_pass http://localhost:8090;
add_header Cache-Control 'max-age=0';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
client_max_body_size 100M;
root html;
index index.html index.htm;
}
}
}
4.怎么解決問題
在上述配置下使用React或Vue基本history的單頁面路由,當當前頁面不是index頁面時刷新時出現(xiàn)404問題
-
定位產(chǎn)生問題原因
由于同時使用了nginx和apache预伺,如果不確定問題是出在誰身上只能一點點的去試订咸,顯然是沒辦法的辦法。其實從本質上分析nginx是做轉發(fā)工作酬诀,那只要確定問題是不是出在轉發(fā)層面就可以了脏嚷。方法很直接:
由于服務并沒有向外開放8080和8090端口,所以可以直接在服務上通過wget打開一個非index的具體頁面瞒御,如果可以打開那么問題自然是在nginx上父叙,否則是apache配置的問題。
經(jīng)排除發(fā)現(xiàn)問題是在apache端
-
問題解決辦法
第一步肴裙、在apache配置文件中增加以下配置
LoadModule rewrite_module modules/mod_rewrite.so
第二步趾唱、在網(wǎng)站根目錄下新建.htaccess,文件內容如下
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.html [L] </IfModule>