HI!, 你好, 我是 zane,zanePerfor 是一款最近我开发的一个前端性能监控平台, 现在支持 web 浏览器端和微信小程序段.
我定义为一款完整, 高性能, 高可用的前端性能监控系统, 这是未来会达到的目的, 现今的架构也基本支持了高可用, 高性能的部署. 实际上还不够, 在很多地方还有优化的空间, 我会持续的优化和升级.
开源不易, 如果你也热爱技术, 拥抱开源, 希望能小小的支持给个 star.
项目的 GitHub 地址:
https://github.com/wangweianger/zanePerfor
项目开发文档说明:
https://blog.seosiwei.com/performance/index.html
MongoDB 副本集架构
优势:
MongoDB 副本集 (Replica Set) 是有自动故障恢复功能的主从集群, 有一个 Primary 节点和一个或多个 Secondary 节点组成.
当主节点挂掉之后, 会由多个副本节点选举产生出新的主节点.(节点数请保持为基数个).
这样就能保证应用的高可用, 其中一个或多个节点挂掉之后还能正常运行和服务.
劣势:
数据丢失: 主节点挂掉之后, 副本节点选举出新的主节点需要一定的时间, 这段时间会造成数据的丢失.
不能完全保证项目的高可用: 在副本集的环境中, 要是所有的 Secondary 都宕机了, 只剩下 Primary. 最后 Primary 会变成 Secondary, 将不能再提供服务.
总结:
在大多数情况下推荐使用副本集架构, 副本集架构在保证高可用的同时还能降低服务器成本, 相对于集群分片来说配置也更简单, 更易于维护, 具体选择什么架构需要根据自己的项目来觉定.
MongoDB 副本集架构搭建:
MongoDB 副本集搭建比价简单, 你只需要根据下面的步骤一步一步操作即可(以下内容以 Linux 或 Mac 为例进行搭建).
一: 安装 MongoDB (略)
请参考: Linux 系统下安装 MongoDB https://blog.seosiwei.com/detail/40
关于副本集搭建还可参考我的另一篇文章: MongoDB 主从副本集架构 https://blog.seosiwei.com/detail/39
二: 副本集搭建
(备注: 鉴于成本, 以下内容在单机下部署为例, 多机部署只需要替换下 IP 即可)
1, 创建数据和日志存放目录
- // 数据存放目录
- mkdir -p /data/replication/s0
- mkdir -p /data/replication/s1
- mkdir -p /data/replication/s2
- // 日志存放目录
mkdir -p /data/replication/log
2, 启动 MongoDB 服务
- (下面以 28100,28101,28100 三个端口为例)
- // 启动 MongoDB 服务
- mongod --dbpath /data/replication/s0 --logpath /data/replication/log/s0.log --fork --smallfiles --port 28100 --replSet rs1
- mongod --dbpath /data/replication/s1 --logpath /data/replication/log/s1.log --fork --smallfiles --port 28101 --replSet rs1
mongod --dbpath /data/replication/s2 --logpath /data/replication/log/s2.log --fork --smallfiles --port 28102 --replSet rs1
--dbpath: 存放数据目录
--logpath: 存放日志目录
--smallfiles: 是否使用较小的默认文件. 默认为 false, 不使用.
--replSet: 副本集名称, 副本集名称必须一致
进入 28100 服务设置副本集
- // 登录 MongoDB
- mongo localhost:28100
- // 切换到 admin 用户
- use admin
- // 初始化副本集
- rs.initiate({
- _id:"rs1",members:[{
- _id:0,host:"127.0.0.1:28100"
- },{
- _id:1,host:"127.0.0.1:28101"
- },{
- _id:2,host:"127.0.0.1:28102"
- }]
- })
- // 查看副本集状态
rs.status()
副本集设置成功之后, 查看状态会看到如下信息即标识成功.
- {
- "set" : "rs1",
- "date" : ISODate("2018-11-14T08:40:44.659Z"),
- "myState" : 1,
- "term" : NumberLong(2),
- "heartbeatIntervalMillis" : NumberLong(2000),
- "optimes" : {
- "lastCommittedOpTime" : {
- "ts" : Timestamp(1542184835, 1),
- "t" : NumberLong(2)
- },
- "readConcernMajorityOpTime" : {
- "ts" : Timestamp(1542184835, 1),
- "t" : NumberLong(2)
- },
- "appliedOpTime" : {
- "ts" : Timestamp(1542184835, 1),
- "t" : NumberLong(2)
- },
- "durableOpTime" : {
- "ts" : Timestamp(1542184835, 1),
- "t" : NumberLong(2)
- }
- },
- "members" : [
- {
- "_id" : 0,
- "name" : "127.0.0.1:28100",
- "health" : 1,
- "state" : 1,
- "stateStr" : "PRIMARY",
- "uptime" : 5977,
- "optime" : {
- "ts" : Timestamp(1542184835, 1),
- "t" : NumberLong(2)
- },
- "optimeDate" : ISODate("2018-11-14T08:40:35Z"),
- "electionTime" : Timestamp(1542178880, 1),
- "electionDate" : ISODate("2018-11-14T07:01:20Z"),
- "configVersion" : 1,
- "self" : true
- },
- {
- "_id" : 1,
- "name" : "127.0.0.1:28101",
- "health" : 1,
- "state" : 2,
- "stateStr" : "SECONDARY",
- "uptime" : 5970,
- "optime" : {
- "ts" : Timestamp(1542184835, 1),
- "t" : NumberLong(2)
- },
- "optimeDurable" : {
- "ts" : Timestamp(1542184835, 1),
- "t" : NumberLong(2)
- },
- "optimeDate" : ISODate("2018-11-14T08:40:35Z"),
- "optimeDurableDate" : ISODate("2018-11-14T08:40:35Z"),
- "lastHeartbeat" : ISODate("2018-11-14T08:40:43.345Z"),
- "lastHeartbeatRecv" : ISODate("2018-11-14T08:40:43.603Z"),
- "pingMs" : NumberLong(0),
- "syncingTo" : "127.0.0.1:28102",
- "configVersion" : 1
- },
- {
- "_id" : 2,
- "name" : "127.0.0.1:28102",
- "health" : 1,
- "state" : 2,
- "stateStr" : "SECONDARY",
- "uptime" : 5970,
- "optime" : {
- "ts" : Timestamp(1542184835, 1),
- "t" : NumberLong(2)
- },
- "optimeDurable" : {
- "ts" : Timestamp(1542184835, 1),
- "t" : NumberLong(2)
- },
- "optimeDate" : ISODate("2018-11-14T08:40:35Z"),
- "optimeDurableDate" : ISODate("2018-11-14T08:40:35Z"),
- "lastHeartbeat" : ISODate("2018-11-14T08:40:43.345Z"),
- "lastHeartbeatRecv" : ISODate("2018-11-14T08:40:43.575Z"),
- "pingMs" : NumberLong(0),
- "syncingTo" : "127.0.0.1:28100",
- "configVersion" : 1
- }
- ],
- "ok" : 1,
- "operationTime" : Timestamp(1542184835, 1),
- "$clusterTime" : {
- "clusterTime" : Timestamp(1542184835, 1),
- "signature" : {
- "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
- "keyId" : NumberLong(0)
- }
- }
}
3, 设置 MongoDB 副本可读
在 Mac 和 Linux 系统中, 一般在~ 目录下会有个. mongorc.JS 文件, 给此文件新增一句 rs.slaveOk(); 即可.
查看是否有次文件:
cd ~
ll -a
若无, 则全局查找:
// 全局搜索
sudo find / -name .mongorc.JS
添加 rs.slaveOk();
- vi ~/.mongorc.JS
- // 此文件默认为空
- // 增加一行, 保存退出
rs.slaveOk();
重启 MongoDB, 这时所有副本节点都可读.
在 zanePerfor (前端性能监控平台)生产环境中使用, 并做读写分离.
一: 找到项目的 config/config.prod.JS 文件
更改如下 MongoDB 配置即可:
- // MongoDB 服务
- // 此处替换 url 参数为链接副本集方式即可
- const dbclients = {
- db3: {
- url: 'mongodb://127.0.0.1:28100,127.0.0.1:28101,127.0.0.1:28102/performance?replicaSet=rs1',
- options: {
- poolSize: 100,
- keepAlive: 10000,
- connectTimeoutMS: 10000,
- autoReconnect: true,
- reconnectTries: 100,
- reconnectInterval: 1000,
- },
- },
};
读写分离:
项目所有查询已经做好了读写分离操作, 例如查询 page 页列表, 其他皆如此即可, 这样就保证了服务的读写压力(主节点负责写数据, 副本节点负责读取数据).
read 参数说明
primary - (默认值) 只从主节点读取. 如果主节点不可用则报错. 不能跟 tags 选项组合使用.
secondary 只有当从节点可用时, 从中读取, 否则报错.
primaryPreferred 优先读取主节点, 不可用时读取从节点.
secondaryPreferred 优先读取从节点, 不可用时读取主节点.
nearest 所有操作都读最近的候选节点, 不同于其他模式, 该选项会随机选取所有主, 从节点.
选项别名:
- p primary
- pp primaryPreferred
- s secondary
- sp secondaryPreferred
n nearest
zanePerfor 下一步架构: MongoDB 集群分片架构.
zanePerfor GitHub 地址: GitHub.com/wangweiange...
zanePerfor 开发文档: blog.seosiwei.com/performance...
来源: https://juejin.im/post/5bebe4645188250b4816e482