Parse Server - 快速實現 Serverless 平臺的利器

原文地址

圖片描述

近年來NODEJS發展迅速,很多工程師尤其是前端工程師,用NODEJS來開發一些後端應用。同時,研發效率和研發成本成爲開發者關注的重點,對於一些基礎常用功能,如何避免重複開發,成爲大家關注的重點,而 Parse Server 就是抽象了常用功能的NODEJS開源項目。

首先,從整體上看看 Parse Server 提供了哪些基礎功能:

  • 用戶的登錄註冊
  • 用戶身份的認證
  • 數據存儲 && 靈活查詢
  • 文件存儲
  • 實時查詢
  • 消息推送
  • 緩存服務
  • 與雲平臺很好的對接
  • 自定義業務邏輯與Hook機制

服務快速搭建

默認情況下,Parse Server 使用的默認數據庫是 MonogDB,所以需要提前安裝該數據庫。關於數據庫的安裝與使用不是本文的重點,暫且跳過。

const config = require('./config');
const app = express();

var api = new ParseServer({
  databaseURI: config.databaseURI,
  cloud: './cloud/main.js',
  appId: config.appId,
  masterKey: config.masterKey,
  // push: { ... }, // See the Push wiki page
  // filesAdapter: ..., // 對應不同雲廠商的 FilesAdapter 
  // javascriptKey: config.javascriptKey, // js客戶端認證
  liveQuery: { // 建立websocket鏈接,實現實時通信
    classNames: ['Sdtuent']
  }
});

var dashboard = new ParseDashboard({
  "apps": [
    {
      "serverURL": "http://localhost:1337/parse",
      "appId": config.appId,
      "masterKey": config.masterKey,
      "appName": "test"
    },
  ]
});

// Serve the Parse API at /parse URL prefix
app.use('/parse', api);
app.use('/dashboard', dashboard);

const port = 1337;
const httpServer = http.createServer(app);

httpServer.listen(port, function() {
  console.log('parse-server-example running on port ' + port + '.');
});

var parseLiveQueryServer = ParseServer.createLiveQueryServer(httpServer);

通過上述少量的代碼,快速完成服務的搭建,/parse 是API的前綴,/dashboard 是後臺的頁面路由前綴,這樣就可以快速使用 Parse Server 提供的各種功能。

圖片描述

客戶端調用

針對不同環境、不同語言,parse server提供了大量的 SDK,本文以 javascript 爲例進行簡單介紹。

<head>
  <script src="https://unpkg.com/[email protected]/dist/parse.js"></script>
</head>
<body>
  ...
  <script>
    // 對應服務端設置的id
    Parse.initialize(${appId}, ${javascriptKey}); 
    Parse.serverURL = 'http://127.0.0.1:1337/parse'

    const username = "xxx", password = 'xxxx';
    const email = 'xxx'
    async function signup() {
      try {
        const user = new Parse.User;
        user.set('username', username);
        user.set('password', password);
        user.set('email', email);
        const result = await user.signUp();
        console.log('result is: ', result);
      } catch(err) {
        console.log('error: ', err);
      }
    }
    signup();
  </script>
</body>

上面的示例,是在瀏覽器端進行用戶的註冊: 首先引入Javascript SDK;然後進行基本的環境設置 Parse.initializeParse.serverURL;第三部就是使用SDK調用 user.signUp 完成註冊。

然後到 dashboard,可以看到 user 中新增了一條記錄:

{
    "results": [
        {
            "objectId": "1r2sFIzSRP",
            "username": "xxx",
            "createdAt": "2019-02-16T10:30:00.070Z",
            "updatedAt": "2019-02-16T10:30:00.070Z",
            "ACL": {
                "*": {
                    "read": true
                },
                "1r2sFIzSRP": {
                    "read": true,
                    "write": true
                }
            }
        }
    ]
}

重點功能介紹

權限控制

Parse Server的權限控制分爲兩層: Class level permission(類級別的權限控制)、Object level access control(對象級別的權限控制)。

圖片描述

async function saveData() {
  const Student = Parse.Object.extend("Student");
  const student = new Student();

  student.setACL(new Parse.ACL(Parse.User.current()));
  student.set("name", "小明");
  student.set("age", 12);

  const result = await student.save();
  console.log('save data: ', result);
}
async function getData() {
  const Student = Parse.Object.extend("Student");
  const query = new Parse.Query(Student);
  query.equalTo('name', '小明');
  const result = await query.find();
  console.log('save data: ', result);
}

async function run() {
  await saveData();
  await getData(); // 獲得一條數據
  await Parse.User.logOut();
  // 用另外一個賬號登錄
  await getData(); // 結果爲空
}

上述示例設置了 Object level access control ,只有擁有該 object 權限的用戶,才能獲取對應的數據。

數據的實時通信

要實現數據的實時通信,通常的做法是搭建一個websocket服務,客戶端與服務端建立長連接,這樣就可以實現數據的實時通信。Parse Server 也集成了這個功能,把websocket服務跟HTTP服務整合在一起,便於 client 端統一調用。

圖片描述

Class的schema問題

因爲 Parse Server 背後的數據存儲使用的是 MongoDB,數據格式是 schemaless 的, 但是這並不是說可以隨意寫入數據:

  • 第一次創建 Class 的時候,可以自定義字段及類型,同時默認添加 _id、_created_at、_updated_at、_acl 等字段
  • 同時,在底層數據中,存在一個 _SCHEMA 集合,存儲了 Class 的格式信息,約束了數據再次寫入時的字段類型

爲了驗證上述兩點,直接登錄 MongoDB 數據庫後臺:

// step1: 登錄數據庫後臺
mongo

// step2: 查看 collection 情況
show collections
結果如下: 
Student
_Role
_SCHEMA
_Session
_User

// step3: 查看 _SCHEMA 內容
db.getCollection('_SCHEMA').find()
結果如下:
{
    "_id":"Student",
    "objectId":"string",
    "updatedAt":"date",
    "createdAt":"date",
    "name":"string",
    "age":"number",
    "address":"string"
}
...

接下來對Student表進行寫入操作,age的類型不是number,而使用string:

async function saveData() {
  const Student = Parse.Object.extend("Student");
  const student = new Student();

  student.setACL(new Parse.ACL(Parse.User.current()));
  student.set("name", "張三");
  student.set("age", '9999');
  student.set('address', '北京');

  const result = await student.save();
  console.log('save data: ', result);
}

執行上述代碼,會拋出異常信息 schema mismatch for Student.age; expected Number but got String

Cloud Code / HOOK 機制 - 實現自定義業務邏輯

如果進行業務開發,肯定存在自定義的業務邏輯,Parse Server 同樣提供了對應的解決途徑。

先來看看 Cloud Code 是如何工作的:

// step1 在Parse Server入口處指定路徑
var api = new ParseServer({
  ...
  cloud: './cloud/main.js',
  ...
});
// step2 定義一般的Function
Parse.Cloud.define("averageStars", async (request, response) => {
  const params = request.params;
  ...
  const result = ...
  response.success(result);
});
// 定義hook函數
Parse.Cloud.beforeSave("Student", (request) => {
  ...
});
// step3 客戶端調用自定義函數方式
async function invokeFn() {
  const params =  {  ... };
  const ratings = await Parse.Cloud.run("averageStars", params);
  console.log('ratings: ', ratings);
}
// 客戶端出發hook比較簡單,對Student進行寫入,就會觸發hook函數
async function saveData() {
  const Student = Parse.Object.extend("Student");
  const student = new Student();
  ...
  const result = await student.save();
}

同時,Parse Server 也支持遠程調用,使用 Dashboard 的 Webhook功能,就可以配置遠程調用API

圖片描述

思考總結

Parse Server這個開源項目給了不少項目設計上的思考:

  • 具體功能抽象,把一些常用功能抽象出來,是研發提效的一個很重要的手段
  • server + client模式,抽象出業務模型之後,如果只是解決了某一部分的問題(例如server),使用成本依然很高,但是如果解決更多鏈路上的問題,那就會變得更加容易使用和落地。Parser Server不僅提供了server端的實現,而且提供了Dashboard、Client、Adapter等內容
  • hook功能,用於解決個性化需求,滿足業務定製
  • 與雲的結合,目前已成爲未來技術選型的一個很大趨勢,Parse Server 的文件存儲,提供了很多雲存儲相關的 Adapter,快速實現跟雲產品的對接
  • 權限控制設計,數據的安全已經成爲研發很重要的一個工作,分級控制是個思路
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章