关于HUX素材管理项目的一些思考

不同阶段应该有不同的套路

比如开发阶段,应该有一个地方可以查看到所有常用链接的地址,方便大家进行调试。

比如进入 BUG 修改阶段,就应该先创建一个石墨文档,然后及时跟进 BUG 修复的进度,保证大家(需求方、开发人员、测试人员)信息透明。

比如这次的 BUG 修复日志,就很有用:

https://shimo.im/docs/j6rJrhvhhrx8qGpj

为什么项目实际开发时间远大于评估时间?

为什么这个项目 BUG 这么多?

技术经验

获取用户的真实 IP

由于用户请求我们的接口,经过了好几次中转(用户->域名服务器的 nginx->docker 内部的 nginx->node 服务),因此必须在每一个 nginx 的配置中,转发请求的时候,把代理请求的 IP 信息加上去才行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 配置文件.builddep\prod\nginx\vhosts\web.conf
location /resource/api/{
root /var/www/resource/server;
# 下面这三行
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_max_temp_file_size 0;
proxy_pass http://resource-server/;
proxy_redirect off;
proxy_read_timeout 240s;
client_max_body_size 1000m;
}

Egg.js 项目的上传文件大小限制

一般需要修改 3 个地方:

Nginx:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 配置文件.builddep\prod\nginx\vhosts\web.conf
location /resource/api/{
root /var/www/resource/server;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_max_temp_file_size 0;
proxy_pass http://resource-server/;
proxy_redirect off;
proxy_read_timeout 240s;
# 加这一行即可
client_max_body_size 1000m;
}

另外还需要修改这个地方,把 client_body_buffer_size 设置大一些:

1
2
3
4
5
6
7
server {
listen 80;
server_name localhost datav.iwencai.com;
fastcgi_intercept_errors on;
# 需要把这个数值设置大一些
client_body_buffer_size 100m;
}

如果不设置 client_body_buffer_size,当上传文件较大时,会将文件存入 client_body_temp 目录,而如果没有给该目录设置权限,就会导致 500 报错:

1
2020/09/22 17:09:20 [crit] 178#0: *46065 open() "/usr/local/openresty/nginx/client_body_temp/0000000012" failed (13: Permission denied), client: 192.168.201.236, server:localhost, request: "POST /resource/api/file/upload HTTP/1.0", host: "hot_upstream_balancer", referrer: "http://datav.iwencai.com/resource/page/index.html"

Nginx 分配给请求数据的 Buffer 大小,如果请求的数据小于 client_body_buffer_size 直接将数据先在内存中存储。如果请求的值大于 client_body_buffer_size 小于 client_max_body_size,就会将数据先存储到临时文件中,在哪个临时文件中呢?
client_body_temp 指定的路径中,默认该路径值是/tmp/.
所以配置的 client_body_temp 地址,一定让执行的 Nginx 的用户组有读写权限。否则,当传输的数据大于 client_body_buffer_size,写进临时文件失败会报错。

Egg.js:

1
2
3
4
5
6
7
// config.default.js
const config = (exports = {
multipart: {
fields: 50, //表单上传字段限制的个数
fileSize: '10mb', //文件上传的大小限制
},
});

Egg.js 设置 cookie 是很方便的:

1
2
3
4
5
6
7
8
9
10
// wrong
// const isAdmin = true;

// right
const isAdmin = 'true';
ctx.cookies.set('is_admin', isAdmin, {
httpOnly: false,
signed: false,
maxAge: 86400000,
});

但是一定要注意,设置的 cookie 的值,必须是字符串,不能是诸如 boolean 这样的值,否则会导致设置的 cookie 的值是空的,永久失效,进而前端无法获取你想要的 cookie 信息。

forEach 无法实现 sleep 的问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function myPromise() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 1000);
});
}

function forEach() {
const arr = [1, 2, 3];
arr.forEach(async (d) => {
await myPromise();
console.log(`I am in forEach : ${d}`);
});
}

async function forI() {
const arr = [1, 2, 3];
for (let i = 0; i < arr.length; i++) {
await myPromise();
console.log(`I am in for : ${arr[i]}`);
}
}

// 不能sleep
forEach();

// 可以sleep
forI();