小类随手记

golang 高性能网络io框架 nbio

之前一直在用gnet,但是gnet有两个痛点:1、不支持tls/https 2、http和websocket的功能不完整。
因为主要是做api使用,所以第二点对我困扰并不大,但是第一点带来很多麻烦。
于是偶尔在v2ex看到 nbio的作者的自吹贴,详细看了他的测试结果,看了一部分源码后,觉得新的服务应该去尝试一下。

同时在tcp/tls基础上实现简易的http(单纯非必要不用完整http)

1
go get github.com/lesismal/[email protected]      

tcp :https://github.com/lesismal/nbio-examples/blob/master/echo/server/server.go

简易http server

golang 代码 (42 行)
 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
package main

import (
	"bytes"
	"fmt"
	"strconv"
	"strings"

	"github.com/lesismal/nbio"
)

func main() {
	engine := nbio.NewEngine(nbio.Config{
		Network:            "tcp",
		Addrs:              []string{":8888"},
		MaxWriteBufferSize: 6 * 1024 * 1024,
	})

	engine.OnData(func(c *nbio.Conn, data []byte) {
		//封装http start
		joinLengthBytes := []byte(strings.Join([]string{strconv.Itoa(len(data)), "\r\n\r\n"}, ""))
		htmlList := [][]byte{
			[]byte("HTTP/1.1 200\r\nServer:fish-v5\r\nContent-Type:text/plain\r\nContent-Length:"),
			joinLengthBytes,
			data,
		}
		http_response := bytes.Join(htmlList, nil)
		c.Write(http_response)
		//封装http  end
		//c.Write(append([]byte{}, data...))
	})

	err := engine.Start()
	if err != nil {
		fmt.Printf("nbio.Start failed: %v\n", err)
		return
	}
	defer engine.Stop()

	<-make(chan int)
}

简易 https server

rsaCertPEM 和 rsaKeyPEM 可以用nginx格式的 .cer(至少需要第一段)和key,当然也支持 acme申请的证书

golang 代码 (110 行)
 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
79
80
81
82
83
84
85
package main

import (
	"bytes"
	"log"
	"strconv"
	"strings"

	"github.com/lesismal/llib/std/crypto/tls"
	"github.com/lesismal/nbio"
	ntls "github.com/lesismal/nbio/extension/tls"
)

func main() {
	cert, err := tls.X509KeyPair(rsaCertPEM, rsaKeyPEM)
	if err != nil {
		log.Fatalf("tls.X509KeyPair failed: %v", err)
	}
	tlsConfig := &tls.Config{
		Certificates:       []tls.Certificate{cert},
		InsecureSkipVerify: true,
	}

	g := nbio.NewGopher(nbio.Config{
		Network: "tcp",
		Addrs:   []string{":8888"},
	})
	isClient := false
	g.OnOpen(ntls.WrapOpen(tlsConfig, isClient, func(c *nbio.Conn, tlsConn *tls.Conn) {
		log.Println("OnOpen:", c.RemoteAddr().String())
	}))
	g.OnClose(ntls.WrapClose(func(c *nbio.Conn, tlsConn *tls.Conn, err error) {
		log.Println("OnClose:", c.RemoteAddr().String())
	}))
	g.OnData(ntls.WrapData(func(c *nbio.Conn, tlsConn *tls.Conn, data []byte) {
		log.Println("OnData:", c.RemoteAddr().String(), string(data))
		joinLengthBytes := []byte(strings.Join([]string{strconv.Itoa(len(data)), "\r\n\r\n"}, ""))
		htmlList := [][]byte{
			[]byte("HTTP/1.1 200\r\nServer:fish-v5\r\nContent-Type:text/plain\r\nContent-Length:"),
			joinLengthBytes,
			data,
		}
		http_response := bytes.Join(htmlList, nil)
		//c.Write(http_response)
		tlsConn.Write(http_response)
	}))

	err = g.Start()
	if err != nil {
		log.Fatalf("nbio.Start failed: %v\n", err)
		return
	}
	defer g.Stop()

	g.Wait()
}

var rsaCertPEM = []byte(`-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUJeohtgk8nnt8ofratXJg7kUJsI4wDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDEyMDcwODIyNThaFw0zMDEy
MDUwODIyNThaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQCy+ZrIvwwiZv4bPmvKx/637ltZLwfgh3ouiEaTchGu
IQltthkqINHxFBqqJg44TUGHWthlrq6moQuKnWNjIsEc6wSD1df43NWBLgdxbPP0
x4tAH9pIJU7TQqbznjDBhzRbUjVXBIcn7bNknY2+5t784pPF9H1v7h8GqTWpNH9l
cz/v+snoqm9HC+qlsFLa4A3X9l5v05F1uoBfUALlP6bWyjHAfctpiJkoB9Yw1TJa
gpq7E50kfttwfKNkkAZIbib10HugkMoQJAs2EsGkje98druIl8IXmuvBIF6nZHuM
lt3UIZjS9RwPPLXhRHt1P0mR7BoBcOjiHgtSEs7Wk+j7AgMBAAGjUzBRMB0GA1Ud
DgQWBBQdheJv73XSOhgMQtkwdYPnfO02+TAfBgNVHSMEGDAWgBQdheJv73XSOhgM
QtkwdYPnfO02+TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBf
SKVNMdmBpD9m53kCrguo9iKQqmhnI0WLkpdWszc/vBgtpOE5ENOfHGAufHZve871
2fzTXrgR0TF6UZWsQOqCm5Oh3URsCdXWewVMKgJ3DCii6QJ0MnhSFt6+xZE9C6Hi
WhcywgdR8t/JXKDam6miohW8Rum/IZo5HK9Jz/R9icKDGumcqoaPj/ONvY4EUwgB
irKKB7YgFogBmCtgi30beLVkXgk0GEcAf19lHHtX2Pv/lh3m34li1C9eBm1ca3kk
M2tcQtm1G89NROEjcG92cg+GX3GiWIjbI0jD1wnVy2LCOXMgOVbKfGfVKISFt0b1
DNn00G8C6ttLoGU2snyk
-----END CERTIFICATE-----
`)

// 警告: 以下私钥仅用于演示/nbio 测试示例,请勿用于生产环境!
var rsaKeyPEM = []byte(`-----BEGIN RSA PRIVATE KEY-----
<your_test_private_key>
-----END RSA PRIVATE KEY-----
`)

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Theme Stack