腾讯云(CentOS)下的Web应用环境搭建(JDK+Tomcat+PostgreSQL+Nginx)

最近在帮别人做微信小程序,需要一台服务器做后端,正好腾讯云有优惠,并且跟小程序都是一家子,所以选用了腾讯云服务器(CVM)

前言

微信小程序服务目标人群固定,短期内访问量不是很大,预测瞬时最高并发量120左右,所以云服务器选择了一款面向开发者的专惠套餐,1核/2G内存/1Mbps带宽/50G存储,操作系统CentOS7.6。完成在线实验任务,可升级到4G内存,完成Web业务验证任务,可升级到2M带宽。另外还有邀请好友免费续费活动,这个可能就比较难完成了。

小程序后端开发的是Java Web应用,在tomcat上运行,数据库选用PostgreSQL,并安装PostGIS插件用于地理位置计算。使用Nginx做代理,一是可以反向代理到tomcat,并且可配置负载均衡,二是可以直接代理静态资源文件。

所以罗列了一下需要安装及配置的内容:
1、JDK
2、Tomcat
3、PostgreSQL
4、PostGIS
5、Nginx

另外,微信小程序要求后端服务器必须通过htpps域名访问,并且必须ICP备案,所以域名申请和解析,ssl证书的申请,ICP备案这些都是必须的。索性腾讯云这方面的服务比较到位,去相应的页面操作即可,这里就不详述了。(备案周期比较长,建议域名申请后立即做备案,因为备案的时候根本不关心你的网站做没做好,有什么内容,而且备案时明确要求暂停或关闭域名解析的)

如果本地电脑系统是Windows,建议使用WinSCP软件连接云服务器,上传/下载文件很方便。

下面主要阐述一下服务器环境的搭建步骤及方法。

JDK的安装

选用yum的方式安装jdk比较简单方便,不需要配置环境变量,至少本人亲测没问题,搭配tomcat启动Web应用服务一切正常。

  • 查找jdk版本。
yum search java|grep jdk
  • 选择适合的版本进行安装(本例选择1.8版)。
yum install -y java-1.8.0-openjdk
  • 验证,出现下图即算完成。
java -version
  • 如果想配置环境变量,建议把devel一起安装。
yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel
  • JDK默认安装路径/usr/lib/jvm,安装完成后该目录下应该有如下图所示的内容。
  • 配置环境变量,在/etc/profile文件尾部添加如下代码。(如果不熟悉VI,比如我,建议使用WinSCP将profile文件下载到本地编辑后再上传)
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64
PATH=$PATH:$JAVA_HOME/bin  
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar  
export JAVA_HOME  CLASSPATH  PATH 
  • 保存后执行
source  /etc/profile

Tomcat的安装

  • 添加用户组。
groupadd tomcat
  • 添加一个用户tomcat 并分配到组tomcat,设置其home目录为/home/tomcat,并且这个用户为非登录用户。
useradd -s /bin/nologin -g tomcat -d /home/tomcat tomcat
  • 进入https://tomcat.apache.org/download-90.cgi页面,选择Binary Distributions(二进制发行版)下的Core(核心)下的tar.gz的压缩文件,复制其下载地址,用wget命令在CentOS终端下载。
wget -c http://mirror.bit.edu.cn/apache/tomcat/tomcat-9/v9.0.29/bin/apache-tomcat-9.0.29.tar.gz
  • 把下载的内容解压到 /home/tomcat 里。
tar -zxvf apache-tomcat-9.0.29.tar.gz -C /home/tomcat --strip-components 1

-C 选项的作用是:指定需要解压到的目录。
--strip-components 1 提取下一级目录。

  • 为 /home/tomcat/bin/catalina.sh 生成链接。
ln -s /home/tomcat/bin/catalina.sh /etc/init.d/tomcat
  • 编辑 /etc/profile 将 /home/tomcat 目录添加到环境变量中。
export CATALINA_HOME=/home/tomcat
  • 保存后执行
source /etc/profile
  • 把目录/home/tomcat/的own权限分配置给tomcat组的tomcat用户。
chown -R tomcat:tomcat /home/tomcat/
  • 修改/home/tomcat/webapps/manager/META-INF/context.xml文件,注释掉其中的Valve标签(非必须,如果想使用tomcat管理页面需设置)。
  • 修改/home/tomcat/conf/tomcat-users.xml,增加如下配置(非必须,如果想使用tomcat管理页面需设置)。
  • 现在就可以通过/etc/init.d/tomcat 来启动了,如下三种命令皆可,指定tomcat用户来启动,防止tomcat删除你整个硬盘里的东西(后一个-u参数一定要带,不然java web应用程序启动会报权限不足拒绝访问的错误,这是我遇到的一个很大的坑
sudo -u tomcat /home/tomcat/bin/catalina.sh start -u -security
sudo -u tomcat /etc/init.d/tomcat start -u -security
sudo -u tomcat service tomcat start -u security

这里有个坑,CentOS非root用户不能启动1024以内的端口,所以如果tomcat使用80、443这样的端口,则必须用root用户启动tomcat,不能使用上述的tomcat用户启动,否则80、443不会被监听到。
换而言之,使用80、443端口,则上述安装过程中创建tomcat用户组/用户等的步骤都可以不做。
可以使用下述命令查看操作系统当前各端口的监听状态。

netstat -tunlp
  • 停止tomcat服务使用下面的命令
sh /home/tomcat/bin/shutdown.sh
  • 监控日志命令(Ctrl+C退出,实时监控可以用这个命令,如果想看得更全还是下载下来更好)
tail -f /home/tomcat/logs/catalina.out
  • tomcat启动后,可以通过下面的命令来查看tomcat监听的端口,一般是8009:与其它http集成可能用到的端口;8080:web访问端口;8005:监听关闭tomcat的端口。
netstat -napt |grep java |grep LISTEN
  • ssl的配置

1、将证书下载后解压缩,把其中tomcat文件夹下的 www.domain.com.jks 文件上传到 /home/tomcat 目录下;
2、修改 /homt/tomcat/conf/server.xml 文件:

    <Connector port="80" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="443" />
    <Connector port="443" protocol="HTTP/1.1"
            maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
            clientAuth="false"
             keystoreFile="www.domain.com.jks"
             keystorePass="40te94si4u5f20x" />

2.1、80端口的redirectPort修改成443,
2.2、新添加443端口的设置,其中keystoreFile的内容是上传的那个jks文件的文件名,可以是绝对路径也可以是相对路径,相对路径是相对于CATALINA_HOME的路径,keystorePass的内容是证书解压缩后tomcat目录里keystorePass.txt文件的内容;
3、重启tomcat即可。

  • Tomcat9简单的安全设置

1、隐藏版本号
mkdir -p /home/tomcat/lib/org/apache/catalina/util
vi /home/tomcat/lib/org/apache/catalina/util/ServerInfo.properties 添加下面内容
server.info=version
然后重启tomcat就可以了
2、修改/home/tomcat/conf/server.xml 中<Server port="8005" shutdown="SHUTDOWN">这个配置中的port值及shutdown值;port指定的是指定Tomcat监听shutdown命令端口,shutdown指定终止Tomcat服务器运行时,发给Tomcat服务器的shutdown监听端口的字符串;为了安全起见。不要使用默认值;如修改成下面的内容
<Server port="8303" shutdown="god_bless_me_have_no_longer_bug">
记住一定要在你没有启动tomcat的情况修改
3、在自己的web应该中尽量替换默认的404,403,500页面
4、尽量在启动脚本后加-security 增加安全管理;如
/home/tomcat/bin/catalina.sh start -security
5、尽量不要用root用户启动tomcat(对于想用80、443端口,则必须root启动)

  • 关于tomcat正常启动后,网站无法访问的排查办法。

1、确认域名解析是否正确;
2、安全组设置是否正确(要开放tomcat中设置的访问监听端口)。
3、确认端口是否被监听(非root用户启动tomcat后,80、443等端口就不会被监听);
4、确认网站是否完成ICP备案(不备案80、443端口无法访问,但用ip地址可以)。

重要的事情我只说一遍,上述第三和第四点是我遇到的最大的坑。

  • tomcat项目部署的三种方式:

1、直接把项目复制到Tomcat安装目录的webapps目录中,这是最简单的一种Tomcat项目部署的方法,缺点是只能通过 http://www.domain.com/项目目录名 访问。
2、修改/home/tomcat/conf/server.xml,在<host>和</host>之间加入如下代码

<Context docBase="newwebapp" path="/nwa" debug="0" reloadable="true" />

此时可以通过http://www.domain.com/nwa 访问,docBase是项目路径,可以是绝对路径,也可以是相对于Host中的appBase设置的目录的相对路径;path是访问路径,如果想让域名直接访问该项目,则path设置成"/"即可。
3、在 /home/tomcat/conf/Catalina/localhost 下新建一个nwa.xml文件(文件名即是访问路径,如果跟内容中的path不一致,tomcat还是会以文件名作为访问路径的,所以感觉Context里的path没什么用),编辑内容如下:

<Context path="/nwa" docBase="newwebapp" debug="0" privileged="true" />

第二和第三种方法比较灵活。第三种方式如果想设置成根目录访问,则xml文件名必须叫ROOT.xml。

  • 如果应用中有图片/文件上传功能,记得这几个方面需要考虑到:

1、Tomcat 以 tomcat 用户身份启动时,保存上传资源的目录一定要对tomcat赋予足够的操作权限。

chown -R tomcat:tomcat /home/webapps/

2、修改 Tomcat 安装根目录下的 /bin/catalina.sh 文件,将下面的代码普片段中的 UMASK 的值 0027 改成 0022 ,否则上传成功后,nginx 无法访问(不用nginx直接代理该资源文件时这个可以不设置)。

# Set UMASK unless it has been overridden
if [ -z "$UMASK" ]; then
    UMASK="0027"
fi
umask $UMASK

3、nginx 默认允许客户端请求数据大小是1M,如果允许上传文件大小大于该数值,记得修改 nginx 的改项配置,否则请求在 nginx 这一层就会被拦下。

client_max_body_size 20M;

PostgreSQL

  • 上述步骤完成后,默认会创建一个名为postgres的linux登录用户,这里进行密码修改。
passwd postgres
  • 编辑 /var/lib/pgsql/12/data/postgresql.conf 文件的远程连接信息,让所有计算机能访问到该测试数据库;去掉下图的#,修改localhost为*后保存(vi命令:wq)。
  • 同样对 /var/lib/pgsql/12/data/pg_hba.conf 文件进行编辑;追加下图红框内的一行数据,修改黄框的内容后保存。
  • 重启服务:
systemctl restart postgresql-12
  • 用postgres账号登录centos服务器,并修改数据库用户密码(或者直接 su postgres 切换过去)
psql -U postgres
\password
  • 用客户端连接测试即可。

  • PostgreSQL相关的补充:

1、别忘记安全组中开放5432端口,即便该数据库紧供同台服务器上的web应用以localhost方式访问,也需要开放5432端口,原因未知(懒得发工单问腾讯技术人员了,之前tomcat的问题已经被折磨疯了)。

  • 自动备份数据库
    在 /usr/pgsql-12/bin 目录下面创建 backup.sh 文件,内容如下:
#!/bin/bash
cur_time=$(date +%Y%m%d_%H_%M_%S);
/usr/pgsql-12/bin/pg_dump -h 127.0.0.1 -p 5432 -U postgres -F c -b -v -f /home/dbbackup/dbase_backup_$cur_time.dmp yourdbname;

同时创建目录 /home/dbbackup 作为备份文件存放路径。
启动cron服务:

# 查看服务状态
systemctl status crond
# 启动
systemctl start crond
# 停止
systemctl stop crond
# 重启
systemctl restart crond
# 重新加载
systemctl reload crond

开机自动启动cron服务

systemctl start crond.service

进入编辑模式

crontab -e

添加执行 backup.sh 任务

#每天2:30分执行
30 2 * * * /usr/pgsql-12/bin/backup.sh

保存退出

:wq

查看定时任务列表

crontab -l

查看定时任务执行日志

cat /var/log/cron

PostGIS

  • 因为需要在数据库层面进行地理位置坐标之间的距离计算,所以需要安装PostgreSQL的一个相关的扩展PostGIS

  • 查找合适的版本。

yum search postgis|grep postgis
  • 因为之前安装的PostgreSQL的版本是12,所以选择12版对应的最新版postgis,即postgis30_12.x86_64。
yum install postgis30_12.x86_64
  • 如果安装过程中出现缺少依赖包的问题,可以先执行下面语句安装依赖包。
rpm -ivh ftp://bo.mirror.garr.it/1/slc/centos/7.6.1810/extras/x86_64/Packages/epel-release-7-6.noarch.rpm
  • 为始数据库可用PostGIS,需在该数据库上执行下列语句,我是用pgAdmin连数据库执行的,这里有个坑,该数据库一定要有public这个shema,因为要在public下创建一些表。
CREATE EXTENSION postgis;
CREATE EXTENSION postgis_topology;  # 这句不执行对于我的业务来说没影响,我只用距离计算这个功能。
  • 测试,能正确返回数据表示成功能。
select ST_distance(ST_GeomFromText('POINT(121.2309 39.1823)', 4326)::geography, ST_GeomFromText('POINT(121.2319 39.1811)', 4326)::geography);

Nginx

  • 使用 yum 命令安装 Nginx
yum install -y nginx
  • 设置 Nginx 开机启动
systemctl enable nginx.service
  • 启动Nginx
nginx

此时,访问 http://主机ip地址 可以看到Nginx的默认页。

  • 配置文件 /etc/nginx/nginx.conf 里定义了80端口的默认配置,可以直接修改该文件,也可以在 /etc/nginx/conf.d 目录下新建 *.conf 文件进行自定义配置。我选择后一种方式,这样感觉更清晰些。

  • 到 SSL 控制台下载证书文件,将解压缩后的 Nginx 文件夹下的两个文件上传至 /etc/nginx 目录下,

  • 新建 ssl.conf 文件,编辑好后上传至 /etc/nginx/conf.d 目录,配置示例如下:

upstream tomcatweb {
    server localhost:8443;
}

server {
    listen 80;
    server_name www.domain.com; # 改为绑定证书的域名
    rewrite ^(.*)$ https://${server_name}$1 permanent;
}

server {
    listen 443 ssl;
    server_name www.domain.com; # 改为绑定证书的域名
    ssl_certificate 1_www.domain.com_bundle.crt; # 改为自己申请得到的 crt 文件的名称
    ssl_certificate_key 2_www.domain.com.key; # 改为自己申请得到的 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;
    client_max_body_size 20M;

    location / {
        proxy_pass https://tomcatweb/yourapp/;
        proxy_cookie_path /yourapp/ /;
        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 /yourapp/ {
        proxy_pass https://tomcatweb/yourapp/;
        proxy_cookie_path /yourapp/ /;
        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 /resource/ {
        root /home/webapps/yourapp;
    }

    location /yourapp/resource/ {
        root /home/webapps;
    }
}

这个配置文件主要做了一下几件事:
1、监听80端口,重定向到443端口;
2、监听443端口,配置ssl证书,需要注意的是“ssl_certificate”和“ssl_certificate_key”这两个设置,可以使用绝对路径也可以使用相对路径,若是相对路径,则是相对 /etc/nginx 目录的路径;
3、/resource/ 下的文件都是静态文件,这里做了设置,nginx直接代理;
4、上例中的静态资源配置,如果访问地址是 https://www.domain.com/resource/test.jpg 则nginx会按照配置找 /home/webapps/yourapp/resource/test.jpg 文件,注意这里是把root的值和location的值拼在一起;
5、upstream 的配置,将来如果是多Tomcat服务器的话,直接在这里加新地址即可,可实现负载均衡;
6、注意upstream配置的命名,如果带下划线,写成tomcat_web,跳转到tomcat9时会报错”java.lang.IllegalArgumentException: The character [_] is never valid in a domain",Tomcat7好像不会,所以为了避免不必要的问题出现,这里就不要使用下划线命名了;
7、proxy_pass 如果是设置到某个具体的应用下(比如上例),则最后一定要加“/”这个符号,不加会有问题,至于为什么我没调查;
8、像上例这样反向代理到具体某个应用时,location /yourapp/ 这个一定要设置,不然应用内不的相对路径加载资源文件等会找不到(因为Nginx只设置跟路径解析,应用内部相对路径引用的文件地址会解析成www.domain.com/yourapp/yourapp/.)。

  • 修改配置完成后,重启 nginx 服务
nginx -s reload
  • 使用 https 协议访问你的域名, 如 https://www.domain.com 检查是否成功,如果地址栏出现绿色带安全字样的锁头标志,说明 SSL 配置成功。

  • 补充一点,有一次重启系统后,发现直接访问 tomcat 正常,但访问 nginx 返回502错误,查看 nginx 错误日志文件,发现报 connect() to [::1]:8080 failed (13: Permission denied) while connecting to upstream, client: 错误,解决方案是查看系统 httpd 配置,

getsebool -a | grep httpd

设置httpd可以连接到网络

setsebool httpd_can_network_connect on -P

写在最后

整个安装过程其实比较简单,除了PostgreSQL耗时有点长,其它软件安装速度很快。
配置上则需要看具体需求了,其实只使用Tomcat我觉得也完全可以,但这次用Nginx+Tomcat,算是一种尝试吧,主要考虑用Nginx实现动静分离,至于负载均衡暂时还用不上。
另外Nginx+Tomcat的方式,我这次是两边都采用https协议,其实也可以只Nginx实现https,而Tomcat仍旧使用http协议。

最后的最后,给新建网站的朋友一个建议,一定要先申请域名做ICP备案,备案周期真的比较长,不要像我这样万事俱备苦等审核结果。

后期补充

运维过程中需求变更,某个小程序页面有使用WebSocket的应用场景,简化开发及运维成本,选用Node.js构建了WebSocket服务器,接下来补充一下Node.js相关的环境搭建。

Node.js

  • 添加 Node.js Yum 存储库
yum clean all && yum makecache fast
yum install -y gcc-c++ make
curl -sL https://rpm.nodesource.com/setup_12.x | sudo -E bash -
  • 安装 Node.js (不进行上面的操作直接执行安装,只能安装到6.x版本)
yum install nodejs -y
  • 安装 npm 包管理器
yum install npm -y
  • 新建项目文件夹,比如/home/webapps/yourapp
mkdir /home/webapps/yourapp
  • 进入新建的文件夹
cd /home/webapps/yourapp
  • 初始化环境,成功后会生成 package.json 文件
npm init -y
  • 因使用到了 ws 和 pg 两个第三方组件,所以需要顺次安装
npm install ws --save
npm install pg --save
  • 将本地写好的代码文件上传

  • 运行

node index.js
  • 后台运行指令
/usr/bin/nohup /usr/bin/node /home/webapps/yourapp/index.js & >> /home/webapps/logs.txt
  • 终止后台运行
    先查看一下node的进程号
ps -aux|grep node

或者根据端口号查询

netstat -nap|grep 端口号

杀死进程

kill -9 进程号
  • Nginx配置的修改
    增加 upstream 的定义
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream nodews {
    server localhost:3000;
}

增加location的定义

    location /ws/ {
        proxy_pass http://nodews/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
  • 安全起见,可以不对外暴露websocket监听的3000端口
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280