最近做了一個前后端分離的商城項目來熟悉開發的整個流程,最后希望能有個正式的部署流程,於是試着把項目放在雲服務器上,做了一下發現遇到了不少問題,借此記錄一下整個部署的過程。
使用的技術棧如標題所說大體上是Vue+Spring boot,但還是要提一下詳細的版本,因為在解決問題的過程中發現由於開發環境的不同會產生諸多影響,查找問題時如果沒有版本作為前提經常會出現很多不必要的誤解,甚至是誤操作,非常浪費時間。詳細版本情況如下:
- Vue 2.6.11
- Vue-cli 4.5.0
- Spring boot 2.1.1
- MySQL 8.0.13 (尤其注意)
- Nginx
1 上傳工具
部署的第一步要把文件上傳至雲服務器,並且后續還要在雲服務器上進行操作,方法很多,我這里選擇了Xshell和Xftp這兩個工具,均出自NETSARANG這家公司,需要注意的是在國內的官網上隱藏了免費家庭版的申請地址,可以通過直接訪問 Xshell、Xftp免費許可 進行下載,需要填寫姓名和郵箱。
1.1 Xftp
首先在Xftp中新建連接,填寫主機地址和用戶名密碼,連接成功就可以看到左側選項卡為本地的文件目錄,右側為雲服務器的文件目錄,只要從左側或右側將文件拖動到另一邊就可以實現相應文件的上傳和下載,下方傳輸選項卡會顯示具體進度,圖形化的界面相當直觀,不做過多的說明了。
關於Linux的目錄規范我沒有查到太多需要的信息,所以我這里是在根目錄新建了一個名為 app 的文件夾來存放網站應用,關於網站的打包我們在下一節說明,這里我們掌握如何上傳文件就可以。
1.2 Xshell
Xshell的連接建立方法與Xftp差不多,填寫主機地址,連接后再輸入用戶名密碼,連接后就可以在雲服務器上進行操作了。
通過這兩個工具與雲服務器建立聯系后我們就可以開始着眼於網站應用自身的問題了。
2 前端
相對來說前端的部署沒有遇到太多問題,所以我們先從前端開始
2.1 Vue
由於我使用了Vue-cli,所以項目完成后通過執行命令 npm run build
程序就會自動打包到項目目錄下的 dist 文件夾,打包后的目錄結構如下:
之后通過Xftp將這個文件夾上傳至雲服務器上,之前我已經新建了一個文件夾來存放,因為我們還可能有其他項目,並且后台也需要一個文件夾,所以建立具體文件夾結構如下:
新建文件夾可以使用Xftp的圖形界面快速建立,也可以在Xshell中使用指令,看個人的喜好和習慣,如果需要經常使用Linux系統,建議使用指令多加練習。
在Windows端進行開發的時候,在控制台使用 npm run serve
指令就可以快速啟動一個本地網站,但是這樣的網站只能在內網被訪問,肯定是達不到我們最初在外網訪問的目的,所以這里要借助反向代理服務器,我選擇的是被廣泛使用的Nginx。
2.2 Nginx
- 選定安裝目錄
cd /usr/local/src
- 在服務器上安裝Nginx之前先安裝若干依賴:
yum install gcc
yum install pcre-devel
yum install zlib zlib-devel
yum install openssl openssl-devel
這些依賴的作用可以參考這一篇 Linux上安裝Nginx依賴環境和庫、Nginx安裝,Nginx服務命令,我沒有逐一試過缺少某個依賴會有什么問題,在安裝Nginx之前就已經安裝好這些依賴了。
- 下載Nginx安裝包並解壓
可以從官網選擇需要的版本。
wget http://nginx.org/download/nginx-1.13.7.tar.gz #下載
tar -xvf nginx-1.13.7.tar.gz #解壓
- 執行配置並安裝
cd nginx-1.13.7 #切換目錄
./configure #執行配置
make && make install #編譯安裝(默認安裝在/usr/local/nginx)
- 安裝完成后查看版本無誤啟動
/usr/local/nginx/sbin/nginx -v #查看版本
cd /usr/local/nginx/sbin #cd到nginx的安裝位置的sbin目錄下
./nginx #啟動nginx
這里可以先訪問一下服務器的外網IP試試,出現 Welcome to nginx 就說明已經啟動成功了。
Nginx安裝完成后修改配置文件以對應我們的網站應用,修改文件的方法也可以選擇使用Xftp或者在Linux上用指令操作
location / {
root /app/osd_mall/vue_app/dist;
index index.html index.htm;
}
location /api {
proxy_pass http://localhost:28019/api/v1;
}
這里映射了兩個地址,第一個就是網站前端部分的主體,應該沒有太多的差異,主要的問題應該集中在第二個地址上,由於我做的是一個前后端分離的項目,后端接口也是包含在項目里的,那么必然存在跨域問題,開發時使用了Vue的Proxy從前端處理,代碼如下:
然后在axios里配置對應的名稱即 api,這樣就可以解決跨域的問題,但這只是本地開發時使用的方法,在Linux服務器上通過Nginx反向代理可以更安全地處理跨域問題,所以上圖中的代碼就不再需要了,打包前需要注釋或者刪除。
axios.defaults.baseURL = process.env.NODE_ENV == 'development' ? '/api' : '/api'
配置修改完成后測試配置文件,沒有問題后重啟Nginx服務
./nginx -t #測試配置文件
./nginx -s reload #重啟Nginx
這時已經可以通過我們的外網IP訪問前端頁面了,但是由於還沒有配置后端接口,所以基本是沒有數據和圖片的。顯而易見,上圖中的本地地址 http://localhost:28019/api/v1 就是我們的后端接口地址,那么我們接下來就對后端的部署進行說明。
3 后端
相對於前端來說,后端遇到的問題可謂是層出不窮,中間有很多波折,好在最后都解決了,其中有幾個就是開頭強調的版本問題。
3.1 Java
首先要安裝Java環境,從官網下載需要的版本,然后和之前一樣,通過Xftp上傳:
創建目錄,解壓:
mkdir /usr/java
tar zvxf server-jre-8u271-linux-x64.tar.tar.gz -C /usr/java
為了能在全局使用java命令,配置環境變量:
# 修改環境配置文件
vi /etc/profile
# 編輯配置文件,在里面添加如下三行
export JAVA_HOME=/usr/java/jdk1.8.0_271
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
# 使環境變量生效
source /etc/profile
# 驗證是否配置成功,查看java版本
java -version
3.2 Spring boot
要將Spring boot項目打包部署有很多選擇,詳情可以看這篇文章 java項目部署Linux服務器幾種啟動方式總結經驗
我這里選擇的是使用jar包部署,通過Maven打包的步驟就不說明了。再次通過Xftp將jar文件上傳至服務器,我的截圖里有一個dev版本的是保留了控制台日志的版本,正常只需要一個就可以。
3.3 Screen
上面介紹的文章里有提到java項目會運行在前台,當我們的Xshell窗口關閉后,項目其實也是會關閉的,但如果讓連入的機器也保持開機也並不合理,所以使用nohub指令將jar程序一直掛載在后台。這里再介紹另一種方法,那就是Screen工具。
Screen是一款由GNU計划開發的用於命令行終端切換的自由軟件。用戶可以通過該軟件同時連接多個本地或遠程的命令行會話,並在其間自由切換。GNU Screen可以看作是窗口管理器的命令行界面版本。它提供了統一的管理多個會話的界面和相應的功能。
Screen在一些流行的發行版上已經預安裝了,你可以使用下面的命令檢查是否已經在你的服務器上安裝了。
screen -v
如果沒有可以通過自帶的包管理器簡單地安裝。
yum -y install screen
screen -S yourname #創建一個名為yourname的session
screen -ls #列出當前所有的session
screen -r yourname #回到yourname這個session
screen -d yourname #遠程detach某個session
screen -d -r yourname #結束當前session並回到yourname這個session
使用Screen就如同切換窗口一般,這樣在服務器性能允許的情況下就可以同時掛載多個應用,同時也相對方便管理。
3.4 MySQL
1. 安裝
剛開始部署的時候,我幾乎忽略了MySQL,之后也沒想到這是最花時間的部分,但如果遵循正確的步驟其實並不困難。
大部分的工具我們都可以通過包管理器yum來安裝,上文的Screen正是如此,我本以為MySQL也是如此,不過查了一下發現最初確實如此,但自從MySQL被收購之后就存在版權問題了,所以CentOS7已經不再支持MySQL,而是在內部集成了MariaDB,兩者頗有淵源,結果就是文件會有沖突,所以還要先卸載MariaDB才行。
# 列出所有被安裝的rpm package
rpm -qa | grep mariadb
# 卸載(注意“版本號”根據當前系統顯示的版本信息的為准)
rpm -e mariadb-libs-5.5.37-1.el7_0.x86_64
# 如果提示依賴檢測失敗可以強制卸載
rpm -e --nodeps mariadb-libs-5.5.37-1.el7_0.x86_64
# 安裝依賴
yum install vim libaio net-tools
之后我們要決定是通過repo源直接從服務器下載安裝還是自己去官網下載一個再上傳到服務器上,最初我是按一些教程的步驟直接從repo源下載,但由於選擇的版本不對,最后程序無法正確建立連接,反復嘗試之后選擇從社區版官網下載需要的版本。
進入網站默認是最新版本,要找之前的版本點擊Archives,在新的頁面選擇對應的版本。然后是選擇操作系統,CentOS系統就是Red Hat的社區發行版,內核是相同的,或者用通用版本(Generic)也可以。
下載bundle包,解壓出其中如圖所示的五個文件上傳至服務器,依次安裝mysql-community-common、mysql-community-libs、mysql-community-client、mysql-community-server、mysql-community-release。
# 依次類推
rpm -ivh mysql-community-common-8.0.13-1.el7.x86_64.rpm
# 如果出現“依賴檢測失敗”問題再后面添加 --force --nodeps強制安裝
rpm -ivh mysql-community-common-8.0.13-1.el7.x86_64.rpm --force --nodeps
現在常見的MySQL版本一般是5.7和8.0之后的若干小版本,根據使用版本的不同,后續的配置有很大的不同,我使用的版本是8.0.13,接下來也是以8.0版本為例。
2. 重置密碼
在這一步遇到了諸如權限問題、版本不對、字段不同等情況,因為部署時完全沒想到有如此多的問題,沒有留下截圖,這里說一下整體的思路:首先要登錄MySQL,安裝完成后可能會有一個隨機密碼,記錄下來,用這個密碼登錄進數據庫,如果有權限問題就先給MySQL文件夾授權,登錄之后通過數據表修改默認密碼,指令如下:
# 登錄,-p后面沒有空格,直接輸入密碼,5.7版本密碼默認為空,8.0使用隨機密碼
mysql -u root -p密碼
# 切換數據庫
use mysql;
# 修改密碼(不能用123456這種簡單的密碼,需要大小寫和數字,如果還是想用簡單的密碼,看下文)
update user set password=password('123456') where user='root';
# 退出
exit;
設置完成后就可以用新密碼登錄了,如果設置有問題或者沒有記錄隨機密碼還有通過修改本地文件來重置密碼的方式,這里就不介紹了。
如果只是個人開發,不想用太過復雜的密碼怎么辦?可以通過修改密碼規則來解決這一問題,同樣的,5.7和8.0版本也存在區別:
# 5.7
set global validate_password_policy=0;
set global validate_password_length=1;
# 8.0
set global validate_password.policy=0;
set global validate_password.length=1;
# 查看密碼驗證變量
SHOW VARIABLES LIKE 'validate_password%';
密碼等級表
Policy | Tests Performed |
---|---|
0 or LOW | Length |
1 or MEDIUM | Length; numeric, lowercase/uppercase, and special characters |
2 or STRONG | Length; numeric, lowercase/uppercase, and special characters; dictionary file |
3. 遠程連接
每次要查數據庫都要登錄Linux就會很不方便,而且界面不友好,如果我們想用本地的Navicat訪問遠程的數據庫要怎么設置呢?
首先要關閉防火牆或者開放數據庫的3306端口(最好還是開放端口),
# 查看防火牆狀態
systemctl status firewalld
# 開啟防火牆服務
systemctl start firewalld
# 開放指定端口
firewall-cmd --zone=public --add-port=3306/tcp --permanent
# 重新載入
firewall-cmd --reload
如果使用的是雲服務器,還要記得在平台上開放指定端口:
設置完防火牆之后仍然不能遠程登錄,因為我們沒有授權用戶,先查詢一下用戶表:
select user,host from user;
可以看到除了remote都是localhost,remote就是我新建的專門用於遠程登錄的用戶,host代表的是該用戶可以在哪個地址下登錄,“%”代表所有地址都可以。5.7之前的版本可以通過授權直接隱式創建用戶,8.0之后不可以了。直接修改root用戶的host也是可以的,但是這樣登錄時會有些小區別,具體忘記了,這里我推薦新建一個用戶。
/* 創建用戶,這里的密碼同樣也受前面設置的密碼等級限制 */
CREATE USER '用戶名'@'%' IDENTIFIED BY '密碼';
/* 授權 */
grant all privileges on *.* to '用戶名'@'%';
執行后使用Navicat遠程登錄如果報錯 1251 client does not support authentication,說明MySQL8與Navicat的加密方式不同,修改加密方式:
alter user 用戶名 identified with mysql_native_password by '密碼';
這樣就可以從本地直接訪問遠程的數據庫了。
4.卸載MySQL
如果你在安裝時不幸出現問題,有各種各樣的問題需要重裝MySQL,那么可以根據這篇文章 Linux下徹底卸載mysql詳解來卸載MySQL。
5.程序建立數據庫連接
到這里就是最后一步了,我在這里出現問題后試了各種方法都沒有成功建立連接,用戶名密碼都沒有錯的情況下可能需要檢查以下幾個方面:
- 數據庫版本與程序的驅動版本是否一致
- 數據庫連接串是否正確
- 賬號是否有訪問權限
引用的插件版本要與服務器上安裝的數據庫版本一致
5.7和8.0的連接串有不少區別,8.0需要很多額外詞條,這里留下我的連接串
jdbc:mysql://localhost:3306/onesideddice_mall?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&autoReconnect=true&allowPublicKeyRetrieval=true&useSSL=false&allowMultiQueries=true
6.導入數據
這一步很簡單了,有各種方法,這里記錄一下導入服務器上的sql文件這種方式:
create database abc; /* 創建數據庫 */
use abc; /* 使用已創建的數據庫 */
set names utf8; /* 設置編碼 */
source /home/abc/abc.sql /* 導入備份數據庫 */
3.5 Nginx圖片服務器
在前端部分我們已經在Nginx中配置過后端接口了,為什么這里還要再提一次呢?其實理論上到這一步之前,就已經完成網站的部署了,如果中間各種對接沒有其他問題,網站已經可以正常運行了,但是如果你的站點中有大量的圖片,則不得不思考圖片要以什么方式存儲,相對路徑如何設置等。在部署完成后在圖片展示上我遇到了很多問題,其中比較顯著的就是圖片的相對路徑轉換問題,在觀察了一些網站的后,我發現他們的圖片通常單獨存放在圖片服務器上,這樣圖片的路徑相對穩定又方便設置,於是我就想到用Nginx再配置一個圖片服務器出來,盡可能地利用現有的服務器資源,當然也可以選擇七牛雲這種專門的圖片服務器,這樣圖片的訪問應該會更加穩定快速。
- 配置Nginx
在Nginx的配置里添加一個新的Server,方便與我們的網站應用區分,配置如下:
server {
listen 8000;
server_name localhost;
location / {
root /app/osd_mall/images;
autoindex on;
}
}
- root則是將images映射到/home/ftpadmin/hatlth/images/
- autoindex on便是打開瀏覽功能。
設置修改完成后記得測試並重載Nginx。
- 開放端口
和之前開放數據庫端口相同。
- 修改文件訪問權限
chown ftpadmin /app/osd_mall/images
chmod 777 -R /app/osd_mall/images
- 修改程序
根據自己的站點修改路徑,由於使用了統一的圖片服務器,現在可以設置一個配置項來專門管理圖片地址了,相對於之前要方便很多,本地環境也可以使用這個線上的圖片服務器。
4 結束
到這里,基本的部署就完成了,實現了從本地Windows端到Linux服務端的轉換,在解決問題的過程中沒有想到有如此多的問題,記錄的時候遺漏了很多細節,但主要的問題應該都得以解決,希望能幫助遇到問題的人,也方便自己日后回顧瀏覽。