最近遇到的一个小问题,记录了一下解决过程,写出来分享给大家。
背景
因为前段时间买了腾讯云3年的云服务器,准备偶尔写点后台代码放上去。正好最近也在计划写个小程序,用这个云服务器作为后台。但是微信小程序必须要求使用已经备案的域名和80端口,但是只有一台云服务器,一个80端口,如果我想用这台云服务器作为多个小程序的后台,那就不能满足需求了。
想着要是能够将多个子域名都解析到我的云服务器上,然后再通过不同的子域名映射到我云服务器的不同端口,这样,对外看起来是多个子域名并且是80端口,但是其实背后只有一台云服务器。
本来也就是想想,正好有个好朋友最近也遇到了这个需求,就直接准备搞一下,找找具体的解决方法。
解决方案
刚开始的想法是这样的,在我的云服务器上装个Tomcat,然后将Tomcat监听端口从8080改为80。然后自己写个Java Web的程序,接受所有发到80端口的请求,然后再获得请求的子域名,根据不同的子域名转发请求到不同的内部服务的其他端口。但是感觉自己写,可能没法很好地处理,造成性能很低,遂作罢。
然后又上网找了一下其他方案,然后发现了nginx。nginx是一个高性能的HTTP反向代理服务器,关于它的介绍,这里不再赘述,大家可以自行搜索资料了解。这里的nginx服务器可以通过配置,监听80端口,并且可以将80端口的请求根据不同的子域名转发到不同的内部端口,正好满足了我的需求,所以选定了nginx来实现。
具体实施
下面来实战演示整个过程。
演示环境
云服务器使用的是Ubuntu16.04
安装nginx服务器
使用下面的命令安装nginx。
sudo apt install nginx
配置nginx服务器
在安装完nginx服务器以后,nginx的配置文件在/etc/nginx/nginx.conf
,然后我么看到这个配置文件中有这样的一段内容。
http { #...... include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
说明nginx的默认配置文件中包含加载了这两个目录下的配置文件,所以我们可以在/etc/nginx/conf.d/
这个目录下创建以.conf
结尾的文件,在里面配置我们的个性化配置就ok了。
所以我们在/etc/nginx/conf.d/
这个目录下使用vi创建a.conf
和b.conf
来分别表示我们需要解析映射的两个子域名。然后在这两个文件中分别写入下面的内容。
server { listen 80; server_name a.codekong.cn; location / { proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-Ip $remote_addr; proxy_set_header X-NginX-Proxy true; proxy_pass http: proxy_redirect off; } }
其实我们需要关注的就两行内容,下面这一行是表示你要映射处理的子域名,我这里是a.codekong.cn
server_name a.codekong.cn
还有就是下面这行用来表示你将这个子域名的请求转发到服务器的哪个端口进行处理,这里是3000
这个端口。
proxy_pass http:
同样的,我们再配置一下将b.codekong.cn
的请求转发到服务器内部的4000
这个端口,配置文件如下:
server { listen 80; server_name b.codekong.cn; location / { proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-Ip $remote_addr; proxy_set_header X-NginX-Proxy true; proxy_pass http: proxy_redirect off; } }
这样就配置好了。
配置域名解析
下面我们开始配置子域名的解析,分别添加a.codekong.cn
和b.codekong.cn
两个子域名的解析到我自己的云服务器,入下图所示:
我这里解析配置完后缓存会在10分钟后失效,也就是域名解析会在10分钟后生效,大家依据自己的配置来定。
安装NodeJS
到上面这一步其实我们就已经成功了,但是我们下面可以使用NodeJs写一段程序来验证一下,所以必须先按照下面的命令按照NodeJs。
sudo apt install nodejs sudo apt install nodejs-legacy sudo apt install npm
执行完上面的命令就安装好了Node环境,为我们下一步测试做好了准备。
测试验证
我们使用Node来写一段最简单的程序来验证一下,程序如下:
var http = require('http'); http.createServer(function (request, response) { response.writeHead(200, {'Content-Type': 'text/plain'}); response.end('Hello World I am from A server\n'); }).listen(3000); console.log('Server running at http://127.0.0.1:3000/');
var http = require('http'); http.createServer(function (request, response) { response.writeHead(200, {'Content-Type': 'text/plain'}); response.end('Hello World I am from B server\n'); }).listen(4000); console.log('Server running at http://127.0.0.1:4000/');
然后我们先使用下面的命令启动nginx监听80端口
sudo service nginx start
然后我们再使用Node启动我们上面的那段测试代码
node servera.js
然后访问http://a.codekong.cn
就可以看到浏览器输出响应了。然后测试一下另一个子域名也是可以正常响应的。
到这里,我们就已经成功使用nginx实现了单主机多域名映射了。
遇到的问题
整个的探索过程中也遇到了一下问题,这里记录一下。
1. nginx启动失败,报下面的错误信息
Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.
这个最可能的原因是80端口被其他程序占用了,可以使用下面的命令查看占用80端口的程序的名称和PID
sudo lsof -i:80
然后输出下面的信息
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME apache2 18472 root 3u IPv4 12682582 0t0 TCP *:http (LISTEN) apache2 18475 www-data 3u IPv4 12682582 0t0 TCP *:http (LISTEN) apache2 18476 www-data 3u IPv4 12682582 0t0 TCP *:http (LISTEN)
可以看出我这里是apache占用了80端口,所以可以使用命令吧apache停止了即可,也可以使用下面的命令直接把进程杀死
sudo kill -9 [进程PID]
- nginx报启动失败
这次端口没被占用,报错依然是下面的信息
Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.
看不出原因就按错误提示使用下面的命令查看详细的报错信息
sudo systemctl status nginx.service
输出信息如下:
nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled) Active: failed (Result: exit-code) since Wed 2018-09-12 01:07:34 CST; 16s ago Process: 18137 ExecStop=/sbin/start-stop-daemon Process: 18616 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=1/FAILURE) Process: 22450 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=1/FAILURE) Main PID: 22563 (code=exited, status=0/SUCCESS) Sep 12 01:07:34 VM-163-140-ubuntu systemd[1]: Starting A high performance web server and a reverse proxy server... Sep 12 01:07:34 VM-163-140-ubuntu nginx[22450]: nginx: [emerg] socket() [::]:80 failed (97: Address family not supported by protocol) Sep 12 01:07:34 VM-163-140-ubuntu nginx[22450]: nginx: configuration file /etc/nginx/nginx.conf test failed Sep 12 01:07:34 VM-163-140-ubuntu systemd[1]: nginx.service: Control process exited, code=exited status=1 Sep 12 01:07:34 VM-163-140-ubuntu systemd[1]: Failed to start A high performance web server and a reverse proxy server. Sep 12 01:07:34 VM-163-140-ubuntu systemd[1]: nginx.service: Unit entered failed state. Sep 12 01:07:34 VM-163-140-ubuntu systemd[1]: nginx.service: Failed with result 'exit-code'.
然后在错误信息里面看到了下面这句
nginx: [emerg] socket() [::]:80 failed (97: Address family not supported by protocol)
第一反应是IPV6的问题,想起来因为上次在云服务器上安装docker,IPV6存在问题,直接把云服务器的IPV6禁用了,而nginx是默认同时支持IPV4和IPV6协议的,所以我禁用了IPV6就会报错,所以处理办法是禁用掉nginx的IPV6。
但是nginx的IPV6配置在哪里修改呢,看一下我们最开始展示的/etc/nginx/nginx.conf
这个配置文件中的下面这样
include /etc/nginx/sites-enabled/*;
我们在这个目录下发现了一个叫default
的链接文件,它的链接信息可以通过ls -al
查看,信息如下:
default -> /etc/nginx/sites-available/default
然后我们打开这个文件,看到里面的内容是这样的
server { listen 80 default_server; listen [::]:80 default_server; }
其中第二行就是对IPV6的支持,直接注释了,重新启动nginx即可。
总结
上面就是今晚的一个探索过程,记录一下,分享给有需要的人。
原文链接:https://blog.csdn.net/bingjianIT/article/details/82635212