0%

@[toc](Nginx 配置大文件上传)

nginx问题

遇到的问题:

  • Nginx: 413 – Request Entity Too Large Error and Solution
  • TIMEOUT

解决方法

解决方法:在nginx的配置文件下(通常为xxx.conf),加上以下配置:

1
2
3
4
5
6
client_max_body_size     50m;  # 限制请求体的大小,若超过所设定的大小,返回413错误,默认1m
client_header_timeout 1m; # 读取请求头的超时时间,若超过所设定的大小,返回408错误
client_body_timeout 1m; # 读取请求实体的超时时间,若超过所设定的大小,返回413错误
proxy_connect_timeout 60s; # http请求无法立即被容器(tomcat, netty等)处理,被放在nginx的待处理池中等待被处理。此参数为等待的最长时间,默认为60秒,官方推荐最长不要超过75秒
proxy_read_timeout 1m; # http请求被容器(tomcat, netty等)处理后,nginx会等待处理结果,也就是容器返回的response。此参数即为服务器响应时间,默认60秒
proxy_send_timeout 1m; # http请求被服务器处理完后,把数据传返回给Nginx的用时,默认60秒
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
listen 80;
server_name localhost;

client_max_body_size 10m;
client_header_timeout 5m;
client_body_timeout 5m;
proxy_connect_timeout 6000s;
proxy_read_timeout 5m;
proxy_send_timeout 5m;

location / {
# ...
}
}

重启nginx

设置完成后,需要使用 reload 或者reload重启nginx

正确设置PORT端口(windows/mac)

在跑lesson5的时候,有部分同学会遇到以下错误,这是由于不同系统,所执行的命令代码有所差异。
查看图片:​​
https://imgconvert.csdnimg.cn/aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy85NDE4MjkyLTVmMDYxYjRlYzI1NWJkY2YucG5n

MAC/linux环境:

1
$ PORT=8081 npm start

使用上面命令每次都需要重新设置

如果想设置一次永久生效,使用下面的命令。

1
$ export PORT=8081
1
$ npm start

Window系统环境,按照顺序这样进行:

1
$ set PORT=8081
1
$ npm start

关闭命令行窗口后,端口的配置会失效

发布npm包

注册并在本机添加npm用户(已注册可忽略)

完成了上面的步骤之后,我们接下来要在www.npmjs.com注册一个账号,这个账号会被添加到npm本地的配置中,下面命令行将会使用到。

1
2
3
4
5
//前提已完成npm用户的注册
$ npm adduser
Username: your name
Password: your password
Email: yourmail@gmail.com

如果出现以下错误,可能是你的npm版本太低,通过sudo npm install -g npm升级一下。

1
2
3
4
5
6
7
8
9
npm WARN adduser Incorrect username or password
npm WARN adduser You can reset your account by visiting:
npm WARN adduser
npm WARN adduser http://admin.npmjs.org/reset
npm WARN adduser
npm ERR! Error: forbidden may not mix password_sha and pbkdf2
npm ERR! You may need to upgrade your version of npm:
npm ERR! npm install npm -g
npm ERR! Note that this may need to be run as root/admin (sudo, etc.)

成功之后,npm会把认证信息存储在~/.npmrc中,并且可以通过以下命令查看npm当前使用的用户:

1
$ npm whoami

以上完成之后,我们终于可以发布自己包了。

发布

1
$ npm publish

删除

1
$ npm unpublish --force //强制删除
1
$ npm unpublish guitest@1.0.1 //指定版本号
1
$ npm deprecate //某些情况

promise用法

对比传统回调函数与Pormise的写法

传统回调函数

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
30
31
32
33
34
35
36
// 声明函数
function run(callback) {
let parmas = 0;
if (callback) callback(parmas);
};
function fnStep1(callback) {
let parmas = 123;
if (callback) callback(parmas);
};
function fnStep2(callback) {
let parmas = 456;
if (callback) callback(parmas);
};
function fnStep3(callback) {
let parmas = 789;
if (callback) callback(parmas);
};
// fnStep4 ...

// 传统使用回调的写法
run(function (parmas) {
// parmas = 0
console.log(parmas);
fnStep1(function (parmas1) {
// parmas = 123
console.log(parmas1);
fnStep2(function (parmas2) {
// parmas = 456
console.log(parmas2);
fnStep3(function (parmas3) {
// ...
// 一直嵌套
});
});
});
});

Promise的写法

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
30
31
32
33
34
35

let p = new Promise((resolve, reject) => {
// ?异步操作,最终调用:
//
const parmas = 0;
resolve(parmas); // fulfilled
// ?或
// reject("failure reason"); // rejected
})

p
.then(
(parmas) => {
// parmas,resolve返回的值
console.log(parmas);
// 你的代码块 code...
return 123; //返回值给下一个then
}
)
.then(
(parmas) => {
// parmas,上一个then返回的值
console.log(parmas);
// 你的代码块 code...
return 456; //返回值给下一个then
}
)
.then(
(parmas) => {
// parmas,上一个then返回的值
console.log(parmas);
// 你的代码块 code...
return 789; //返回值给下一个then
}
)

Promise要比传统回调函数更简洁直观,可读性更强。

那如何使用Promise进行异步回调? 如何捕获错误?

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
30
31
32
33
34
35
36
37
38
// 声明函数
function asyncFn(a) {

return new Promise((resolve, reject) => {
a += 1;
setTimeout(function () {
// 使用resolve则返回a
resolve(a);
// 使用reject则返回错误,并结束then的继续向下执行,并会跳到catch
// reject(new Error("fail"));
}, 2000);
});

}

// 执行
asyncFn(1).then(
(a) => {
// 过了2秒后接收到a值 => 2
console.log(a);

const newVal = 5;
// const newVal = {a: 5};
// const newVal = new Promise((resolve, reject) =>{});
// 返回值可以是数字,字串,对象或者是 Promise
return newVal;
}
).then(
(newVal) => {
// newVal 获得上一个then返回的值 或 返回的Promise的返回值

}
).catch(
(err)=>{
// 如用到reject,则会直接跳到此处
console.log(err)
}
);

SQL 语言功能划分

SQL 语言按照功能划分成以下的 4 个部分

  1. DDL,Data Definition Language,也就是数据定义语言

定义数据库对象,包括数据库、数据表和列。
通过使用 DDL,可以创建,删除和修改数据库和表结构。(CUD)

2. DML,Data Manipulation Language,数据操作语言
操作和数据库相关的记录。
增加、删除、修改数据表中的记录。

3. DCL,Data Control Language,数据控制语言
定义访问权限和安全级别。
4. DQL,Data Query Language,数据查询语言
语言的重中之重。
用它查询想要的记录。

SQL 大小写约定

MySQL在默认情况下是否区分大小写,也和操作系统有关。
在Linux下,MySQL对表名和数据库名是区分大小写的。
在Windows下,MySQL默认情况是不区分大小写的
Oracle中,SQL语句是不区分大小写,如果查询中有字符,是区分大小写的

关于 SQL 大小写的问题,约定下面两点:

  1. 表名、表别名、字段名、字段别名等都小写;
  2. SQL 保留字、函数名、绑定变量等都大写。

UTF8字符集

在这里插入图片描述

  • 字符集是 utf8,排序规则是utf8_general_ci,代表对大小写不敏感,如果设置为utf8_bin,代表对大小写敏感
  • 数据表的存储规则默认采用 InnoDB

是否使用外键

具体看看以下的观点,是否符合你当前的项目场景。

  • 首先,外键本身是为了实现强一致性,所以如果需要正确性>性能的话,还是建议使用外键,它可以让我们在数据库的层面保证数据的完整性和一致性。

  • 当然不用外键,你也可以在业务层进行实现。不过,这样做也同样存在一定的风险,因为这样,就会让业务逻辑会与数据具备一定的耦合性。也就是业务逻辑和数据必须同时修改。而且在工作中,业务层可能会经常发生变化。

  • 当然,很多互联网的公司,尤其是超大型的数据应用场景,大量的插入,更新和删除在外键的约束下会降低性能,同时数据库在水平拆分和分库的情况下,数据库端也做不到执行外键约束。另外,在高并发的情况下,外键的存在也会造成额外的开销。因为每次更新数据,都需要检查另外一张表的数据,也容易造成死锁。
    所以在这种情况下,尤其是大型项目中后期,可以采用业务层来实现,取消外键提高效率。

  • 不过在SQL学习之初,包括在系统最初设计的时候,还是建议你采用规范的数据库设计,也就是采用外键来对数据表进行约束。因为这样可以建立一个强一致性,可靠性高的数据库结构,也不需要在业务层来实现过多的检查。

  • 当然在项目后期,业务量增大的情况下,你需要更多考虑到数据库性能问题,可以取消外键的约束,转移到业务层来实现。而且在大型互联网项目中,考虑到分库分表的情况,也会降低外键的使用。

  • 不过在SQL学习,以及项目早期,还是建议你使用外键。在项目后期,你可以分析有哪些外键造成了过多的性能消耗。一般遵循2/8原则,会有20%的外键造成80%的资源效率,你可以只把这20%的外键进行开放,采用业务层逻辑来进行实现,当然你需要保证业务层的实现没有错误。不同阶段,考虑的问题不同。当用户和业务量增大的时候,对于大型互联网应用,也会通过减少外键的使用,来减低死锁发生的概率,提高并发处理能力。

  • 《阿里巴巴 Java 开发手册》28页第6条。SQL语句中 【强制】不得使用外键与级联,一切外键概念必须在应用层解决。 外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻 塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。