git工作流概念与http长连接、websocket实践
目录
- git工作流概念
- http长连接
- 长轮询
- SSE
- WebSocket
- nodejs-websocket
- socket.io
git工作流
很久之前我都不知道这个概念,但实际我已经遵循这个概念有了很长时间。
工作流是一种工作方式,是工作时的一种规范,一种流程。所以git工作流是在写项目时,这个团队项目开发,测试的基础。
常见的工作流有以下几种
- 中心化的工作流
- 基于功能分支的工作流
- Gitflow工作流
- Fork工作流
我认为不是一定要遵循这些工作流的流程,在实际的开发中,根据自己项目的实际情况,合理的总结出一个git规范即可。
http长连接
在http 1.1 时代早期的服务器推技术实现中,长连接与长轮询经常被用到,因为http 1.1默认开启了keep-alive
,节省了tcp连接握手断开连接的开销。
长连接与长轮询的区别在于:前者是服务端轮询查到数据后给客户端,等待的时候客户端请求一致处于pending
状态,当然在超时范围内;后者是客户端轮询查数据,在一定的周期时间内。
很显然,长轮询对于客户端来说,消耗的资源是一定的,无论请求的数据是否有效都会再次请求。而长连接只会在请求收到有效的数据后再次发起请求,当然,当数据多的时候,客户端可能会crash
。
长连接实践
- XMLHttpRequest
- iframe
- EventSource
Server-Send Events,简称为sse
// XMLHttpRequest
function fetch() {
const xhr = new XMLHttpRequest()
xhr.send('get', url)
xhr.onreadystatechange = function() {
if (this.readState === 4 && this.status === 200) {
fetch()
}
}
}
fetch()
查看请求与响应信息,在request body
与response body
中都可以看到connection: keep-alive
。
// iframe
function iframePull() {
const url = ''
const iframe = document.createElement('iframe')
iframe.src = url
iframe.style.display = 'none'
iframe.onload = function() {
document.body.removeChild(iframe)
iframePull()
}
document.body.appendChild(iframe)
}
iframePull()
基于http1.1长连接的服务器推技术实现称为Comet
,还有一种为html5标准中Server-Send Events与长轮询的区别在于
在于有更长时间的 HTTP 连接,谓之“长连接” —— 服务器发完了新数据也不断开连接,继续等待下一份新数据,除非超过了一定的时限(即自定义的最大连接空闲时长,浏览器可以超时重连)
SSE实现
// index.html
<div id='msg'></div>
<script>
const event = new EventSource('/msg')
console.log(event)
event.onmessage = (e) => {
document.getElementById('msg').innerHTML = e.data
}
</script>
// server.js
const http = require("http")
const fs = require("fs")
var server = http.createServer()
// 客户端请求
server.on("request", function(req, res){
if(req.url == "/"){
fs.readFile(__dirname + '/index2.html', function(err, data){
if(err) {
res.writeHead(err, data)
return res.end('Error loading index.html')
}
res.writeHead(200)
res.end(data)
})
return
}
if(req.url == "/msg"){
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Connection": "keep-alive"
});
setInterval(function () {
res.write("data: " + Date.now() + "\n\n");
}, 1000)
return
}
res.end("no page")
})
server.listen(8888)
使用SSE返回的数据必须设置头信息"Content-Type": "text/event-stream"
。
SSE与长连接的本质是相同的,都是基于http的,前者是html5标准API,后者是利用XMLHttpRequest的异步请求。
参考阅读
- 长连接 http://www.cnblogs.com/hoojo/p/longPolling_comet_jquery_iframe_ajax.html
- 概念区别 https://www.zhihu.com/question/27498235
- sse https://cnodejs.org/topic/5463840472f405c829029f62
- 长连接实践 http://www.lizhiqianduan.com/myblog/#/article/10060
WebSocket
WebSocket不是基于http的,是直接建立在tcp连接的基础上的数据通信。
实例一,html5标准WebSocket
+ nodejs-websocket
步骤
- node做http服务器
- node做WebSocket服务器
- 客户端发起socket请求
// 客户端 index.html
const ws = new WebSocket('ws://localhost:8001')
ws.onopen = opt => {
ws.send('hi')
}
ws.onmessage = evt => {
console.log(evt.data)
}
// 服务端 server.js
// node http
const fs = require('fs')
const server = require('http').createServer(((req, res) => {
if (req.url === '/') {
fs.readFile(`${__dirname}/index.html`, (err, data) => {
res.writeHead(200)
res.write(data)
res.end()
})
}
}))
server.listen(3000, () => {
console.log('server is start on 3000')
})
// node ws
const ws = require('nodejs-websocket')
ws.createServer(conn => {
conn.on('text', function (str) {
console.log(`received text: ${str}`)
conn.sendText(`send text: ${str.toUpperCase()}`)
})
}).listen(8001)
打开localhost:3000
客户端会发送连接请求,发送hi
字符,ws接受到并转为大写后也发送给客户端,客户端接收到打印显示。
延伸链接
nodejs-websocket
HTML5 WebSocket
node.js http 模块
实例二,socket.io
,使用socket.io
就变得相对简单容易理解很多。
// 客户端
const socket = io.connect() // 与本地服务器一致时可省略参数
socket.on('init', msg => {
console.log(msg)
socket.emit('reply', `i receive ${msg}`)
})
// socket
const io = require('socket.io')(server)
io.on('connection', client => {
client.emit('init', 'connect ok')
client.on('reply', msg => {
console.log(msg)
})
client.on('disconnect', () => {
console.log('disconnect')
})
})
当二者握手成功后,服务端会发出init消息,客户端收到后发出reply消息,告知客户端收到消息了,服务端打印该消息。
小结
对于服务器推,或客户端与服务端互相通信,相对于websocket,http长连接实现的成本要低很多,而且在对于客户端只需接收服务端消息更新某些小范围内容时,http长连接是很适合的,当然延时也很明显。对于实时要求高的场景websocket就显得更适合了,当然服务器的成本会增大(具体数据未考证对比)。