## 概述 选择阿里云作为服务商时,服务空间资源完全免费,每个账号最多允许创建50个服务空间。**阿里云目前处于公测阶段,如有正式业务对稳定性有较高要求建议使用腾讯云。** 选择腾讯云作为服务商时,可以创建一个免费的服务空间,资源详情参考[腾讯云免费额度](uniCloud/price?id=price-free);如想提升免费空间资源配额,或创建更多服务空间,则需付费购买。 付费用户享受腾讯云提供的服务协议SLA,[详见](https://uniapp.dcloud.net.cn/uniCloud/agreement) uniCloud的腾讯云版的定价、套餐内容、服务SLA,是由腾讯公司直接公布的。DCloud公司不会加价,包括开发者通过DCloud充值也会直接充到开发者在腾讯云建立的子账户下。DCloud只从腾讯云等云厂商获取返佣,也不会在未来加价收割开发者。 uniCloud提供包月、按量计费两种计费方式(仅腾讯云),具体说明如下: |计费方式 |付费方式 |计费单位 | |:-: |:-: |:-: | |包月 |预付费 |参考 [腾讯云包月套餐](uniCloud/price?id=price-month) | |按量计费 |结算时冻结费用,每日结算 |参考 [腾讯云按量计费](uniCloud/price?id=price-info)| ## 阿里云@aliyun 阿里云的服务空间是纯免费的。但为避免资源滥用,有一些限制,见下。 |资源类目 |限制 |说明 | |:-: |:-: |:-: | |云函数并发限制 |1000个实例/服务空间|实际普通项目很难达到这个并发数,阿里云可以设置单实例多并发单实例最多100,理论最大并发量1000*100=100000 (10万),关于单实例多并发请参考:[单实例多并发](uniCloud/cf-functions.md?id=concurrency) | |每个服务空间的云函数数量 |48个 |实际项目中由于clientDB和单路由云函数,只会用到几个云函数,达不到限制数字。[详见](https://uniapp.dcloud.net.cn/uniCloud/faq?id=merge-functions) | |云函数定时触发最小间隔 |1小时 |- | |云存储容量 |10GB |- | |云数据库容量 |100GB |- | |单次数据库执行时长限制 |5秒 |**不可申请调整** | 尤其注意阿里云的cdn确实是全免费的,这些免费资源可用于正常公司业务,阿里云不允许开发者使用这些免费的存储及CDN资源来开展图床类业务。 除上面的描述外,阿里云没有其他限制。 因为阿里云免费向DCloud提供了硬件资源,所以DCloud也没有向开发者收费。如果阿里云后续明确了收费计划,DCloud也会第一时间公布在这里。 如有超大型应用突破阿里云资源限制,请发邮件到service@dcloud.io请求协助,可以特批扩大资源。 申请邮件内需要提供以下信息 ``` 公司信息 // 个人用户无须此项 负责人 联系电话 公司介绍 // 个人用户无须此项 业务场景 // 与申请资源相关的业务场景,包括应用名称及发布平台 用户规模 申请spaceId 申请资源 // 要具体到申请资源量,例如:云存储要写明申请多大、定时触发要写明申请的触发频率 申请日期 ``` ## 腾讯云@tencent **使用腾讯云Nodejs12版本时,务必仔细阅读此文档:[keepRunningAfterReturn](uniCloud/cf-functions.md?id=keep-running)** 为了给各位用户提供更加优质可靠的产品服务,腾讯云计划将于2022年8月12日,对计费方式进行如下升级: 新计费模式下,统一采用**基础套餐+按量计费**的模式,开发者可先购买带有一定配额的基础套餐,超出套餐配额部分按使用量付费。 ### 基础套餐@tencent-package | 配额 | 个人版 | 入门版| 初创版 | 商用版 | 团队版 | 单位 | | --- | --- | --- | --- | --- | --- | --- | | QPS | 500 | 500 | 500 | 800 | 1000 | - | | 调用次数 | 20 | 500 | 1000 | 2000 | 5000 | 万次 | | 容量 | 2 | 30 | 100 | 200 | 300 | GB | | 云函数资源使用量| 10 | 30 | 45 | 60 | 100 | 万GBs | | 云函数外网出流量| 2 | 8 | 10 | 15 | 25 | GB | | CDN流量 | 5 | 80 | 200 | 400 | 600 | GB | | CDN回源流量 | 5 | 40 | 100 | 200 | 300 | GB | | 价格 | **~~39.9~~ 19.9** | **99**| **299** | **499** | **999** | 元/月 | 1. 个人版5折折扣至少延续至2022年底,后续折扣如有变化将另行通知。 2. **调用次数**:包含云存储上传、下载操作;数据库读、写操作;云函数调用次数。 3. **容量**:包含云存储、数据库容量。 4. **CDN流量**、**CDN回源流量**:仅包含云存储,不含前端网页托管 5. 开通基础套餐时可以选择是否允许超量,开启后如果用量超出套餐配额将按照按量付费定价进行收费 6. 前端网页托管开通后即为按量计费,不管服务空间有没有开启允许超量使用,前端网页托管计费参考[高级功能按量计费](#tencent-advanced) ### 按量付费/超量使用定价@tencent-postpay | 计费项 | 定价 | | --- | --- | | 调用次数 | 0.5元/万次/天 | | 容量 | 0.1元/GB/天 | | 云函数资源使用量| 0.00011108元/GBs| | 云函数外网出流量| 0.8元/GB | | CDN流量 | 0.21元/GB | | CDN回源流量 | 0.15元/GB | ### 高级功能按量计费定价@tencent-advanced | 计费项 |计费项 |定价 | | --- | --- |--- | |前端网页托管 |容量 |0.005元/GB/天 | | |流量 |0.21元/GB | |日志服务 |标准索引存储 |0.0115元/GB/日 | | |标准日志存储 |0.0115元/GB/日 | | |标准索引流量 |0.35元/GB/日 | | |写流量 |0.18元/GB/日 | | |请求次数 |0.15元/百万次/日 | | |分区数量 |0.04元/个/日 | - 在正式进行计费方式切换之日起,用户将不可继续续费或新购旧版套餐或按量计费服务空间。用户可选择是否切换新的计费方式,超时(2022.09.08)切换的服务空间将会停服释放。 **注:当包年包月服务空间升级新套餐时,如果已开通前端网页托管,则前端网页托管会自动转为按量计费,请确保账号余额充足!** ## 发生故障时如何判断故障点 当你的线上系统故障时,可以参考此文档判断责任归属:[如何判断是DCloud或阿里云或腾讯云的问题](https://uniapp.dcloud.io/uniCloud/faq?id=fault) ## 云厂商之间的迁移@cross-provider ### 数据库迁移@cross-provider-db 目前可以使用云数据库的导入导出进行迁移,迁移数据库之前可以使用导出db_init.json功能将所有集合及索引导出。再使用数据导入导出功能进行迁移。导入导出请参考:[数据导入导出和备份](uniCloud/hellodb.md?id=dbmigration) > 也可以直接使用第三方封装好的插件:[unicloud数据库一键搬家工具,支持阿里云与腾讯云互转。支持跨账号转。](https://ext.dcloud.net.cn/plugin?id=6089) #### 腾讯云迁移到阿里云@tencent-to-aliyun-db 迁移数据可以通过在腾讯云服务空间导出数据表为json文件,在阿里云服务空间导入json文件到表的方式进行迁移。 #### 阿里云迁移到腾讯云@aliyun-to-tencent-db 由于此前腾讯云并未完全支持ObjectId类型的数据,在阿里云迁移到腾讯云时需要注意处理一下`ObjectId`类型的数据,包括自动生成的_id字段以及关联到其他表的_id的字段。简单来说就是将导出的数据内的ObjectId类型的数据处理成字符串且不满足ObjectId的格式。 例: ```js // 原始数据 {"_id":{"$oid":"60fa6d25cd84d60001ec38a2"},"uid":{"$oid":"60fa6d1d2e5faa0001ade857"}} // 调整后的数据 {"_id":"60fa6d25cd84d60001ec38a2a","uid":"60fa6d1d2e5faa0001ade857a"} // 在结尾追加了一个“a”使其不满足ObjectId格式 ``` 以下为一个简单的脚本示例用于处理导出的json文件 如果将此文件存储为`parse.js`,使用`node parse.js 输入文件相对或绝对路径 输出文件相对或绝对路径`即可处理导出的json文件 ```js const fs = require('fs') const path = require('path') const readline = require('readline') const cwd = process.cwd() const inputPath = path.resolve(cwd, process.argv[2]) const outputPath = path.resolve(cwd, process.argv[3]) if (fs.existsSync(outputPath)) { throw new Error(`输出路径(${outputPath})已存在`) } function getType(val) { return Object.prototype.toString.call(val).slice(8, -1).toLowerCase() } function parseRecord(obj) { const type = getType(obj) switch (type) { case 'object': if (obj.$oid) { return obj.$oid + 'a' } const keys = Object.keys(obj) for (let i = 0; i < keys.length; i++) { const key = keys[i]; obj[key] = parseRecord(obj[key]) } return obj case 'array': for (let i = 0; i < obj.length; i++) { obj[i] = parseRecord(obj[i]) } return obj default: return obj } } async function parseCollection() { const inputStream = fs.createReadStream(inputPath) const outputStream = fs.createWriteStream(outputPath) const rl = readline.createInterface({ input: inputStream }); for await (const line of rl) { const recordStr = line.trim() if (!recordStr) { continue } const record = parseRecord(JSON.parse(recordStr)) outputStream.write(JSON.stringify(record) + '\n') } rl.close() console.log(`处理后的文件已输出到${outputPath}`) } parseCollection() ```