项目中有一些使用Golang进行开发的中间件,以及小工具,现在检查服务器IO发现Golang的日志输出导致磁盘IO紧张,现在采取 RingBuffer + Driect IO进行处理

package logger

import (
	"errors"
)

var (

	ErrClosed = errors.New("logger is closed")
)

// Logger 基本方法
type Logger interface {
	Write(b []byte) (n int, err error)
	flush()
	worker()
	GetWriter()(interface{})
}

package logger

import (
	"fmt"
	directio "github.com/ncw/directio"
	. "github.com/smallnest/ringbuffer"
	"os"
	"sync"
	"time"
)

const (
	// MB is Bytes in a Megabyte
	MB = 1024 * 1024
	// BlockSize is size of block to do IO with
	BlockSize = 2 * MB
)

type AsyncLog struct {
	Workdir string
	Threads int
	buf     *RingBuffer
	RW      sync.Mutex
	Wait    sync.WaitGroup
}

func (log *AsyncLog) GetWriter() interface{} {
	go log.worker()
	return log
}

func (log *AsyncLog) flush() {
	dt := time.Now()
	fileName:=fmt.Sprintf("%s_block_2mb.log", dt.Format("2006_01_02_15_04_05"))
	out, err :=directio.OpenFile(fileName, os.O_SYNC|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
	}
	block := directio.AlignedBlock(BlockSize)
	for i := 0; i < len(log.buf.Bytes()); i++ {
		block[i] = log.buf.Bytes()[i]
	}
	if _, err := out.Write(block); err != nil {
		fmt.Println("write err",err)
	}
	if err := out.Close(); err != nil {
		fmt.Println("close err",err)
	}
}

func (log *AsyncLog) worker() {
	t1 := time.NewTicker(time.Millisecond * 100)
	for {
		select {
		case <-t1.C:
			if  log.buf.IsFull(){
				log.flush()
				log.buf.Reset()
			}
		}
	}
}

func NewSetting() Logger {
	rb := New(BlockSize)
	logger := &AsyncLog{
		Workdir: "",
		Threads: 4,
		buf:     rb,
	}
	return logger
}
func (log *AsyncLog) Write(b []byte) (n int, err error) {
	fmt.Printf("[Debug] %s",string(b))
	return log.buf.Write(b)
}
// 使用方式
asyncLog:=logger.NewSetting()
log.SetOutput(asyncLog.GetWriter().(io.Writer))