简客-记忆

抽象的才是永恒的

0%

背景

每次百度这内容,都要花费我不少时间

客户端初始化

1
2
git config --global user.name "yourname"  
git config --global user.email "your@email.com"
1
ssh-keygen -t rsa -C "XXX@company.com"

在git服务器下的git主目录下面的.ssh文件下添加(修改)

1
authorized_keys

重新启动sshd

1
service sshd restart

背景

开始用vue写项目,可是用axios进行get操作没问题,进行post操作时,post的值始终没有传过来

直到搜索到“qs序列化”关键词,才发现其中的缘由

参考

Kouss博客 http://kouss.com/3884.html

内容

设置了headers中Content-Type为application/x-www-form-urlencoded数据格式,post发起的请求仍为json类型,并没有序列化。
郁闷的是用JSON.stringify无效。

这个Form Data后台取不到数据,正常的Form Data数据应该是key:val
最终解决方法:使用qs

1
2
3
4
5
6
7
8
9
10
var qs = require('qs')
Vue.prototype.$http = axios.create({
baseURL: 'http://chaozhi.hk',
timeout: 10000,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: [function (data) {
data = qs.stringify(data)
return data
}]
})

背景

早先在CPK项目时,因为有用户反应页面打不开,后来采用了CDN和静态页,那段时间也用ab测试工具测试过速度,但用了之后就没深入了解(主要是没写笔记做记录,忘记了)
之后因为离职去应聘时,一个面试官问过ab测试,且对我当时的一个开源项目进行了简单的压力测试。因为采用了pjax,没用静态页,首页的测试并不理想,之后打算着将TP的静态页部分改进下,满足pjax时也能调用。
在laravel,TP5,YII2等框架性能据说都有不错的提升时,自己用TP3.2开源的项目就显得十分的老旧。如何对比速度上的差异,也就只能先记录下TP3.2时的速度,用新框架的速度来进行对比。

参考地址

作者:橙子酱
链接:http://www.jianshu.com/p/43d04d8baaf7
來源:简书

关于压力测试的概念

吞吐率(Requests per second)

概念:服务器并发处理能力的量化描述,单位是reqs/s,指的是某个并发用户数下单位时间内处理的请求数。某个并发用户数下单位时间内能处理的最大请求数,称之为最大吞吐率。
计算公式:总请求数 / 处理完成这些请求数所花费的时间,即

1
Request per second = Complete requests / Time taken for tests

以100并发 100次请求,各大网站的对比(20171025)

1
2
3
4
百度(www.baidu.com)   80~88
知乎(www.zhihu.com) 75~85
QQ(www.qq.com) 25~35
微博(www.weibo.com) 20~25

并发连接数(The number of concurrent connections)

概念:某个时刻服务器所接受的请求数目,简单的讲,就是一个会话。

并发用户数(The number of concurrent users,Concurrency Level)

概念:要注意区分这个概念和并发连接数之间的区别,一个用户可能同时会产生多个会话,也即连接数。

用户平均请求等待时间(Time per request)

计算公式:处理完成所有请求数所花费的时间/ (总请求数 / 并发用户数),即

1
Time per request = Time taken for tests /( Complete requests / Concurrency Level

服务器平均请求等待时间(Time per request: across all concurrent requests)

计算公式:处理完成所有请求数所花费的时间 / 总请求数,即

1
Time taken for / testsComplete requests

可以看到,它是吞吐率的倒数。
同时,它也 等于 用户平均请求等待时间/并发用户数,即

1
Time per request / Concurrency Level
1
2
3
4
百度(www.baidu.com)   1100~1300  11.00~13.00
知乎(www.zhihu.com) 1100~1300 11.00~13.00
QQ(www.qq.com) 3200~3500 32.00~35.00
微博(www.weibo.com) 4000~5000 40.00~50.00

单次测试结果的说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Concurrency Level: 100                 //并发请求数
Time taken for tests: 50.872 seconds //整个测试持续的时间
Complete requests: 1000 //完成的请求数
Failed requests: 0 //失败的请求数

Total transferred: 13701482 bytes //整个场景中的网络传输量
HTML transferred: 13197000 bytes //整个场景中的HTML内容传输量

Requests per second: 19.66 [#/sec] (mean) //吞吐率,大家最关心的指标之一,相当于 LR 中的每秒事务数,后面括号中的 mean 表示这是一个平均值
Time per request: 5087.180 [ms] (mean) //用户平均请求等待时间,大家最关心的指标之二,相当于 LR 中的平均事务响应时间,后面括号中的 mean 表示这是一个平均值
Time per request: 50.872 [ms] (mean, across all concurrent requests) //服务器平均请求处理时间,大家最关心的指标之三

Transfer rate: 263.02 [Kbytes/sec] received //平均每秒网络上的流量,可以帮助排除是否存在网络流量过大导致响应时间延长的问题

关于登录的问题

有时候进行压力测试需要用户登录,怎么办?
请参考以下步骤:

1
先用账户和密码登录后,用开发者工具找到标识这个会话的Cookie值(Session ID)记下来
1
2
如果只用到一个Cookie,那么只需键入命令:
ab -n 100 -C keyvalue http://test.com/
1
2
如果需要多个Cookie,就直接设Header:
ab -n 100 -H “Cookie: Key1=Value1; Key2=Value2” http://test.com/

如何防止别人用ab之类的测试软件恶意请求自己的网站

网友回答:

1
2
3
4
目前此类软件可以很真实的模拟浏览器请求,所以在少量的请求下,基本上是屏蔽不了的。
但是,使用此类软件请求你的网站通常都有其他目的,会产生大量重复的请求。
可以通过单位时间的请求次数进行控制,相同IP或者相同的userAgint产生的异常请求通过程序判断来禁止。
但是即便程序做了判断,请求已经进入处理阶段依然会影响性能,所以还要配合其他的处理方式,重复响应最好用缓存的方式来实现,避免过多的消耗CPU;确诊的问题IP应该在防火墙端就进行屏蔽。
1
2
nginx的话可以用HttpLimitReqModule
此模块能通过特定的客户端标识(如IP,UA等)来限制客户端在一定时间内的访问频次,比你在程序里控制要省资源得多。

背景

上一个项目接手后,在转移数据庫的时候,数据庫的转移失败,那是我第一次接触mysql视图。但是那时没去研究啥是视图。

今天查看另一个项目时,又发现了mysql视图的存在,需要充电一下了!

文章来源

作者:风一样的码农
原文地址:http://www.cnblogs.com/chenpi/p/5133648.html

什么是视图

通俗的讲,视图就是一条SELECT语句执行后返回的结果集。所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。

视图的特性

视图是对若干张基本表的引用,一张虚表,查询语句执行的结果,不存储具体的数据(基本表数据发生了改变,视图也会跟着改变);

可以跟基本表一样,进行增删改查操作(ps:增删改操作有条件限制);

视图的作用

方便操作,特别是查询操作,减少复杂的SQL语句,增强可读性;

更加安全,数据库授权命令不能限定到特定行和特定列,但是通过合理创建视图,可以把权限限定到行列级别;

使用场合

权限控制的时候,不希望用户访问表中某些含敏感信息的列,比如salary…

关键信息来源于多个复杂关联表,可以创建视图提取我们需要的信息,简化操作;

视图实例1-创建视图及查询数据操作

现有三张表:用户(user)、课程(course)、用户课程中间表(user_course),表结构及数据如下:

表定义:

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
-- ----------------------------
-- Table structure for `course`
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL,
`description` varchar(500) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of course
-- ----------------------------
INSERT INTO `course` VALUES ('1', 'JAVA', 'JAVA课程');
INSERT INTO `course` VALUES ('2', 'C++', 'C++课程');
INSERT INTO `course` VALUES ('3', 'C语言', 'C语言课程');

-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`account` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`address` varchar(255) DEFAULT NULL,
`others` varchar(200) DEFAULT NULL,
`others2` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'user1', '小陈', '美国', '1', '1');
INSERT INTO `user` VALUES ('2', 'user2', '小张', '日本', '2', '2');
INSERT INTO `user` VALUES ('3', 'user3', '小王', '中国', '3', '3');

-- ----------------------------
-- Table structure for `user_course`
-- ----------------------------
DROP TABLE IF EXISTS `user_course`;
CREATE TABLE `user_course` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`userid` bigint(20) NOT NULL,
`courseid` bigint(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user_course
-- ----------------------------
INSERT INTO `user_course` VALUES ('1', '1', '2');
INSERT INTO `user_course` VALUES ('2', '1', '3');
INSERT INTO `user_course` VALUES ('3', '2', '1');
INSERT INTO `user_course` VALUES ('4', '2', '2');
INSERT INTO `user_course` VALUES ('5', '2', '3');
INSERT INTO `user_course` VALUES ('6', '3', '2');

这时,当我们想要查询小张上的所以课程相关信息的时候,需要这样写一条长长的SQL语句,如下:

1
2
3
4
5
6
7
8
9
10
SELECT
`uc`.`id` AS `id`,
`u`.`name` AS `username`,
`c`.`name` AS `coursename`
FROM
`user` `u`
LEFT JOIN `user_course` `uc` ON ((`u`.`id` = `uc`.`userid`))
LEFT JOIN `course` `c` ON ((`uc`.`courseid` = `c`.`id`))
WHERE
u.`name` = '小张'

但是我们可以通过视图简化操作,例如我们创建视图view_user_course如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-- ----------------------------
-- View structure for `view_user_course`
-- ----------------------------
DROP VIEW
IF EXISTS `view_user_course`;

CREATE ALGORITHM = UNDEFINED
DEFINER = `root`@`localhost`
SQL SECURITY DEFINER
VIEW `view_user_course` AS (
SELECT
`uc`.`id` AS `id`,
`u`.`name` AS `username`,
`c`.`name` AS `coursename`
FROM
(
(
`user` `u`
LEFT JOIN `user_course` `uc` ON ((`u`.`id` = `uc`.`userid`))
)
LEFT JOIN `course` `c` ON ((`uc`.`courseid` = `c`.`id`))
)
);

几点说明(MySQL中的视图在标准SQL的基础之上做了扩展):

ALGORITHM=UNDEFINED:指定视图的处理算法;

DEFINER=root@localhost:指定视图创建者;

SQL SECURITY DEFINER:指定视图查询数据时的安全验证方式;

创建好视图之后,我们可以直接用以下SQL语句在视图上查询小张上的所以课程相关信息,同样可以得到所需结果:

1
2
3
4
5
6
7
SELECT
vuc.username,
vuc.coursename
FROM
view_user_course vuc
WHERE
vuc.username = '小张'

视图实例2-增删改数据操作

继续,我们可以尝试在视图view_user_course上做增删改数据操作,如下:

1
update view_user_course set username='test',coursename='JAVASCRIPT' where id=3

遗憾的是操作失败,提示错误信息如下:

[SQL] update view_user_course set username=’test’,coursename=’JAVASCRIPT’ where id=3

[Err] 1393 - Can not modify more than one base table through a join view ‘demo.view_user_course’

因为不能在一张由多张关联表连接而成的视图上做同时修改两张表的操作;

那么哪些操作可以在视图上进行呢?

视图与表是一对一关系情况:如果没有其它约束(如视图中没有的字段,在基本表中是必填字段情况),是可以进行增删改数据操作;

如我们创建用户关键信息视图view_user_keyinfo,如下:

1
2
3
4
5
6
7
8
9
10
11
12
-- ----------------------------
-- View structure for `view_user_keyinfo`
-- ----------------------------
DROP VIEW
IF EXISTS `view_user_keyinfo`;

CREATE ALGORITHM = UNDEFINED DEFINER = `root`@`localhost` SQL SECURITY DEFINER VIEW `view_user_keyinfo` AS SELECT
`u`.`id` AS `id`,
`u`.`account` AS `account`,
`u`.`name` AS `username`
FROM
`user` `u`;

进行增删改操作如下,操作成功(注意user表中的其它字段要允许为空,否则操作失败):

1
2
3
INSERT INTO view_user_keyinfo (account, username)
VALUES
('test1', 'test1');
1
2
3
4
5
DELETE
FROM
view_user_keyinfo
WHERE
username = 'test1';
1
2
3
4
UPDATE view_user_keyinfo
SET username = 'updateuser'
WHERE
id = 1

视图与表是一对多关系情况:如果只修改一张表的数据,且没有其它约束(如视图中没有的字段,在基本表中是必填字段情况),是可以进行改数据操作,如以下语句,操作成功;

1
2
update view_user_course set coursename='JAVA' where id=1;
update view_user_course set username='test2' where id=3;

以下操作失败:

1
2
delete from view_user_course where id=3;
insert into view_user_course(username, coursename) VALUES('2','3');

其它

视图中的查询语句性能要调到最优;
修改操作时要小心,不经意间你已经修改了基本表里的多条数据;

运行环境

Nginx 1.8+
PHP 5.6+
Mysql 5.7+
Redis 3.0+
Memcached 1.4+

安装

1
git clone https://github.com/summerblue/phphub5.git

安装扩展包依赖

1
composer install

生成配置文件

1
cp .env.example .env

编辑env
选择数据库
数据库迁移

1
2
3
php artisan migrate

php artisan db:seed

安装命令

1
brew install redis

安装完成后提示

1
2
3
4
5
6
To have launchd start redis now and restart at login:
brew services start redis
Or, if you don't want/need a background service you can just run:
redis-server /usr/local/etc/redis.conf
==> Summary
🍺 /usr/local/Cellar/redis/4.0.2: 11 files, 2.7MB, built in 23 seconds

执行提示

1
brew services start redis

完成后提示

1
2
3
4
5
6
7
8
Cloning into '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-services'...
remote: Counting objects: 12, done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 12 (delta 0), reused 7 (delta 0), pack-reused 0
Unpacking objects: 100% (12/12), done.
Checking connectivity... done.
Tapped 0 formulae (39 files, 53.5KB)
==> Successfully started `redis` (label: homebrew.mxcl.redis)

ok~redis 已经启动

知乎上说,不要在mac自带的python里折腾,怕折腾蹦了影响系统

用brew 安装,且自带pip

安装python2 & python3

1
brew install python
1
brew install python3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
This formula installs a python2 executable to /usr/local/bin.
If you wish to have this formula's python executable in your PATH then add
the following to ~/.zshrc:
export PATH="/usr/local/opt/python/libexec/bin:$PATH"

Pip and setuptools have been installed. To update them
pip2 install --upgrade pip setuptools

You can install Python packages with
pip2 install <package>

They will install into the site-package directory
/usr/local/lib/python2.7/site-packages

See: https://docs.brew.sh/Homebrew-and-Python.html

设置PATH

vim ~/.zshrc 加入
export PATH="/usr/local/opt/python/libexec/bin:$PATH"

验证PATH设置成功

输入which python
如果显示 /usr/local/opt/python/libexec/bin/python则说明成功

如何使用系统的python

如果有需要想使用一下系统的Python,输入/usr/bin/python即可

虽然python不是我的入门语言,之前一直抵触它的缩进语法,但通过《python宝典》的入门学习,发现python成为当前最热门的语言不是偶然。

python社区和语言一起成长,融合了多种语言的特性及优点。

刚试着用import this 查看了python之禅

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
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
python之禅 by Tim Peters

优美胜于丑陋(Python 以编写优美的代码为目标)
明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)
简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)
复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)
扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)
间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)
可读性很重要(优美的代码是可读的)
即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上)

不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码)

当存在多种可能,不要尝试去猜测

而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)

虽然这并不容易,因为你不是 Python 之父(这里的 Dutch 是指 Guido )

做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)

如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准)

命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)

上升到开发哲学上,任何语言都是适用的

xxx—–代表一切可以感恩和赞颂的“人”或“事”或“自己”

某天,我发现自己一直以来都很少去感恩别人,包括自己所取得的一些小成就,也是被自己所否定不认可,总觉得自己(或别人)做的还是不够好,不够完美。可完美的事情真得存在吗?

感恩自己身边的人和事,才会发现生活原来是如此的美。自然的美,和谐的美,错误的美,成功的美……

想象着,自己和父母都存在如此的心声,那将是多么幸福的事:

有这样的儿子感到荣幸

有这样的老婆感到荣幸

有这样的公司感到荣幸

有经历这样的项目感到荣幸

为我的抉择感到荣幸

……

从今天起,试着去感恩吧!

插入

快捷键 说明 常用指数(自己)
a 在当前光标后插入文本 ★★★★
A 在本行行尾插入文本 ★★★★★★
i 在光标前插入文本 ★★★★★
I 在本行行首插入文本 ★★
o 在光标下插入新行 ★★
O 在光标上插入新行 ★★
h 左移一个字符
j 下移一个字符
k 上移一个字符
l 右移一个字符
$ 移动至当前行的行尾 ★★★★
0(数字零) 移动至当前行的行首 ★★★★★★
H 移动屏幕上端 ★★★★★
M 移动屏幕中央 ★★
L 移动屏幕下端 ★★★★★
gg 到整个文件的第一行 ★★★★★★★
G 到整个文件的最后一行 ★★★★★★★★
nG 到第n行,如5G到第5行 ★★★
:n 到第n行 ★★★★★★★★

删除和取消

快捷键 说明 常用指数(自己)
x 删除光标所在处字符 ★★★★★
nx 删除光标所在处n个字符
dd 删除光标所在行(+p剪切) ★★★★★★★
ndd 删除n行(+p剪切) ★★
dG 删除光标所在行值末尾 ★★★★
D 删除光标所在处至行尾 ★★★★
:n1,n2d 删除指定范围的行 ★★★
u 取消上一步操作 ★★★★★★★★★

复制和粘贴

快捷键 说明 常用指数(自己)
yy,Y 复制当前行 ★★★★★
nyy,nY 复制当前行以下的n行 ★★★
p 将内容粘贴所在行的下一行 ★★★★★★★
P 将内容粘贴所在行的上一行

搜索替换

快捷键 说明 常用指数(自己)
/string 查找string(+n下一个) ★★★★★
:%s/old/new/g 全文替换,如:%s/123/789/g ★★★

屏幕

快捷键 说明 常用指数(自己)
ctrl+u 向上滚动半屏 ★★★★★
ctrl+d 向下滚动半屏 ★★★★★
ctrl+b 向上滚动整屏 ★★★★★
ctrl+f 向下滚动整屏 ★★★★★

归纳图片

20160712110935064