编码

主要差异点:单进程 vs 多进程

  • Egg.js —— 单进程内模拟多进程机制,实现了上下文
  • Express.js —— HTTP 库,没有进程上下文,请求数据需要通过函数层层传递
  • Koa.js —— HTTP 库,没有进程上下文,请求数据需要通过函数层层传递
  • Java:Spring —— 多进程,有进程上下文
  • PHP: Laravel —— 多进程,有进程上下文

阅读更多

概述

阅读《Accelerated C++》时的笔记,记录下每一章使用的库函数。

第一章 使用字符串

本章介绍了两个标准库 iostreamstringiostream 处理输入输出流,string 包含针对字符串封装的一系列方法。

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <string>

std::string input;
std::cin >> input;
std::cout << "this is user input: " + input << endl;

std::string str = "this is a string";
std::string::size_type size = str.size();
str.substr(start, length);

阅读更多

在 JavaScript 编码过程中,对象作为引用传递存在被修改的情况,而我们更希望原始对象尽量不被修改,这样有利于对对象状态的追踪,这也与函数式编程中纯函数避免副作用的理念一致。以下两种方式用来创建一个新的对象用来进行操作并返回而不会修改原始对象。

利用 JSON.parse 与 JSON.stringify 创建新对象

1
2
3
4
5
6
7
8
// 避免修改他人传入的对象
function someOperation(originalObject) {
let _object = JSON.parse(JSON.stringify(originalObject));
_object.someKey = someValue;
return _object;
}
// 避免他人的函数修改自己的对象
someOperation(JSON.parse(JSON.stringify(originalObject)));

阅读更多

概述

async.parallelLimit 方法在文档中位于 Controll Flow 章节,表明这个方法是用来做流程控制的,async.eachLimit 方法位于 Collections 章节,表明这个方法是用来做数据处理的。在实际开发中我们可以使用这两个方法来完成同样的工作,下面我们就以给 26 位用户发送邮件这个任务来举例。

使用 async.parallelLimit 方法实现

async.parallelLimit 方法接受两个参数,第一个参数为任务数组,每个任务是一个函数,第二个参数为每次并行执行的任务数,第三个参数为回调函数。使用 async.parallelLimit 完成发送邮件任务的思路是先使用数据与所要做的任务,组装成任务数组交给 async.parallelLimit 方法去执行。

阅读更多

在实际生产环境中,避免不了有很多后台运行的任务和定时任务,对任务状态的监控与及时告警可以尽量减少程序出错时对用户造成的影响。针对常见的两种任务类型:定时任务、守护进程内批处理任务,利用 Node.js child_process 实现了任务状态的监控、重启与邮件告警。

思路

现在的互联网已经不是单机作战的时代了,分布式部署是非常常见的方式,一个项目中的任务可能运行在多台服务器上,我们的监控平台要做到重启某个任务就需要知道任务运行的具体服务器,针对这一个问题我们需要获取到任务与服务器关系的确切信息,所以每台运行任务的服务器需要在启动任务时向任务状态管理平台注册自己的信息。

任务状态的维护依赖于任务运行服务器的心跳上报,每个任务设置一个超时时间,在任务启动时向任务状态管理平台发送开始运行信号,在任务运行结束后向管理平台发送运行完成信号。任务管理平台根据任务设置的超时时间,在超时后仍然没有接收到任务完成信号则判定任务失败,将任务失败信号发送回任务运行的服务器。再有任务运行服务器自行处理,如重启任务或者结束任务等。

阅读更多

生产者

添加任务时将 value 设置为任务名称并携带序列化的参数 name@params, score 设置为任务开始执行的时间戳。在每次加入任务时首先判断任务是否已经存在,如果存在跳过处理,如果不存在将任务加入任务池。

阅读更多

需求:功能 A 需要调用第三方 API 获取数据,而第三方 API 自身是异步处理方式,在调用后会返回数据与状态 { data: "查询结果", "status": "正在异步处理中" },这样就需要间隔一段时间后再去调用第三方 API 获取数据。为了用户在使用功能 A 时不会因为第三方 API 正在异步处理中而必须等待,将用户请求加入任务队列中,返回部分数据并关闭请求。然后定时从任务队列里中取出任务调用第三方 API,若返回状态为”异步处理中“,将该任务再次加入任务队列,若返回状态为”已处理完毕“,将返回数据入库。

根据以上问题,想到使用 Node.js + Redis sorted set 来实现任务队列。Node.js 实现自身应用 API 用来接受用户请求,合并数据库已存数据与 API 返回的部分数据返回给用户,并将任务加入到任务队列中。利用 Node.js child process 与 cron 定时从任务队列中取出任务执行。

阅读更多

利用 Express 中间件功能实现登录拦截。如果用户请求的路径需要登录后才能访问,将用户重定向到登录页面,登录成功后将用户重定向到原始请求路径。

设置应用中间件,监控所有请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// app.js
app.use(function (req, res, next) {
if (req.session.user) { // 判断用户是否登录
next();
} else {
// 解析用户请求的路径
var arr = req.url.split('/');
// 去除 GET 请求路径上携带的参数
for (var i = 0, length = arr.length; i < length; i++) {
arr[i] = arr[i].split('?')[0];
}
// 判断请求路径是否为根、登录、注册、登出,如果是不做拦截
if (arr.length > 1 && arr[1] == '') {
next();
} else if (arr.length > 2 && arr[1] == 'user' && (arr[2] == 'register' || arr[2] == 'login' || arr[2] == 'logout')) {
next();
} else { // 登录拦截
req.session.originalUrl = req.originalUrl ? req.originalUrl : null; // 记录用户原始请求路径
req.flash('error', '请先登录');
res.redirect('/user/login'); // 将用户重定向到登录页面
}
}
});

阅读更多

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×