ubuntu部署小筆記
- 搭建前端+控制端+后端
- 前端
- nginx反向代理
- 使用ubuntu部署nextjs項目
- 問題一 如何訪問端口號
- 配置
- 后臺運行該進程
- pm2
- 問題二 包體過大
- 生產環境下所需文件
- 問題三 部署在vercel時出現的問題
- 需要魔法
- 訪問后端api時,必須使用==https==協議
- 電腦端訪問正常,手機端出現異常
- 控制器
- 部署
- 路由正常,但是刷新后提示404的問題
- 相對路徑問題
- 后端
- 部署
在實際將項目部署到linux服務器(ubuntu)的過程中遇到的一些小細節的問題
在這里記錄一下
搭建前端+控制端+后端
找到一個大佬開源的項目nextjs+vite+java,是一個用起來功能蠻多的開源項目,蠻好用的,很多實用性的功能。前端使用nextjs,控制器使用vite,后端使用java,想試著在linux上部署
前端
nginx反向代理
題外話
之前一直沒有去摸這方面相關的技術,因為一直不是很理解,也沒有想去花時間接觸,現在因為需要項目搭建,所以特意用了nginx來部署項目,也是為了提高自己的能力
那么啥叫反向代理,經過最近差不多一個星期的接觸和使用,我的理解其實就像大家熟知的那樣,是一個類似中轉站的東西,將外部發送過來的訪問和請求,以一定的規則,去訪問內部的資源和項目。
但是這和使用apache2或者tomcat之類的又有什么區別呢,不也是外部通過ip或者域名的方式,訪問到我們綁定的項目路徑嗎
其實還是有一些細微的差別,但我不知道能不能解釋清楚。就我的認知,反向代理可以通過內部轉換的方式,將外部的訪問進行識別和處理,然后轉發給內部的指定服務
具體的例子就是
我有一個前端項目 ,域名為www.xxx.com。這是我的一個主頁
同時我有一個配套的前端管理項目,我希望也在這個域名下通過www.xxx.com/admin的方式進行訪問
如果是我之前的能力,我的解決方式有兩個
- 在這個域名上申請多一個二級域名,比如admin.xxx.com,然后將這個二級域名綁定到前端管理項目的路徑上,然后進行訪問
- 在前端項目的public路徑下將前端管理項目拉進去,然后通過www.xxx.com/public/admin的方式進行訪問
毋庸置疑,這兩個方式都不能實現我的需求,但是,反向代理就可以實現
通過解析域名的后綴,也就是admin,根據配置轉發到指定的服務,也就是前端管理項目
并且他可以通過配置不同的參數,將同一個訪問下發轉發到不同的服務器上,從而減輕服務器的壓力
好的說了這么多,實際我在使用的過程中都遇到了哪些問題呢
使用ubuntu部署nextjs項目
也是第一次接觸nextjs這個語言,聽說是以react為基礎開發的, 當然react我也沒了解過
這個不重要,主要先講部署的東西
nextjs通過npm指令進行依賴安裝,調試和打包
npm install //這是安裝
npm run dev //這是調試環境
npm run build//這是打包
npm run start//這是生產環境
問題一 如何訪問端口號
配置
按照之前我部署前端的經驗,就是打包,然后將打包出來的上傳到服務器上,然后通過路徑進行訪問
但nextjs不同,他需要通過npm run start指令啟動,并且自己占用端口號。這就把我難住了,我只試過直接訪問靜態資源的部署,這種端口號的可咋整,難道要我直接暴露端口號給用戶嗎,但是www.xxx.com:9003這種訪問真的太丑了…于是我了解了一下發現apache和nginx都是支持轉發端口號的,當程序員這么久也是才知道的Orz。這也就是反向代理的作用之一,當然不是只有nginx才有,apache,tomcat我相信都會有這個功能,只不過談起```反向代理···腦子里第一反應就是nginx,所以就用了他
在哪里配置呢
在etc/nginx/下的nginx.conf或者sites-available下的default兩個文件中其中一個配置下面的信息都行
我建議是在nginx.conf文件下配置,畢竟你可以少進入一個目錄,而且這個文件名也一目了然
不過要注意的是nginx.conf文件
下需要在http{里配置下面的server信息}
server {# Nginx監聽443端口(標準HTTPS端口)listen 443 ssl;# server_name _; # 通用域名server_name xxx.xxx.xxx; # 你的域名# SSL證書配置ssl_certificate ;//如果有的話ssl_certificate_key ;//如果有的話location / {proxy_pass http://localhost:9001; //通過轉發的方式訪問nextjs項目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_set_header X-Forwarded-Proto $scheme;}# 后端APIlocation /api {# rewrite ^/api/(.*) /$1 break; # 去掉/api前綴proxy_pass http://localhost:9003;//通過轉發的方式訪問后端項目(java)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_set_header X-Forwarded-Proto $scheme;}location /static/{root /var/www/;autoindex on; }}
后臺運行該進程
由于直接執行npm run start的話,當我們遠程連接關閉后,進程就會被自動kill掉了,所以我們需要將進程放在后臺運行
有兩個方案,一個是nohup,下面運行jar包會詳細講,這里說另一個方案
pm2
pm2好像是專門用來管理npm相關的項目的工具
pm2 start npm --name 項目名(自定義)--port=端口號(不寫就默認使用3000)
命令大概是這樣,還可以設置對應的運行內存啥的,有興趣可以自己了解一下
運行了之后也可以實時查看日記
輸入下面的指令就可以查看了
pm2 log 前面自定義的項目名
問題二 包體過大
回到正題,nextjs項目在build之后,包體非常大,就我目前在用的打包出來有768m,說實話,這比我用unity開發網頁版的游戲都大了4、5倍…
然后因為包體太大了,我就嘗試在服務器端直接拉去項目源碼,然后在服務器上跑npm run dev
這一dev,沒什么問題,npm run start
也沒什么問題,但是用戶一訪問項目,開始編譯的時候,2核2g的服務器直接就宕機了…一開始我要還以為是我的指令有問題,排除了好久…
原因就是npm run build
對讀寫性能的要求很大,在自己的電腦上處理沒什么問題,大不了等多一會,但是云服務器上的配置撐在不了這么大的讀寫量,所以就直接宕機了…
無奈,于是只能乖乖的本地npm run build
后部署到服務器端,然后執行npm run start
好了,這下可以通過端口訪問了,然后再用nginx轉發的方式,將外部訪問轉到內部的這個端口號就行了
當然其中有一些小細節需要注意
生產環境下所需文件
.next
// npm run build 指令后生成
package.json
、package-lock.json
// 運行項目所需配置文件
當然只有這三個不出意外的話也是不行的, 因為npm run start執行時,會需要next相關的依賴
所以要么在項目根目錄下執行npm install配置項目所需的環境依賴,要么就全局配置一下相關依賴。我是項目根目錄中install的,這樣有一個壞處就是生成的node_module文件也不小,我的是400+m,一個400m一個700m,好家伙一個前端項目就要1g了…前端發展的太快了…
如果以上操作都沒問題的話,那么你的項目應該最終也能跑起來了
問題三 部署在vercel時出現的問題
原先因為包體過大在ubuntu上無法正常訪問,所以通過github的方式在vercel上進行了部署,vercel有一些坑
vercel有什么好處,第一是免費,第二是一鍵幫你部署項目。只要關聯github,選擇對應的項目,vercel就會一鍵幫你構建和部署,只需要訪問他提供給你的項目域名即可
需要魔法
vercel部署的項目需要魔法
才能訪問,有梯子的話訪問速度還蠻快的說實話。當然,你也可以通過cloudflare進行cname的設置將國內的域名綁定到vercel提供的域名上,畢竟有的白嫖誰不想呢是吧
但是
經過實際體驗,就算通過cloudflare轉發,訪問速度也是完全看cloudflare的,時快時慢,體驗非常不好…所以這也是為什么我想最后還是部署在自己服務器上段原因,
訪問后端api時,必須使用https協議
http他是不給調用的,而且有些即使是https的圖片資源他也無法正常加載
有一個投機的辦法,如果你的域名還沒有備案通過的話,可以先去ssl申請免費證書,然后給服務器上的nginx里配置后端服務的ssl文件, 雖然ssl是給域名準備的,不過還是能訪問的,只是前面會提示你依舊是不安全的內容
電腦端訪問正常,手機端出現異常
部署項目后在電腦端沒問題,能跑通,但是在手機端就是怎么都調用不到后端的數據
這個問題也是排查了很久才發現的,原因就是因為上面的投機取巧的方式,https證書在國內瀏覽器上應該是有處理的,不安全的直接就給你攔截下來了,所以在手機端上的任何瀏覽器都訪問不了(微博內置的可以打開,他會提示你https不安全,是否繼續訪問,也是這個提示才讓我知道問題所在;不過這里也有一個問題,我后面用備案過的域名申請的ssl證書,在微博里打開項目他也提示不安全…真是奇了怪了hhh)
然后我就試著用已經備案過的域名去申請一個ssl,然后在nginx上綁定這個域名和對應的證書文件,發現手機端也正常了
控制器
控制器使用的是vite,這個說實話我也不了解,不過這個也可以用npm進行操作
淺淺的看了一下,直接跳轉如何部署項目
vite通過指令
npm install
安裝依賴
然后通過npm run dev
進行調試
npm run preview
進行預覽
npm run build
進行打包
vite打包出來不需要額外的啟動,直接訪問項目路徑即可
這一點還是挺好的
你只需看把打包出來的dist
文件上傳到服務器即可
nginx配置一下訪問路徑
部署
server {listen 80 ;server_name _; # 或者你的域名# SSL證書配置# ssl_certificate /home/ssl/xxx.pem;# ssl_certificate_key /home/ssl/xxx.key;root /var/www/redfanswebadmin/dist;index index.php index.html index.htm;location / {try_files $uri $uri/ /index.html;}location ~ /\.ht {deny all;}}
路由正常,但是刷新后提示404的問題
這是由于沒有在localtion /下配置下面的這行代碼,導致項目內路由正常,但刷新時,因為沒有配置從index.html進行訪問,直接去訪問項目資源,導致了404的問題
location / {try_files $uri $uri/ /index.html;}
相對路徑問題
原先我是想在nginx配置文件中已經有的nextjs項目里添加一個/admin的轉發,然后少申請一個二級域名的,但是vite項目中的一些資源文件和路由,使用的都是相對路徑,也就是說,如果我用admin轉發到了vite項目,由于相對路徑的問題,很多的資源他訪問的位置就不是vite的路徑了
舉個例子就是
vite項目中加載一些css和js的文件
使用的是/assets/...css
,如果使用/admin轉發的話,他就會在nextjs項目的路徑中去找對應的/assets/...css
文件,這顯然是不對的,如果要改的話,需要在vite項目中一個一個找所有用了相對路徑的配置,這會比較麻煩,所以就放棄了這個方式
當前做法
- 申請二級域名
- 在nginx中配置該二級域名以及對應的vite項目的資源路徑
后端
后端使用的是java,我們的老熟人了,這個因為用了不少,所以基本沒遇到什么問題
部署
- 在idea中通過maven的package命令直接一鍵生成jar包
- 上傳到服務器,服務器需要有java
2.1 用tomcat運行(我沒用)
2.2 使用linux的nohup指令后臺運行
nohup java -jar jar包路徑/xxx.jar &
后面的&就是后臺運行的意思,不加的話就是遠程連接的時候能用,關閉了這個指令就不執行了,所以是必須要加的
相關指令
nohup執行后會返回一個進程號,不需要的時候就用下面的指令加提供的進程號kill掉就行
kill -9 端口號
當然一般人也不會去記錄這玩意兒,所以可以用下面的指令去找相關的服務器的進程號
ps -ef|grep 服務名(java,apache2,nginx等)
不過這樣運行的話,你在jar包中設置的是什么端口號,那就是什么端口號,不能修改了
怎么查看日志,每個nohup執行后沒有特別配置的話都會在輸入命令的當前目錄下生成nohup.out文件,可以通過下面的指令去查看實時日志
tail -f nohup.out
由于都是用的純命令行,所以也就沒有什么截圖的必要了,指令真的只能多打才能記得住…
題外話
- 開源項目中也存在一些問題,如上傳圖片的路徑需要設置,后臺也需要配置,否則會出現上傳后在前端無法訪問的情況。其他問題暫時沒有。哦開源的作者部署前端項目使用的是寶塔,我在win上安裝了下寶塔,在運行前端項目時提示了一些python相關的異常導致無法正常運行,所以就沒用寶塔了…
- nginx可以和apache之類的同時跑通,不過需要確保端口之間沒有沖突,比如nginx先啟動,默認占用了80端口,你的apache就得在配置文件中將80端口注釋掉,否則apache會無法正常啟動。然后應該怎么使用呢,舉個例子:
2.1 nginx配置了一個域名www.xxx.com,指向apache中的其中一個服務(apahce中通過占用端口8888訪問某個項目),nginx只需要在配置域名的server中的proxy_pass中輸入localhost:8888,那么用戶在輸入www.xxx.com域名時,niginx就會通過轉發的方式,將用戶路由到apache中的8888端口號對應的項目。
2.2 當然這樣有點多余,實際上你只需要在nginx中直接配置就行了。不過總會有需要這么用到的時候,所以就多提一下~ - 另外,部署之后,基本國內的app中內置的瀏覽器都能正常打開運行nextjs項目,唯獨google瀏覽器不行…具體原因未知,一訪問就提示client error之類的,然后再刷新也只能訪問到網頁的一些靜態資源, 調用不到后端的接口。有遇到相同問題但解決了的大佬可以評論區留言解惑Orz
歷時不到一個星期的時間,總算是成功將項目部署到了自己的服務器上,學習到了很多以前沒接觸過的知識和技術,學無止境…
也要感謝ai,基本都是邊問邊改的hhhhh