Skip to content
On this page

git工作流概念与http长连接、websocket实践

目录

  • git工作流概念
  • http长连接
    • 长轮询
    • SSE
  • WebSocket

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 bodyresponse 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的异步请求。

参考阅读

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消息,告知客户端收到消息了,服务端打印该消息。

延伸链接
socket.io
手把手搭建N-chat聊天室

小结

对于服务器推,或客户端与服务端互相通信,相对于websocket,http长连接实现的成本要低很多,而且在对于客户端只需接收服务端消息更新某些小范围内容时,http长连接是很适合的,当然延时也很明显。对于实时要求高的场景websocket就显得更适合了,当然服务器的成本会增大(具体数据未考证对比)。