您好,登錄后才能下訂單哦!
本篇文章為大家展示了Springboot中如何進(jìn)行Serverless的訂單應(yīng)用,內(nèi)容簡明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
這是一個(gè) JAVA 開發(fā)的訂單后臺(tái)應(yīng)用(沒錯(cuò)!就是那個(gè)讓無數(shù)大學(xué)生痛不欲生的訂單后臺(tái)系統(tǒng)),結(jié)合 Serverless 這一無服務(wù)器思想,嘗試通過云函數(shù) + API 網(wǎng)關(guān) + 云數(shù)據(jù)庫的組合來部署 Springboot 的成功之作。
本文作者:Freeeeeedom
該應(yīng)用提供了完整的用戶登錄驗(yàn)證、接口數(shù)據(jù)驗(yàn)證、訂單流 (CRUD) 等強(qiáng)大的功能,而且在本地開發(fā)調(diào)試時(shí)也能模擬 API 網(wǎng)關(guān)調(diào)用云函數(shù)(本地 Java 開發(fā)云端部署不是問題),還兼容了云消息隊(duì)列 CMQ 的調(diào)用,以便后續(xù)開發(fā)引入云中間件。
同時(shí),這種部署方式也能讓其他的 Springboot 很快地轉(zhuǎn)換為云函數(shù)部署。
為響應(yīng)國家「十四五計(jì)劃」的環(huán)保計(jì)劃,特地的研究了一下傳說中的 Serverless 方案(省服務(wù)器 ????),于是便有了這次嘗試。
JAVA 天下第一**,當(dāng)然 c/c++/c#/node/python/go/php/vb 這些也不錯(cuò)
JAVA 的單體應(yīng)用還能選什么呢?只能是 Springboot 啊
注冊(cè)個(gè)騰訊云賬號(hào)
開通以下產(chǎn)品權(quán)限(云函數(shù)、API 網(wǎng)關(guān)、對(duì)象存儲(chǔ))
財(cái)力允許的話還可以購買數(shù)據(jù)庫服務(wù)(因?yàn)槟晟佥p狂打折時(shí)我購買了這倆很長很長時(shí)間)
訂單應(yīng)用來說的話,必然是提供 restful 的接口,所以在統(tǒng)一 VPC 內(nèi)采用了云函數(shù) + API 網(wǎng)關(guān)的模式提供接口,于是就有了以下方案:
應(yīng)用主體部署在云函數(shù)
使用 API 網(wǎng)關(guān)作為函數(shù)入口
頁面則是使用了對(duì)象存儲(chǔ)部署
數(shù)據(jù)庫方面則使用了同一 vpc 下的云數(shù)據(jù)庫(財(cái)力有限只嘗試了 mysql、redis,理論上其他應(yīng)該都可行)
要讓 JAVA 工程部署到云函數(shù)上,首先了解什么是云函數(shù)(以下摘自微信開放文檔)
云函數(shù)即在云端(服務(wù)器端)運(yùn)行的函數(shù)。在物理設(shè)計(jì)上,一個(gè)云函數(shù)可由多個(gè)文件組成,占用一定量的 CPU 內(nèi)存等計(jì)算資源;各云函數(shù)完全獨(dú)立;可分別部署在不同的地區(qū)。開發(fā)者無需購買、搭建服務(wù)器,只需編寫函數(shù)代碼并部署到云端即可在小程序端調(diào)用,同時(shí)云函數(shù)之間也可互相調(diào)用。
云函數(shù)其實(shí)就是將業(yè)務(wù)拆分成函數(shù)粒度部署在云上,那么就寫了個(gè)簡單的 demo 部署到云函數(shù)上,并且配上了 API 網(wǎng)關(guān)嘗試調(diào)用。
/** * 純javascf快速開發(fā)部署(不走springboot) * * @author Freeeeeedom * @date 2020/10/24 10:31 */ public class Scf { /** * log Object */ private static Logger log = LoggerFactory.getLogger(Scf.class); private static DruidDataSource dataSource1 = new DruidDataSource(); static { //此處加載或修改數(shù)據(jù)源 多數(shù)據(jù)源配置多個(gè) dataSource1.setUsername("Freeeeeedom"); dataSource1.setUrl("jdbc:mysql://Freeeeeedom?autoReconnectForPools=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"); dataSource1.setPassword("Freeeeeedom"); dataSource1.setMinIdle(1); dataSource1.setMaxActive(5); dataSource1.setMaxWait(10000); dataSource1.setValidationQuery("SELECT 1 from dual"); log.info("數(shù)據(jù)源加載ok~"); } /** * 純scf入口參數(shù) * * @param insertParam 入?yún)? * @return java.lang.Object 執(zhí)行結(jié)果 * @author Freeeeeedom * @date 2020/10/24 10:31 */ public Object pure(Map<String, Object> insertParam) { log.info("param:{}", gson.toJson(insertParam); Gson gson = new GsonBuilder().disableHtmlEscaping().create(); try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { log.error("內(nèi)部處理異常", e); } Map response = new HashMap(); JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(dataSource1); Map order = jdbcTemplate.queryForMap("select order_id,create_time from `order` limit 1"); log.info(order.toString()); return buildResponse(gson, gson.toJson(order), response); } private Object buildResponse(Gson gson, String json, Map response) { Map<String, String> headers = new HashMap(1); headers.put("Content-Type", "application/json"); response.put("statusCode", HttpStatus.OK.value()); response.put("headers", headers); response.put("body", json); return gson.toJson(response); } }
只需要打包好代碼,然后將入口函數(shù)設(shè)置為 scf.Scf::pure
就實(shí)現(xiàn)了接收數(shù)據(jù),然后從數(shù)據(jù)庫查詢了第一個(gè)訂單的 id 和創(chuàng)建時(shí)間并且返回的能力:
每一次通過 API 網(wǎng)關(guān)觸發(fā)云函數(shù)都會(huì)觸發(fā) pure 這個(gè)方法(調(diào)用者 > 調(diào)用 API 網(wǎng)關(guān) > 云函數(shù) --> pure),但經(jīng)測(cè)試發(fā)現(xiàn) static 的數(shù)據(jù)源初始化并不會(huì)被重復(fù)加載,這也奠定了 springboot 可部署基礎(chǔ)。
其中通過 log 打印 API 網(wǎng)關(guān)帶來的參數(shù),直接將其復(fù)制為 json,然后通過 main 函數(shù)模擬調(diào)用,這樣就實(shí)現(xiàn)了本地模擬 serverless 部署后的調(diào)用。
log.info("param:{}", gson.toJson(insertParam);
有了這些基礎(chǔ),那么只需要有一個(gè)入口類模擬 springboot 啟動(dòng)的加載,然后再映射一下 API 網(wǎng)關(guān)過來入口參數(shù),即可實(shí)現(xiàn) springboot 在云函數(shù)上部署(其實(shí)就是上面 SCF 類的超級(jí) plus 版本)。
** API 網(wǎng)關(guān)配置**
這里的路徑參數(shù)對(duì)應(yīng) springboot 里的 mapping 路徑
有了上面那些 demo 后,可得知我們模擬云端部署運(yùn)行已經(jīng)不是問題。那么怎么在本地調(diào)試呢?答案很簡單,直接啟動(dòng) springboot 然后調(diào)正常就完事了。
沒錯(cuò),就是直接用原生的 springboot 玩法即可。把 springboot 部署到云函數(shù)其實(shí)就是外掛了一個(gè) springboot 的啟動(dòng)類(設(shè)計(jì)模式上叫適配器模式?(+_+)?
完整的 springboot,能用 springboot 做的都能實(shí)現(xiàn),我只是編寫了一些小功能驗(yàn)證這個(gè)應(yīng)用。
[x] 與本地服務(wù)器數(shù)據(jù)庫連接
[x] 云數(shù)據(jù)庫連接
[x] vpc數(shù)據(jù)庫連接
[x] 外部接口調(diào)用(發(fā)短信驗(yàn)證碼)
[x] 實(shí)現(xiàn)簡單的訂單流 (crud)
[x] 實(shí)現(xiàn)簡單的登錄能力
[x] 實(shí)現(xiàn)簡單的數(shù)據(jù)驗(yàn)證能力
整個(gè)項(xiàng)目功能簡單但代碼卻不少。
首先 "serverless"、"騰訊"、"云服務(wù)" 這幾個(gè)詞就足以代表安全了,但為了功能完整性我還是嘗試加了點(diǎn)東西。
在這個(gè)系統(tǒng)中,我選擇了 header 中加簽名的方式驗(yàn)證數(shù)據(jù),原因是啥,操作簡單,有效唄。加密手段和方案暫且不說,就從流程上來看,是很方便的:
從 API 網(wǎng)關(guān)調(diào)用參數(shù)中獲取到 header,body
驗(yàn)證數(shù)據(jù)有效性
請(qǐng)求轉(zhuǎn)入業(yè)務(wù)模塊
驗(yàn)證數(shù)據(jù)有效性
參數(shù)進(jìn)入功能模塊
驗(yàn)證數(shù)據(jù)有效性
………………
其實(shí)只有 123 步驟是最有效的,后面的 45678 如果你想的話……更不用說 API 網(wǎng)關(guān)本身提供的鑒權(quán)功能了。
內(nèi)存的話對(duì)于訂單系統(tǒng)來說單次請(qǐng)求加上 JVM 也才 300mb,而云函數(shù)單個(gè)函數(shù)執(zhí)行內(nèi)存能拉到 3GB,哪怕有點(diǎn)量的分布式計(jì)算應(yīng)該問題也不大。
并發(fā)的話云函數(shù)上的預(yù)置并發(fā)上限 200 個(gè),訂單系統(tǒng)嘛,QPS1000?10000?100000? ezpz了,再怎么也比自家機(jī)柜服務(wù)器強(qiáng)幾百幾千個(gè)量級(jí)了。
內(nèi)存算力不夠服務(wù)器擴(kuò)容?不存在的。
生成個(gè) VUE 項(xiàng)目,改改鏈接調(diào)調(diào)頁面,然后上傳到存儲(chǔ)桶上,一鍵打開 CDN ~( ̄▽ ̄)~*完美!
察覺到了到了科技的進(jìn)步,時(shí)代的發(fā)展,Serverless 的強(qiáng)大。
上述內(nèi)容就是Springboot中如何進(jìn)行Serverless的訂單應(yīng)用,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。