gnet: легкая и высокопроизводительная сетевая библиотека Golang.

Go

gnet

Домашняя страница проекта

Github.com/ Pan Jianfeng 2000 / месяц ...

Добро пожаловать всем на просмотр ~~, он все еще постоянно обновляется, если вам интересно, вы можете пометить его звездочкой и тайно наблюдать за ним.

Введение

gnetЭто высокопроизводительная и легкая сетевая библиотека, основанная на событийном цикле событий. Эта библиотека используется напрямуюepollиkqueueСистемные вызовы вместо стандартных сетевых пакетов Golang:netдля создания веб-приложений он работает как две веб-библиотеки с открытым исходным кодом:libuvиlibevent.

Ценность существования этого проекта заключается в обеспеченииRedis,HaproxyЭти два проекта имеют фреймворки веб-сервера на языке Go с одинаковой производительностью.

gnetИзюминкой является то, что это высокопроизводительная, легкая, неблокирующая чистая реализация Go сетевой библиотеки транспортного уровня (TCP/UDP/Unix-Socket), которую разработчики могут использоватьgnetреализовать собственный сетевой протокол прикладного уровня, чтобы создать собственное сетевое приложение прикладного уровня: например, вgnetРеализуя протокол HTTP, вы можете создать HTTP-сервер или среду веб-разработки, а реализовав протокол Redis, вы можете создать свой собственный сервер Redis и так далее.

gnetВзято из другого проекта:evio, но с лучшей производительностью.

Функции

  • высокая производительностьEvent-Loop, управляемый событиями, на основе многопоточной модели
  • Встроенный алгоритм балансировки нагрузки Round-Robin
  • Лаконичные API
  • Эффективное использование памяти на основе кольцевого буфера
  • Поддержка нескольких сетевых протоколов: TCP, UDP, Unix Sockets
  • Поддерживаются два механизма управления событиями: epoll в Linux и kqueue во FreeBSD.
  • Поддержка асинхронных операций записи
  • Позволяет привязать несколько сетевых адресов прослушивания к Event-Loop.
  • Гибкий таймер событий
  • Повторное использование порта SO_REUSEPORT

Основной дизайн

многопоточная модель

gnetПереработана и разработана новая встроенная модель многопоточности: «многопоточность master-slave Reactor», которая такжеnettyМодель многопоточности по умолчанию. Ниже приведена схема этой модели:

multi_reactor

Процесс его работы выглядит следующим образом:

reactor

сейчас яgnetРазработайте новую модель многопоточности: «Многопоточность master-slave Reactors с пулом процессов thread/go», и она будет завершена в ближайшее время.Архитектурная схема этой модели выглядит следующим образом:

multi_reactor_thread_pool

Процесс его работы выглядит следующим образом:

multi-reactors

Механизм связи

gnetМодель «Master-Slave Reactors Multithreading» основана на горутинах в Golang.Один реактор монтируется на один горутин, поэтому вgnetВ этой сетевой модели главный Reactor/Go-процедура и подчиненные Reactor/Go-процедуры имеют огромные требования к связи, поэтомуgnetДолжен быть механизм для эффективной связи между горутинами Я не выбрал основное решение в Golang: модель CSP на основе Channel, а выбрал решение Disruptor с большей производительностью и на основе Ring-Buffer.

Так что в итоге я выбралgo-disruptor: Golang реализация высокопроизводительной очереди распределения сообщений LMAX Disruptor.

Автоматически расширяющийся кольцевой буфер

gnetИспользуйте кольцевой буфер для кэширования данных потока TCP и управления использованием памяти.

начать использовать

Установить

$ go get -u github.com/panjf2000/gnet

Пример использования

// ======================== Echo Server implemented with gnet ===========================

package main

import (
	"flag"
	"fmt"
	"log"
	"strings"

	"github.com/panjf2000/gnet"
	"github.com/panjf2000/gnet/ringbuffer"
)

func main() {
	var port int
	var loops int
	var udp bool
	var trace bool
	var reuseport bool

	flag.IntVar(&port, "port", 5000, "server port")
	flag.BoolVar(&udp, "udp", false, "listen on udp")
	flag.BoolVar(&reuseport, "reuseport", false, "reuseport (SO_REUSEPORT)")
	flag.BoolVar(&trace, "trace", false, "print packets to console")
	flag.IntVar(&loops, "loops", 0, "num loops")
	flag.Parse()

	var events gnet.Events
	events.NumLoops = loops
	events.OnInitComplete = func(srv gnet.Server) (action gnet.Action) {
		log.Printf("echo server started on port %d (loops: %d)", port, srv.NumLoops)
		if reuseport {
			log.Printf("reuseport")
		}
		return
	}
	events.React = func(c gnet.Conn, inBuf *ringbuffer.RingBuffer) (out []byte, action gnet.Action) {
		top, tail := inBuf.PreReadAll()
		out = append(top, tail...)
		inBuf.Reset()

		if trace {
			log.Printf("%s", strings.TrimSpace(string(top)+string(tail)))
		}
		return
	}
	scheme := "tcp"
	if udp {
		scheme = "udp"
	}
	log.Fatal(gnet.Serve(events, fmt.Sprintf("%s://:%d", scheme, port)))
}

события ввода/вывода

gnetВ настоящее время поддерживаются следующие события ввода-вывода:

  • OnInitCompleteВызывается после завершения инициализации сервера.
  • OnOpenedКогда соединение открывается, оно вызывается.
  • OnClosedВызывается при закрытии соединения.
  • OnDetachedВызывается при активном отключении соединения.
  • ReactВызывается, когда серверная сторона получает данные, отправленные с клиентской стороны. (Ваш основной бизнес-код обычно пишется с помощью этого метода)
  • TickКогда сервер запустится, он будет вызываться один раз, а затем будет вызываться один раз через заданный интервал времени, это метод таймера.
  • PreWriteМетод предварительной записи данных вызывается перед тем, как серверная сторона записывает данные обратно на клиентскую сторону.

Тестирование производительности

Linux (epoll)

Системные параметры

Go Version: go1.12.9 linux/amd64
OS:         Ubuntu 18.04
CPU:        8 Virtual CPUs
Memory:     16.0 GiB

Echo Server

echolinux.png

HTTP Server

httplinux.png

FreeBSD (kqueue)

Системные параметры

Go Version: go version go1.12.9 darwin/amd64
OS:         macOS Mojave 10.14.6
CPU:        4 CPUs
Memory:     8.0 GiB

Echo Server

echomac.png

HTTP Server

httpmac.png

Сертификат

gnetИсходный код позволяет пользователям следовать MITСертификат с открытым исходным кодомиспользуется по правилам.

сделать

gnet все еще находится в процессе непрерывной разработки, поэтому код и документация этого репозитория будут постоянно обновляться.Если вы заинтересованы в gnet, вы можете внести свой код в эту библиотеку с открытым исходным кодом~~