Springboot之基于騰訊云Serverless的訂單應用

來源: TencentServerless
作者:Freeeeeedom
時間:2020-12-02
17124
這是一個JAVA開發(fā)的訂單后臺應用(沒錯!就是那個讓無數(shù)大學生痛不欲生的訂單后臺系統(tǒng)),結(jié)合Serverless這一無服務器思想,嘗試通過云函數(shù)+API網(wǎng)關+云數(shù)據(jù)庫的組合來部署Springboot的成功之作。

前言

這是一個JAVA開發(fā)的訂單后臺應用(沒錯!就是那個讓無數(shù)大學生痛不欲生的訂單后臺系統(tǒng)),結(jié)合Serverless這一無服務器思想,嘗試通過云函數(shù)+API網(wǎng)關+云數(shù)據(jù)庫的組合來部署Springboot的成功之作。

該應用提供了完整的用戶登錄驗證、接口數(shù)據(jù)驗證、訂單流(CRUD)等強大的功能,而且在本地開發(fā)調(diào)試時也能模擬API網(wǎng)關調(diào)用云函數(shù)(本地Java開發(fā)云端部署不是問題),還兼容了云消息隊列CMQ的調(diào)用,以便后續(xù)開發(fā)引入云中間件。

同時,這種部署方式也能讓其他的Springboot很快地轉(zhuǎn)換為云函數(shù)部署。

為響應國家「十四五計劃」的環(huán)保計劃,特地的研究了一下傳說中的Serverless方案(省服務器),于是便有了這次嘗試。

語言和框架

·JAVA天下第一,當然c/c++/c#/node/python/go/php/vb這些也不錯

·JAVA的單體應用還能選什么呢?只能是Springboot啊

部署準備

1.注冊個騰訊云賬號

2.開通以下產(chǎn)品權限(云函數(shù)、API網(wǎng)關、對象存儲)

3.財力允許的話還可以購買數(shù)據(jù)庫服務(因為年少輕狂打折時我購買了這倆很長很長時間)

·mysql數(shù)據(jù)庫

·redis數(shù)據(jù)庫

640.png

部署方案

訂單應用來說的話,必然是提供restful的接口,所以在統(tǒng)一VPC內(nèi)采用了云函數(shù)+API網(wǎng)關的模式提供接口,于是就有了以下方案:

1.應用主體部署在云函數(shù)

2.使用API網(wǎng)關作為函數(shù)入口

3.頁面則是使用了對象存儲部署

4.數(shù)據(jù)庫方面則使用了同一vpc下的云數(shù)據(jù)庫(財力有限只嘗試了mysql、redis,理論上其他應該都可行)

嘗試部署

要讓JAVA工程部署到云函數(shù)上,首先了解什么是云函數(shù)(以下摘自微信開放文檔)

云函數(shù)即在云端(服務器端)運行的函數(shù)。在物理設計上,一個云函數(shù)可由多個文件組成,占用一定量的CPU內(nèi)存等計算資源;各云函數(shù)完全獨立;可分別部署在不同的地區(qū)。開發(fā)者無需購買、搭建服務器,只需編寫函數(shù)代碼并部署到云端即可在小程序端調(diào)用,同時云函數(shù)之間也可互相調(diào)用。

云函數(shù)其實就是將業(yè)務拆分成函數(shù)粒度部署在云上,那么就寫了個簡單的demo部署到云函數(shù)上,并且配上了API網(wǎng)關嘗試調(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ù)源配置多個

        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)?/span>

     * @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ù)設置為scf.Scf::pure就實現(xiàn)了接收數(shù)據(jù),然后從數(shù)據(jù)庫查詢了第一個訂單的id和創(chuàng)建時間并且返回的能力:

640 (1).png

每一次通過API網(wǎng)關觸發(fā)云函數(shù)都會觸發(fā)pure這個方法(調(diào)用者&gt;調(diào)用API網(wǎng)關&gt;云函數(shù)--&gt;pure),但經(jīng)測試發(fā)現(xiàn)static的數(shù)據(jù)源初始化并不會被重復加載,這也奠定了springboot可部署基礎。

其中通過log打印API網(wǎng)關帶來的參數(shù),直接將其復制為json,然后通過main函數(shù)模擬調(diào)用,這樣就實現(xiàn)了本地模擬serverless部署后的調(diào)用。

log.info("param:{}",gson.toJson(insertParam);

有了這些基礎,那么只需要有一個入口類模擬springboot啟動的加載,然后再映射一下API網(wǎng)關過來入口參數(shù),即可實現(xiàn)springboot在云函數(shù)上部署(其實就是上面SCF類的超級plus版本)。

**API網(wǎng)關配置**

這里的路徑參數(shù)對應springboot里的mapping路徑

640 (2).png

640 (3).png

本地調(diào)試

有了上面那些demo后,可得知我們模擬云端部署運行已經(jīng)不是問題。那么怎么在本地調(diào)試呢?答案很簡單,直接啟動springboot然后調(diào)正常就完事了。

沒錯,就是直接用原生的springboot玩法即可。把springboot部署到云函數(shù)其實就是外掛了一個springboot的啟動類(設計模式上叫適配器模式?(+_+)?

功能

完整的springboot,能用springboot做的都能實現(xiàn),我只是編寫了一些小功能驗證這個應用。

·[x]與本地服務器數(shù)據(jù)庫連接

·[x]云數(shù)據(jù)庫連接

·[x]vpc數(shù)據(jù)庫連接

·[x]外部接口調(diào)用(發(fā)短信驗證碼)

·[x]實現(xiàn)簡單的訂單流(crud)

·[x]實現(xiàn)簡單的登錄能力

·[x]實現(xiàn)簡單的數(shù)據(jù)驗證能力

整個項目功能簡單但代碼卻不少。

安全

首先"serverless"、"騰訊"、"云服務"這幾個詞就足以代表安全了,但為了功能完整性我還是嘗試加了點東西。

在這個系統(tǒng)中,我選擇了header中加簽名的方式驗證數(shù)據(jù),原因是啥,操作簡單,有效唄。加密手段和方案暫且不說,就從流程上來看,是很方便的:

1.從API網(wǎng)關調(diào)用參數(shù)中獲取到header,body

2.驗證數(shù)據(jù)有效性

3.請求轉(zhuǎn)入業(yè)務模塊

4.驗證數(shù)據(jù)有效性

5.參數(shù)進入功能模塊

6.驗證數(shù)據(jù)有效性

7.………………

其實只有123步驟是最有效的,后面的45678如果你想的話……更不用說API網(wǎng)關本身提供的鑒權功能了。

640 (3).png

性能

內(nèi)存的話對于訂單系統(tǒng)來說單次請求加上JVM也才300mb,而云函數(shù)單個函數(shù)執(zhí)行內(nèi)存能拉到3GB,哪怕有點量的分布式計算應該問題也不大。

640 (5).png

并發(fā)的話云函數(shù)上的預置并發(fā)上限200個,訂單系統(tǒng)嘛,QPS1000?10000?100000?ezpz了,再怎么也比自家機柜服務器強幾百幾千個量級了。

640 (6).png

內(nèi)存算力不夠服務器擴容?不存在的。

最后

生成個VUE項目,改改鏈接調(diào)調(diào)頁面,然后上傳到存儲桶上,一鍵打開CDN

~( ̄▽ ̄)~*完美!察覺到了到了科技的進步,時代的發(fā)展,Serverless的強大。

立即登錄,閱讀全文
版權說明:
本文內(nèi)容來自于TencentServerless,本站不擁有所有權,不承擔相關法律責任。文章內(nèi)容系作者個人觀點,不代表快出海對觀點贊同或支持。如有侵權,請聯(lián)系管理員(zzx@kchuhai.com)刪除!
掃碼登錄
打開掃一掃, 關注公眾號后即可登錄/注冊
加載中
二維碼已失效 請重試
刷新
賬號登錄/注冊
個人VIP
小程序
快出海小程序
公眾號
快出海公眾號
商務合作
商務合作
投稿采訪
投稿采訪
出海管家
出海管家