Deno
原生提供的网络功能没有 HTTP
服务的能力,这一点和Node.js
的区别有大。虽然Deno
没有应用层面的网络能力,但是提供了比较基础的TCP
网络的支持。学过计算机网络的小伙伴应该知道,HTTP
服务底层就是基于TCP
服务实现的。
本篇文章就是用Deno
提供的原生listen
模块实现最简单的HTTP
服务。
- 利用
Deno
原生模块listen
监听TCP
地址来初始化对应的TCP
服务 - 从
TCP
服务监听器中等待TCP的对话连接 - 等到建立对话连接后,可以从对话中读取对话连接信息,就是HTTP请求报文
- 对话写入对话连接数据,即HTTP响应报文
https://github.com/chenshenhai/deno_note/blob/master/demo/http/example.ts
./demo/http/example.ts
/**
* 创建响应内容
* @param {string} bodyStr
* @return {Uint8Array}
*/
function createResponse (bodyStr: string): Uint8Array {
const CRLF = "\r\n";
const encoder = new TextEncoder();
const resLines = [
`HTTP/1.1 200`,
`content-length: ${bodyStr.length}`,
'',
bodyStr
];
const res = encoder.encode(resLines.join(CRLF));
return res;
}
/**
* HTTP响应操作
* @param conn {Conn}
*/
async function response(conn: Deno.Conn) {
// 创建响应信息
const res = createResponse("hello world");
// TCP连接写入响应信息
await conn.write(res);
conn.close();
}
/**
* HTTP服务
* @param opts {Deno.ListenOptions}
*/
async function server(opts: Deno.ListenOptions) {
// 创建TCP服务
const listener: Deno.Listener = Deno.listen(opts) as Deno.Listener;
console.log("listening on", `${opts.hostname}:${opts.port}`);
// 死循环监听TCP请求
while (true) {
// 等待TCP连接
const connection = await listener.accept();
// 执行响应
response(connection);
}
}
server({
hostname: "127.0.0.1",
port: 3001
});
# --allow-net 是直接允许网络权限
deno run --allow-net example.ts
打开浏览器,输入连接 http://127.0.0.1:3001/,就可以看到以下结果。
从上述的代码看来,利用 Deno
原生的TCP
服务实现一个HTTP
服务的过程代码很简单,浏览器观察的效果看起来也很稳定,但是用基准测试工具强行压测,就会出现服务响应异常的报错。
这里我们利用 npm
模块 autocannon
进行对上述的HTTP
进行压力测试。
- 安装测试工具
npm i -g autocannon
- 发起
100个对话
测试autocannon http://127.0.0.1:3001/ -c 100
- 就会出现以下结果
- 出现以上基准测试响应错误的问题主要是
TCP
对话频繁建立 - 没有一个健壮的排队机制去控制,导致
TCP
对话连接混乱或者不对等
如果想快速知道解决方案,可以直接跳过看后续的文章 原生Deno实现稳定HTTP服务