从零开始部署小程序服务器(腾讯云)

从零开始部署小程序服务器(腾讯云)

话说目前云已经很便宜了,腾讯有一个月的试用期,不过阿里云也有,而且对于学生认证的用户 9.9元一个月的最低配置,这让 Lefe 才有可能尝试配置一个线上的服务器。从一个小白开始,感觉都是新的东西,有时候碰到问题,很难,无从下手,不过通过网上的各种资料最终都解决了,下面主要讲一讲过程,这些知识对于服务器端的同学来说,应该很简单,但我只想记录下这一路走来所经历的!

服务器是什么

服务器是什么?啥,你竟然不知道服务器是啥,你每天都和服务器打交道。以 lefe 自己的理解,服务器和本地一台笔记本差不多,所以配置服务器也就是和配置本地的环境差不多,唯一不同的是各种操作,都需要终端命令来替代我们的图形化界面,比如建立文件夹,下载,解压等等。

购买腾讯云

到腾讯云官网上购买【云服务器CVM】,购买后分派两个ip地址,公网和内网的。我们做一些配置基本都是基于外网ip。Lefe 购买的是 Ubuntu

外网IP,就是公网IP,可以给外面人用的,例如做网站,或给其它人下载等。
肉网IP,就是局网IP,如果你有几台以上的云主机,可以局网传输数据,局网传输数据不占用外部带宽限制,传输大文件速度会快很多很多。

配置服务器

一、如何登录到服务器:

我已经有ip地址了,可是我咋么才能登录到服务器上,来配置我们的环境呢?这里一般官方文档到会有写,不过一般写的比较粗略,对于我这个小白用户来说,看不太明白。这里主要介绍一种登录方式:
ssh的方式登录,这种方式相信很多同学都见过,比如 git。它需要把一台PC上生成的公钥传到服务器后台(腾讯云后台管理中心),这样服务器就可以信任当前的PC了。

  • PC端生成公钥:
    打开终端输入:ssh-keygen , 一路回车,这时会生成一个公钥和一个私钥;
  • 终端输入:cat .ssh/id_rsa.pub,复制公钥,上传到腾讯云后台管理中心;
  • 终端输入:ssh ubuntu@118.89.23.181,ubuntu 这个会管理员账号,不同系统可能会不同,比如有的是 root,阿里云好像都是 root,118.89.23.181 这个是公网的 ip 地址。

登录成功后,你就可以随心所欲了,不要怕搞坏哦,终端显示如下:

很简单吧,这样就可以登录到服务器上了。这里 lefe 推荐终端软件 iTerm

注意:下面所讲到的都是基于登录到服务器后的操作。

二、安装 Node.js

主人公该上场了,有个 Node 我们才能开启我们基本的 Http 服务。

终端输入:
curl -sL https://deb.nodesource.com/setup | sudo bash -
sudo apt-get install nodejs

报错:
The program 'node' is currently not installed. You can install it by typing:
sudo apt install nodejs-legacy

执行下面语句:
sudo apt install nodejs-legacy

终端输入:
node -v ,查看你所安装 Node的版本号;

嗯,这样 Node 就安装好了,还记得你第一安装 Node 吗?

三、开启 Node 服务

这时候需要把 Lefe 写好的 Node 服务克隆到服务器上,想想当你刚接触 git 的时候,你是如何把 github 上的代码克隆到自己电脑上的,如果是别人帮你弄的,lefe 建议读者自行实践一下。

  • 生成一个公钥,和登录时的生成方式一样,只不过这里是在服务器上生成的
  • 把生成好的公钥上传到 git 服务器上
  • 执行 git clone https://github.com/iMetalk/TCZNodeServer

当然 lefe 这时候克隆的是一个自己写好的 Node;

克隆后在服务器上的目录为:

/home/ubuntu/nodeserver/WJCar_node

  • 执行 node app.js,这样服务就起来了。

Lefe:哎,不对哦,我有数据库啊,好吧,还需要安装数据库,不然我的数据从哪来?搞个假数据,你这也能想的出来。

四、安装 mongodb

Lefe:咋么安装呢?呵呵,都是 linux 系统,记得本地以前配置过,哎对了,以前还写过一片博客,翻了翻以前的博客,哎真有啊,开心坏了。不一会就安装好了。可以参考这篇文章
Mongodb安装

关了几次终端,出现了一个问题:

ubuntu@VM-68-186-ubuntu:/usr/local/mongodb/bin$ ./mongod --dbpath=/usr/local/mongodb/data/db/
2017-05-14T11:09:50.823+0800 I CONTROL  [initandlisten] MongoDB starting : pid=21537 port=27017 dbpath=/usr/local/mongodb/data/db/ 64-bit host=VM-68-186-ubuntu
2017-05-14T11:09:50.826+0800 I CONTROL  [initandlisten] db version v3.2.9
2017-05-14T11:09:50.826+0800 I CONTROL  [initandlisten] git version: 22ec9e93b40c85fc7cae7d56e7d6a02fd811088c
2017-05-14T11:09:50.826+0800 I CONTROL  [initandlisten] OpenSSL version: OpenSSL 1.0.2g  1 Mar 2016
2017-05-14T11:09:50.826+0800 I CONTROL  [initandlisten] allocator: tcmalloc
2017-05-14T11:09:50.826+0800 I CONTROL  [initandlisten] modules: none
2017-05-14T11:09:50.826+0800 I CONTROL  [initandlisten] build environment:
2017-05-14T11:09:50.826+0800 I CONTROL  [initandlisten]     distmod: ubuntu1404
2017-05-14T11:09:50.826+0800 I CONTROL  [initandlisten]     distarch: x86_64
2017-05-14T11:09:50.826+0800 I CONTROL  [initandlisten]     target_arch: x86_64
2017-05-14T11:09:50.826+0800 I CONTROL  [initandlisten] options: { storage: { dbPath: "/usr/local/mongodb/data/db/" } }
2017-05-14T11:09:50.880+0800 E NETWORK  [initandlisten] listen(): bind() failed errno:98 Address already in use for socket: 0.0.0.0:27017
2017-05-14T11:09:50.882+0800 E NETWORK  [initandlisten]   addr already in use
2017-05-14T11:09:50.882+0800 E STORAGE  [initandlisten] Failed to set up sockets during startup.
2017-05-14T11:09:50.882+0800 I CONTROL  [initandlisten] dbexit:  rc: 48

这下坏了,纠结啊!!!看了看错误,好像是某个端口已经被占用了,98 Address already in use for socket: 0.0.0.0:27017,别怕 Google一下吧,果然很多人遇到了同样的问题,绕了一圈,最终得以解决。这种情况一般是不正常的退出 Mongodb 导致的。简单粗暴:sudo killall mongod,直接杀掉。

哈哈,大功告成了,正高兴这呢。哎不对呀,如果我把终端关闭了,那我 Node 服务就死了,那还要服务器干吗呢?突然脑海中浮现出一个 PM2(你咋这么聪明呢,我咋只知道 PM2.5),这个家伙经常听后台的同学说,我一开始还以为是 pm2.5呢?抱着试一试的心态,Google 了一下,太神奇了,原来 PM2 就是解决这个问题的。

五、PM2 安装

看了看 官方文档 很快就安装好了,原来它可以使用 NPM 安装。

试一试吧:就是把 node app.js 换成 pm2 start app.js

原来看到后端同学屏幕上显示的原来就是这个东西。呀!不对呀,那我 mongodb 数据库关闭终端后也就会被挂起了,是不也可以使用 PM2 呢?最终发现不可以,那咋么办呢?估计和这个原理差不多,也开启一个守护进程。果不其然,启动 mongodb 还有其他的一种方式:

sudo mongod --fork --dbpath=/usr/local/mongodb/data --logpath=/usr/local/mongodb/logs/mongodb2.log --logappend

Lefe 开心的登录微信小程序后台,哎,不对,微信小程序必须使用域名而不是ip地址,好吧,只好妥协了,申请一个域名吧。

六、申请域名

都这么贵,.com, .cn,那就找一个最便宜的吧,哎有一个,lefe.wang,这个不错,天意呀,lefe 我的笔名,wang 我的姓,果断就选它了,登录腾讯云后台解析了下,很快的我的接口可以使用域名访问了。把域名配置到小程序后台,哎,不对呀,人家要求的是 https 的,这下悲剧了,好吧,我妥协。

七、HTTPS 配置

Lefe 记得自己的后台不支持 Https,赶快支持一下吧。且慢,我还没有 https 证书呢,咋么让我的 Node 服务支持 Https 呢,自签名的腾讯肯定不可以,果断放弃了这种自签名的方式。Google 了一下免费的 Https 证书,收费的真的太贵了。哎,不错,有免费的,最终选择了腾讯云免费的 https证书,这里有一个坑,使用域名申请证书的时候要用与 ip 地址绑定的那个子域名而不是根域名。比如 lefe 申请的根域名是 lefe.wang,与 ip 绑定的是 wqjp.lefe.wang,那么申请 Https 证书要用域名 wqjp.lefe.wang ,证书也有了,开始配置服务器了,代码如下:

var express = require('express');
var bodyparser = require('body-parser');
var router = require('./router.js');
var mongodb = require('./db/mongodb.js');
var fs = require('fs');
var https = require('https');
var http = require('http');

var app = express();
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({
    extended: true
}));

var privateKey  = fs.readFileSync('./res/2_wqjp.lefe.wang.key', 'utf8');
var certificate = fs.readFileSync('./res/1_wqjp.lefe.wang_bundle.crt', 'utf8');
var credentials = {key: privateKey, cert: certificate};

var httpsServer = https.createServer(credentials, app);
var httpServer = http.createServer(app);

var SSLPORT = 4000;
var PORT = 4001;

var routeCB = function routeCallBack(req, res, next){
    if(req.url=="/favicon.ico"){
        res.end();
    }
    else
    {
        next()
    }
}

var dealCB = function  dealCallBack(req, res){
    // 解析post参数
    router.routed(req, res)
}

app.all('*', [routeCB, dealCB]);

// app.listen(4000);

httpsServer.listen(SSLPORT, function() {
    console.log('HTTPS Server is running on: https://localhost:%s', SSLPORT);
});

httpServer.listen(PORT, function() {
    console.log('HTTP Server is running on: http://localhost:%s', PORT);
});

Lefe 打开小程序编辑器,模拟器数据一切请求正确,没问题,用真机预览一下吧,啊,咋么没数据呢,后台也没报错啊!到小程序论坛上查了查,不能使用端口。我说呢,我的请求和服务端的同学不一样呢。我的请求是 https://wqjp.lefe.wang:400/api/store/get,请求本应该是 https://wqjp.lefe.wang/api/store/get 没端口,这可咋办呢?Google 了一下,可以使用 Nginx,啥 Nginx,一直听到后端的同学在说,没想到我也能用到,好吧,我妥协!

八、配置 Nginx

Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。Nginx是由Igor Sysoev为俄罗斯访问量第二的Rambler.ru站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev所开发,供俄国大型的入口网站及搜索引擎Rambler(俄文:Рамблер)使用。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

好吧,一字一句看了,还是不懂。Lefe 的理解是,它可以把你的请求根据不同的需要请求到不同的服务器上。它的作用就是反向代理和负载均衡,不明白也没关系。继续往下看吧。

安装 Nginx:

  • gcc、g++依赖库
    apt-get install build-essential apt-get install libtool

  • 安装 pcre依赖库(http://www.pcre.org/
    sudo apt-get install libpcre3 libpcre3-dev

  • 安装 zlib依赖库(http://www.zlib.net
    apt-get install zlib1g-dev

  • 安装
    cd /usr/local/src wget http://nginx.org/download/nginx-1.4.2.tar.gz tar -zxvf nginx-1.4.2.tar.gz cd nginx-1.4.2

  • ./configure
    --sbin-path=/usr/local/nginx/nginx
    --conf-path=/usr/local/nginx/nginx.conf
    --pid-path=/usr/local/nginx/nginx.pid
    --with-http_ssl_module
    --with-pcre=/opt/app/openet/oetal1/chenhe/pcre-8.37
    --with-zlib=/opt/app/openet/oetal1/chenhe/zlib-1.2.8
    --with-openssl=/opt/app/openet/oetal1/chenhe/openssl-1.0.1t

  • make

执行完一大堆后,就算安装完成了。那么如何才能 让https://wqjp.lefe.wang:400/api/store/get的请求指向https://wqjp.lefe.wang/api/store/get。只能修改配置文件了。Lefe 的配置文件如下,它同时支持 http 和 https。安装完后的 Nginx 在 /usr/local/ 目录下,找到配置文件 /usr/local/nginx/conf/nginx.conf,编辑这个配置文件,在编辑配置文件时,有几个坑需要注意一下:

  • # 是配置文件的注释,所以有些地方需要去掉
  • server_name 不需要加前缀,比如 httphttps
  • proxy_pass 需要是一个完整的地址,包含 httphttps
  • 修改完配置文件一定要重启,lefe 不知道从那个地方看到,说nginx -s reload这个可以重启,可把我害惨了,一直以为是配置文件的问题,原来是没有重启,重启用这个 sudo nginx -c /usr/local/nginx/conf/nginx.conf
  • 如果报pid错误,使用 Nginx killall -9 nginx 来解决
#user  nobody;
worker_processes 1;
#pid        logs/nginx.pid;
events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;
    server {
       listen       80;
       # 这个是你所申请的域名
       server_name  wqjp.lefe.wang;
       location / {
           root   /home/ubuntu/nodeserver/WJCar_node/WJCar;
           index  app.js;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header Host $http_host;
           proxy_set_header X-NginX-Proxy true;
           proxy_pass http://127.0.0.1:4001;
           proxy_redirect off;
        }
   }

    # HTTPS server
    server {
        listen 443;
        server_name wqjp.lefe.wang;
        ssl on;
        # 申请https证书的位置
        ssl_certificate /home/ubuntu/nodeserver/WJCar_node/WJCar/res/1_wqjp.lefe.wang_bundle.crt;
        # 申请https公钥的位置
        ssl_certificate_key /home/ubuntu/nodeserver/WJCar_node/WJCar/res/2_wqjp.lefe.wang.key;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
        ssl_prefer_server_ciphers on;
        location / {
           root   /home/ubuntu/nodeserver/WJCar_node/WJCar;
           index  app.js;
           proxy_redirect off;
           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_pass https://118.89.23.181:4000;
        }
    }
}

恭喜你完成了!呀,这就完成了,嗯,是的,这下用真机预览,就可以看到漂亮的界面了。想看吗?等等给你看!!!

结尾

写了这么多,也没看到小程序长上样,可以看看吗?好吧,满足你们,放几张漂亮的图,长的丑吗?还好吧,感觉没那么垃圾吧,虽然是小白设计,但是有 sketch 这款强大的设计软件,让 lefe 少走很多弯路。

IMG_0851.PNG
IMG_0852.PNG
IMG_0853.PNG

总结

第一次部署服务器,一步一步下来,花了不少时间,几乎用光了我所有的业余时间,从产品的需要,到设计,到切图,到服务器,到小程序。可以说是经历了一个软件开发的大部分过程。也体会到了工作中各个部门的难处,所以工作中我们需要体谅别人,不要只耕自己的一亩三分地,出现问题找各种理由。作为一个小白,难免会有不得当的地方,有什么问题欢迎反馈,谢谢。

参考

Node配置

===== 我是有底线的 ======
喜欢我的文章,欢迎关注我的新浪微博 Lefe_x,我会不定期的分享一些开发技巧

推荐阅读更多精彩内容