国产精品chinese,色综合天天综合精品网国产在线,成午夜免费视频在线观看,清纯女学生被强行糟蹋小说

    <td id="ojr13"><tr id="ojr13"><label id="ojr13"></label></tr></td>
        • <source id="ojr13"></source>
            <td id="ojr13"><ins id="ojr13"><label id="ojr13"></label></ins></td>

            當前位置:文章中心>技術(shù)教程
            公告通知 新聞快遞 技術(shù)教程 產(chǎn)品展示

            優(yōu)化托管于阿里云函數(shù)計算的Node.js應(yīng)用 - 以Parse為例

            發(fā)布時間:2022-02-22 點擊數(shù):866

            上文介紹了怎么快速搬遷Parse到阿里云函數(shù)核算,可是這只是一個跑起來的比如,還有一些問題需求咱們優(yōu)化。本文會介紹常見的優(yōu)化點和辦法,從辦法來看適用于一切Serverless渠道的應(yīng)用。

            Serverless的缺陷

            沒有任何技能形狀是完美的,Serverless供給了杰出的可伸縮性和并發(fā)性,供給了細粒度的資源分配,優(yōu)化了成本,相對的也有難以調(diào)試等缺點。

            這些問題是Serverless這種技能形狀本身形成的,并不是阿里云函數(shù)核算獨有的。不同的云廠商能夠經(jīng)過周邊建設(shè)來補償一些問題,比如阿里云函數(shù)核算的日志和監(jiān)控相對比較完善,Serverless Devs工具處理了一部分調(diào)試問題。

            用更傳統(tǒng)的觀點來了解Serverless的本質(zhì),能夠看作擴容縮容戰(zhàn)略極端激進的集群,而每個函數(shù)都是布置在這一個一個機器上罷了。云廠商的機器特別迷你,計價單位顆粒小。而縮容戰(zhàn)略能夠?qū)?,擴容戰(zhàn)略能夠近乎無限大,縮容戰(zhàn)略是固定,不能夠自定義。

            那么對于一個隨時可能創(chuàng)建隨時可能被毀掉的機器,布置于其間的服務(wù)要面臨兩個方面的問題

            • 服務(wù)毀掉
            • 服務(wù)發(fā)動

            服務(wù)毀掉時內(nèi)存、文件體系的數(shù)據(jù)都丟失了。服務(wù)發(fā)動的時分需求一些必要的初始化,需求發(fā)動程序。

            咱們先看下毀掉引起的耐久化問題。

            耐久化改善

            Parse是支撐文件上傳的,存儲文件的FileAdapter是能夠自定義的。

            一般來說對于文件需求,能夠直接運用阿里云目標存儲OSS,一般挑選標準型就能夠了。


            aliyun-oss-price.png

            Parse官方不支撐阿里云OSS,理論上能夠運用parse-server-s3-adapter,可是我之前沒有配置過,能夠完全能夠自定義,直接運用OSS官方的SDK就行了。


            'use strict';  var OSS = require('ali-oss').Wrapper; const DEFAULT_OSS_REGION = "oss-cn-hangzhou";  function requiredOrFromEnvironment(options, key, env) {  options[key] = options[key] || process.env[env];  if (!options[key]) {  throw `OSSAdapter requires option '${key}' or env. variable ${env}`;  }  return options; }  function fromEnvironmentOrDefault(options, key, env, defaultValue) {  options[key] = options[key] || process.env[env] || defaultValue;  return options; }  function optionsFromArguments(args) {  let options = {};  let accessKeyOrOptions = args[0];  if (typeof accessKeyOrOptions == 'string') {  options.accessKey = accessKeyOrOptions;  options.secretKey = args[1];  options.bucket = args[2];  let otherOptions = args[3];  if (otherOptions) {  options.bucketPrefix = otherOptions.bucketPrefix;  options.region = otherOptions.region;  options.directAccess = otherOptions.directAccess;  options.baseUrl = otherOptions.baseUrl;  options.baseUrlDirect = otherOptions.baseUrlDirect;  }  } else {  options = accessKeyOrOptions || {};  }  options = requiredOrFromEnvironment(options, 'accessKey', 'OSS_ACCESS_KEY');  options = requiredOrFromEnvironment(options, 'secretKey', 'OSS_SECRET_KEY');  options = requiredOrFromEnvironment(options, 'bucket', 'OSS_BUCKET');  options = fromEnvironmentOrDefault(options, 'bucketPrefix', 'OSS_BUCKET_PREFIX', '');  options = fromEnvironmentOrDefault(options, 'region', 'OSS_REGION', DEFAULT_OSS_REGION);  options = fromEnvironmentOrDefault(options, 'directAccess', 'OSS_DIRECT_ACCESS', false);  options = fromEnvironmentOrDefault(options, 'baseUrl', 'OSS_BASE_URL', null);  options = fromEnvironmentOrDefault(options, 'baseUrlDirect', 'OSS_BASE_URL_DIRECT', false);   return options; }  function OSSAdapter() {  var options = optionsFromArguments(arguments);  this._region = options.region;  this._bucket = options.bucket;  this._bucketPrefix = options.bucketPrefix;  this._directAccess = options.directAccess;  this._baseUrl = options.baseUrl;  this._baseUrlDirect = options.baseUrlDirect;   let ossOptions = {  accessKeyId: options.accessKey, accessKeySecret: options.secretKey, bucket: this._bucket, region: this._region  };  this._ossClient = new OSS(ossOptions);  this._ossClient.listBuckets().then((val) => {  var bucket = val.buckets.filter((bucket) => {  return bucket.name === this._bucket  }).pop();   this._hasBucket = !!bucket;  }); }  OSSAdapter.prototype.createBucket = function () {  if (this._hasBucket) {  return Promise.resolve();  } else {  return this._ossClient.putBucket(this._bucket, this._region).then(() => {  this._hasBucket = true;  if (this._directAccess) {  return this._ossClient.putBucketACL(this._bucket, this._region, 'public-read');  }  return Promise.resolve();  }).then(() => {  return this._ossClient.useBucket(this._bucket, this._region);  });  } };  OSSAdapter.prototype.createFile = function (filename, data, contentType) {  let options = {};  if (contentType) {  options.headers = {'Content-Type': contentType}  }  return this.createBucket().then(() => {   return this._ossClient.put(this._bucketPrefix + filename, new Buffer(data), options);   }); };  OSSAdapter.prototype.deleteFile = function (filename) {  return this.createBucket().then(() => {  return this._ossClient.delete(this._bucketPrefix + filename);  }); };  OSSAdapter.prototype.getFileData = function (filename) {  return this.createBucket().then(() => {  return this._ossClient.get(this._bucketPrefix + filename).then((val) => {  return Promise.resolve(val.content);  }).catch((err) => {  return Promise.reject(err);  });  }); };  OSSAdapter.prototype.getFileLocation = function (config, filename) {  var url = this._ossClient.signatureUrl(this._bucketPrefix + filename);  url = url.replace(/^http:/, "https:");  return url; };  module.exports = OSSAdapter; module.exports.default = OSSAdapter;

            這個是我正在用的adapter,能夠參閱運用。特別是getFileLocation,要根據(jù)自己情況運用。

            Parse還有一個緩存,一般默許運用本地環(huán)境,可是考慮到Serverless的特性,這一部分還是要耐久化用于加快。官方供給的RedisCacheAdapter能夠直接運用。Redis集群要求不是很高,最好復用已有的,單獨運用成本有點高。


            發(fā)動改善


            Serverless函數(shù)的生命周期問題一直是搬遷的阻止,比較明顯的是異步懇求丟失、高雅下線困難。阿里云函數(shù)核算對于模型有必定擴展,額定供給了一些Hook。


            aliyun-function-model.png


            初始化只會進行一次,preFreeze和preStop便是退出前的Hook,這三處也是同樣的計費。


            因為Parse也涉及到數(shù)據(jù)庫銜接,所以能夠?qū)?shù)據(jù)庫銜接部分移動到initialize中。

            除了生命周期上一般來說還有一些挑選


            提升內(nèi)存分配:函數(shù)核算能夠自行配置內(nèi)存,對于部分應(yīng)用(特別是有初始化掃描等)加大內(nèi)存能夠改善發(fā)動速度


            調(diào)整結(jié)構(gòu)或者渠道:對于NodeJs而言,新版別普遍都有性能上的優(yōu)化,選用盡可能新的NodeJs版別也能夠加快發(fā)動。假如實在對時刻很靈敏,可能要考慮Rust等發(fā)動速度更友好的語言。


            在發(fā)動函數(shù)中初始化更多的共享資源:這個其實不能處理第一次冷發(fā)動的時刻,可是能夠讓每次call的耗時更少。


            減縮包大小:對于不必要的三方庫優(yōu)先移除,也能夠運用更精簡的版別進行替換。


            定時激活:這個最早在AWS Lambda上廣泛運用,其實本質(zhì)上是保存一個常駐實例,可是依靠的云廠商的機制。比如AWS Lambda大約30-40分鐘收回之前的活躍實例。這樣只需求一個定時觸發(fā)器就能夠進行激活操作。這個辦法在一切Serverless渠道都能夠運用??墒切枨笳_處理來自HTTP觸發(fā)器和Event觸發(fā)器的邏輯。