如何在开发过程中搭建简单的假数据服务器

在开发一块新功能的过程中,我们通常会涉及到与后端接口联调的问题。新的界面、新的后端接口,这时候在开发的时候往往前端就很尴尬,后端不依赖前端,但是前端十分依赖后端。

大部分应用都会有或多或少地依赖后端数据,有的界面只需要简单搞个假数据传入即可,但是我们还需要应对很多复杂情况,比如:

  • 处理无数据、返回错误、各类非正常的状态;

  • 处理分页数据的情况;

  • 模拟一个请求中、请求失败、请求结果返回的情景;

这时候如果能够写一个简单的服务器,你请求真实的接口url,只需要给手机设置一个代理,就返回你设置的假数据。这样你就可以完全抛开其他依赖的顾虑,可以像正常情况一样开发、校验结果,而不是依赖写死在代码里的各种假逻辑(这样做也会为后面的开发带来一些隐患)。

实际上服务器本身的逻辑是非常简单的,但是要真正得搭建成你所需要的环境,需要一些复杂功夫。本文以[nodejs](http://blog.desmondyao.com
/fake-server/node)为例,具体描述一下如何在本机上搭建测试服务器。

使用node搭建起简单的服务器脚本

1. 安装

Unix 用户可以使用命令行安装nodejs。

Windows 用户可以直接下载安装包

安装成功后如果在命令行下输入node -v能够打印出版本信息,说明安装成功了。

2. 简单服务器

Node 服务器可以运行在“IP:PORT”上,我们可以通过如下代码来在127.0.0.1:2333端口上搭建起一个简单的服务器:

server.js

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


const http = require('http');

http.createServer( (req, res) => {

// 返回码200,返回头中标识内容为json

res.writeHead(200, {'Content-Type': 'text/json'});

let resp = {

code : 0,

time : 1469981217,

data : {

name : 'desmond',

gender : 'male'

}

};

res.end(JSON.stringify(resp)); // 将resp转换为JSON字符串返回。

}).listen(2333, '127.0.0.1', )

之后输入node server.js,然后我们到浏览器中访问localhost:2333就可以看见:

具体的信息可以参考Nodejs-http.

3. IDE配置

从IDE环境切换到脚本环境来写代码总会不顺手,推荐一个我认为比较容易上手的配置吧:

Nginx反向代理

nginx
搭建服务器的强大处之一就是它的代理能力,配置也十分简洁。

如果要模拟最终的请求的话,我们应该是原封不动的保留请求url: ‘www.desmond.com/api/something’。首先我们需要
在手机上设置代理,将ip配置到自己电脑上,端口配为80
。但是你的电脑识别到这个请求后,怎么让它导流到你的node服务器,这是一个问题。如果你代码写死的ip+端口来访问,未免有点太low了,我们既然折腾了这么多,那可以继续往下走一步:反向代理

反向代理,简而言之,就是一个分发请求的代理。前向代理
是直接发给目标服务器,但是它会做一些额外的处理工作。反向代理不一样,它自己相当于是一个服务器,请求到它手里,它根据请求去不同服务器上拉取数据。

1. 安装Nginx

Linux用户可以使用命令行:

1
2
3
apt-get update

apt-get install nginx

OSX用户可以用Homebrew:

1
brew install nginx

Windows用户可以下载安装包

2. 配置代理

我们希望针对’www.desmond.com/api/something’下的url交由node服务器(2333端口)处理,其他情况下继续发送,可以在nginx.conf里面这么配置(可以在命令行下输入nginx
-t找到配置文件位置):

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


server {

listen 本机ip:80;

server_name www.desmond.com;

#charset koi8-r;

access_log /Users/desmond/Nginx/api.access.log;

error_log /Users/desmond/Nginx/api.error.log;

location / { //默认情况原路继续

resolver 8.8.8.8;

proxy_pass http://$http_host$request_uri;

proxy_set_header Host $http_host;

proxy_connect_timeout 5;

}

location /api { //检测到api路径下的,转发到端口2333

proxy_pass http://localhost:2333;

}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html

#

error_page 500 502 503 504 /50x.html;

location = /50x.html {

root html;

}

}

这里如果希望原路继续的那些url域名解析配合你的host(此处使用8.8.8.8来做DNS解析),你可以参考[StackOverflow的一个提问](http://stackoverflow.com/questions/8305015
/when-using-proxy-pass-can-etc-hosts-be-used-to-resolve-domain-names-instead-
of)。

这样一来,你所有手机上访问的www.desmond.com/api/something就导到你的nodejs服务器上啦,尽情配置假数据来测试吧~~

4. 配合Charles使用

如果使用Charles的话,手机上一般配的代理是”ip:8888”,那么此时需要做一件事:本地的host设置本机ip
www.desmond.com,这样才能保证 www.desmond.com域名下的请求被导流到nginx服务器,从而导流到自己的nodejs服务器上。

最终搭建

直接使用node,还是有一些繁琐的。既然我们的目的是“简单”,那么可以考虑一下使用express
。它封装了很多API,然呢使用起来非常方便。其中一项就是路由(Route)。它意思简单来说就是: www.desmond.com/api/a 由 a
的逻辑处理,www.desmond.com/api/b 由 b 的逻辑处理。

我相信一个新模块的服务器接口肯定不止一个,假如我们现在接口文档上写着:

1. 提交个人信息:www.desmond.com/api/personal

方法:POST

返回示例:

1
2
3
4
5
6
7
{

code : 0,

time : 1469981217

}

2. 获取未来n天天气信息:www.desmond.com/api/weather

方法:GET

参数:day 未来天数

返回示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

{

code : 0,

time : 1469981217,

data : {

items : [

date : '2016-08-02',

state : 'sunny'

],

//...

}

}

那么你可以使用来做一个简单的ROUTE+请求处理:

server.js

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
const express = require('express');

const url = require('url');

let app = express();

app.post('/api/personal', function (req, res) { //针对/api/personal 的 post请求返回

    res.writeHead(200, {'Content-Type': 'text/json;charset=utf-8'});

    res.end(JSON.stringify({

code : 0,

time : 1469981217

}));

});

app.get('/api/weather', function (req, res) { //针对/api/weather 的 get请求返回

    res.writeHead(200, {'Content-Type': 'text/json;charset=utf-8'});

let count = url.parse(req.url, true).query.day; //解析传入的day参数

if(count) { //若有,根据day参数生成item

let tmpList = [];

let tmpDate = newDate();

for(let i = 0; i < count; i++ ) {

tmpDate.setDate(tmpDate.getDate() + 1);

tmpList.push({

date : `${tmpDate.getFullYear()}-${tmpDate.getMonth() +
1}-${tmpDate.getDate()}`,

state : `sunny - ${i}`

});

}

res.end(JSON.stringify({

code : 0,

time : 1469981217,

items : tmpList

}));

} else { //若无,则返回错误信息

res.end(JSON.stringify({

code : -1,

msg: 'you must send param \"day\"',

time : 1469981217

}));

}

});

app.listen(2333, function(req, res) {

    console.log(`You have run node host.`);

});

注意:不要忘记安装express,(npm install express –save)即可。

编辑结束后运行一下node server.js,你可以看到输出:

You have run node host.

这时我们可以尝试请求一下 localhost:2333,可以看到返回:

大功告成~~

如果希望node server一直在后台跑(使用node
server.js时shell会卡在当前运行中),可以使用ForeverJS

更简单的办法

如果不想折腾太多,可以直接写一个json静态文件去返回:

data.json

1
2
3
4
5
6
7
{

"code" : 0,

"time" : 1469981217

}

*注意:手写json的话,里面的 key 必须以字符串形式(双冒号包围)存在。

server.js

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
const fs = require('fs');

const express = require('express');

let app = express();

app.get('/api/weather', function (req, res) { //针对/api/weather 的 get请求返回

res.writeHead(200, {'Content-Type': 'text/json;charset=utf-8'});

fs.readFile('data.json', 'utf8', (err, data) => { //读取data.json

if(err) { //错误时返回异常

res.end(JSON.stringify({

code : -1,

msg : 'Read File error!'

}));

return;

}

res.end(data);

});

});

app.listen(2333, function(req, res) {

console.log(`You have run node host.`);

});

这样就非常简单,不过缺点就是无法动态地处理。

直播平台整体架构

直播平台整体架构

视频直播链路

视频流转换成不同清晰度

不同的端,不同的网络环境,需要不同码率,以保流畅

播放器的基本实现

SDK在播放器上做层管理

视频相关技术细节

消息发送流程

不同消息通道的优劣对比

心跳及房间结构

用户按需分桶

固定分桶与按需分桶对比

关键词及垃圾文本过滤

大促风险控制

平台化的挑战

想了解可以私信我!

1 SpringBoot+ 高并发消息处理 EDM?项目 实战

2 SpringBoot ELK?分布式 数据分析

3 Netty?高 并发 UTS?项目实战

4 SpringCloud?微服务+NoSQL+ 负载均衡平台设计

互联网架构的演变

互联网架构的演变

1

最初是前端一个web 加一个DB的结构

这种结构,web容易挂掉,业务就会终止,由于高可用的需求,出现了下面这样的架构。

2

加了一个web,两个web之间是主备的关系,一个挂了,另一个来代替,用来解决高可用问题

3

之后发现这样的架构支持的访问量不够了,前端撑不住那么大的访问量,因为前端的访问量和DB的落库有大概是10比1的比例,前端访问10个,会有1个能够落库,所以随着访问量的增加,前端先扛不住了,这个时候主、备结构已经不能解决高可用的问题,所以在web前面加了一个ngx,作为负载均衡进行访问的转发,这个时候,web和web之间的主备关系就不存在了,在ngx进行转发的时候会有一个session保持的操作,再后来就出现无状态的概念,在两个web之间进行轮询,给谁都行

4

当无状态的概念出来以后,web这一层就可以进行多次的横向扩展,这是第一次质的飞越

后来人们觉得一个ngx也会出问题,就设计了主、备结构的ngx

5

后来主、备ngx结构也不满足需求了,就在ngx前面加了一个lvs,lvs是一个负载均衡的结构,lvs先对ngx做分发

这时nginx就解放出来了,不是主、备结构了,而是作为一个层级的结构,可以进行无限横向扩展,lvs被设计成主、备的结构,至此,lvs作为第一层就不再变化了,第一层始终是主、备的结构,lvs的负载特别小,所有的负载到lvs直接就传给ngx,ngx再往下分发

这个时候,转发层活了,web层活了,压力就全到DB了,DB就开始演变

6

最初DB演变出来master和slave这样的架构

所有的web既连master也连slave,连slave只进行读操作,连master只进行写操作,这样把读和写进行分离,这时速度就有一个质的提升

然后如果一个slave不够的时候,再加一个slave,就解决了这个架构对数据库读的压力,这个时候的网站的并发访问量,理论上可以到万级了

但是有一个问题,master是一个单点,如果它挂了,整个系统就都挂了,这个时候要考虑的不只是吞吐量,也要看性能、可靠性,前端已经没有问题了,但是数据库这里有一个单点的问题,后来人们就开始想办法,怎么能保证DB不会出问题呢,后来人们就把DB这块给重构了。

7

在web下面加了一层proxy结构,可以说是转发,也可以说是中间件,这一层结构可以做成集群,这个集群是给数据库做切片的,做成类似于分布式的功能,这一层下来给DB做切片转发,这样DB这一层的库之间就不再有主、从的关系了,都认为是主,挂掉一个,其他的还能正常工作,既做高可用,又做高性能,保证某一台挂掉的时候,另外两台可以做到高可用,如果负载不够的时候,还可以添加

这个4层结构,可以在很高的性能下,很高的可靠性下做到万级甚至十万级的并发。

这是5年前开始流行的架构,现在的使用率也很高,在对可靠性和性能方面要求不是很高的系统中可以很稳定的应用,但它存在一个问题,就是访问量再大的时候,落库的时候会有一个瓶颈,因为DB不只是做插入和查询,还要做分析和关联,速度会很慢,那怎么办呢?

8

人们开始在DB层的上边加两个缓存层(读和写),读缓存层是用redis,它也是集群,在业务层下边,DB层的上边,redis从数据库里抽数据,到自己的缓存中,然后提供给业务,只要被缓存命中的数据,读的是特别快的,redis把DB中的热数据提取到缓存层,直接给业务层来用。

写的话用的是MQ,来实现写的业务,一读一写合起来就大大的提升了并发的处理。

这个架构中的lvs负责四层转发,ngx做7层转发,转发下来后,web做接收。

读的时候,热数据从DB里抽到redis里读,就不会因为DB的计算卡着web了,在像双十一这种秒杀的业务,可以把数据提前放到redis里,供web来读,写数据时可以快速的写给mq,之后web就不用管了,用户就可以接着做下一步了,然后mq往DB里一点一点的落库,就是说通过缓存层把高速的web和低速的DB给隔离开,这样给前边的用户体验就会特别好。

比如双十一之前加购物车,都是提前被写好了放到redis里边,然后下订单都是通过mq来落库,你这边一点刷一下就过去了,你觉得过去了,实际上都在mq里往DB里处理,不可能一下子就落到DB里,目前还没有一家公司能够做到,就算是分布式数据库也不行,分布式数据库只能解决中型的业务场景,解决不了巨型的业务场景,这是这两年很典型的比较火的架构,但是它比不上分布式数据库,这种结构即使很快,如果技术实力不够也只能达到十万级,如果要扩的话,只能是横向的扩,一套一套的往上累加。

9

出现了新型分布式数据库以后,这个架构变得很简单,很明晰,速度也很快。

lvs,nginx,web这三层不变,下边的缓存层,代理层都没有了,只剩数据库本身了,这个DB目前可以撑住10万甚至20万(瞬间的并发写),没有理论上限,各种的复杂的计算在一秒内都可以完成,这就是分布式架构的架构之美,越来越简洁。这个DB实际上是很复杂的。

它的底层有自己的分布式存储dfs结构,另外有控制节点,还有提供实际计算,运行sql的计算节点,这三部分是没有中心(去中心),可扩展,对称的(坏掉一台、加一台都没问题),可以做到平行的扩展,做到无限制的可行性,也是分布式的目的所在。

他是怎么做到高速的呢?实际上就是分布式存储和计算的理念,如果有中心的话,需求下来一定是发给一个中心节点上,这个中心就会成为瓶颈,无中心的话,需求下来抛给控制节点,控制节点也没有中心,控制节点接到请求以后告诉它你去哪个计算节点上去,然后计算节点去计算的时候,如果这时所有的数据放到一个dfs上边(存储DB),读写势必会很慢,但是分布式存储它是完全散开的(多个dfs),一个请求过来后是放到所有的计算节点上去算的,然后拿的时候是到所有的dfs上去拿的,这个速度会特别快,这个过程完全都是分布的,所以,这种新型的数据库架构,就可以做到每秒10万个查询、写入、update,也可以做分析,最快可以到每秒10万。

目前能做到千万级别的并发的,有BAT和12306,其他就没有了,这种架构覆盖了当前互联网基本上 95%甚至是99%的需求。

数据在下发的时候,是多副本,挂掉一个机器数据是不会丢失的,它的数据是打散的,这样读的才会快,这个结构出来之后直接干掉缓存层,而且可以支持列式数据库,目前的数据库基本是行式的,列式数据库对那种特别大的数据量支持的特别好。
(The End)

Your browser is out-of-date!

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

×