mirror of
https://github.com/buger/goreplay.git
synced 2024-04-21 12:32:02 +00:00
### Reducing CPU context switching and number of goroutines. Packet capture and packet processing now use only two goroutines which helps to minimize CPU context switches. Spawning too many goroutines is harmful here. ### Optimized packet capture - allocated memory only when required, and only for data which is used Using ZeroCopy methods from libpcap library to avoid unnecessary allocations. Now memory gets allocated ONLY for the valid packets, and only for the packets which have the data. E.g. no SYN/FIN packets are used now. Additionally we now use `sync.Pool` for re-using packet objects, which helps to re-use already allocated memory. ### Simplification and optimization of request/response detection There is no SYN/FIN packets anymore etc. Now only packet payload is used to detect start and end of the packet. More over payload detection now does not require generating a total “message” buffer, and works with individual packet payloads. Message payloads now concatenated from packets only in the end when message is dispatched. Also, before checking if message is complete, added additional check if all received packets in the valid order, e.g. if their SEQ is valid, and no packets are missing. Reworked chunked encoding validation, and now it does not need expensive operation of re-calculating all the chunks. Now it “trust” that client gives valid chunk body, check if packets are in the right order (e.g. SEQ match), and checks if message ends with the right suffix. All is done with 0 allocations. Parsing all Headers using `proto.GetHeaders` was proved to be very slow. Now we only parse the headers we need(and do it only once). Packets gets matched together using ACK, which on high RPS removed chances of duplicating IDs. Additionally, even if packets are received out of order, now it will properly sort them, before dispatching the message. ### Changes in ID generation algorithm Message ID generation and relations between request and response IDs is fully rewritten. Responses now do not have to lookup for request data in order to get the same ID. ID no rely on the fact that SEQ of the first packet of the response should be the same as ACK of the request. If previously Message ID contained random values, like current timestamp, now it has a consistent algorithm which is based on TCP stream id (SrcPort + DstPort + SrcIP/DstIP) and current ACK/SEQ number (to distinguish multiple messages within the same stream). ### BPF filter optimizations When tracking response it now uses a more accurate BPF rule to filter only needed traffic. ### Misc The packet code is now fully moved to tcp/Packet, so packet processing done only once in one place. TCP output now has a 5 second timeout, and has a proper Close method. Fully switching to go modules and removing vendoring.
147 lines
4.8 KiB
Makefile
147 lines
4.8 KiB
Makefile
SOURCE = $(shell ls -1 *.go | grep -v _test.go)
|
|
SOURCE_PATH = /go/src/github.com/buger/goreplay/
|
|
PORT = 8000
|
|
FADDR = :8000
|
|
CONTAINER=gor
|
|
PREFIX=
|
|
RUN = docker run -v `pwd`:$(SOURCE_PATH) -e AWS_ACCESS_KEY_ID=$(AWS_ACCESS_KEY_ID) -e AWS_SECRET_ACCESS_KEY=$(AWS_SECRET_ACCESS_KEY) -p 0.0.0.0:$(PORT):$(PORT) -t -i $(CONTAINER)
|
|
BENCHMARK = BenchmarkRAWInput
|
|
TEST = TestRawListenerBench
|
|
BIN_NAME = gor
|
|
VERSION = DEV-$(shell date +%s)
|
|
LDFLAGS = -ldflags "-X main.VERSION=$(VERSION)$(PREFIX) -extldflags \"-static\" -X main.DEMO=$(DEMO)"
|
|
MAC_LDFLAGS = -ldflags "-X main.VERSION=$(VERSION)$(PREFIX) -X main.DEMO=$(DEMO)"
|
|
FADDR = ":8000"
|
|
|
|
FPMCOMMON= \
|
|
--name goreplay \
|
|
--description "GoReplay is an open-source network monitoring tool which can record your live traffic, and use it for shadowing, load testing, monitoring and detailed analysis." \
|
|
-v $(VERSION) \
|
|
--vendor "Leonid Bugaev" \
|
|
-m "<support@goreplay.org>" \
|
|
--url "https://goreplay.org" \
|
|
-s dir \
|
|
-C /tmp/gor-build \
|
|
|
|
release: release-x64 release-mac
|
|
|
|
release-bin:
|
|
docker run -v `pwd`:$(SOURCE_PATH) -t --env GOOS=linux --env GOARCH=amd64 -i $(CONTAINER) go build -o $(BIN_NAME) -tags netgo $(LDFLAGS)
|
|
|
|
release-bin-mac:
|
|
GOOS=darwin go build -o $(BIN_NAME) $(MAC_LDFLAGS)
|
|
|
|
release-x64:
|
|
docker run -v `pwd`:$(SOURCE_PATH) -t --env GOOS=linux --env GOARCH=amd64 -i $(CONTAINER) go build -o $(BIN_NAME) -tags netgo $(LDFLAGS)
|
|
tar -czf gor_$(VERSION)$(PREFIX)_x64.tar.gz $(BIN_NAME)
|
|
mkdir -p /tmp/gor-build
|
|
mv ./$(BIN_NAME) /tmp/gor-build/$(BIN_NAME)
|
|
cd /tmp/gor-build
|
|
rm -f goreplay_$(VERSION)_amd64.deb
|
|
rm -f goreplay-$(VERSION)-1.x86_64.rpm
|
|
fpm $(FPMCOMMON) -a amd64 -t deb ./=/usr/local/bin
|
|
fpm $(FPMCOMMON) -a amd64 -t rpm ./=/usr/local/bin
|
|
rm -rf /tmp/gor-build
|
|
|
|
release-x86:
|
|
docker run -v `pwd`:$(SOURCE_PATH) -t --env GOOS=linux --env GOARCH=386 -i $(CONTAINER) go build -o $(BIN_NAME) -tags netgo $(LDFLAGS)
|
|
tar -czf gor_$(VERSION)$(PREFIX)_x86.tar.gz $(BIN_NAME)
|
|
rm $(BIN_NAME)
|
|
|
|
release-mac:
|
|
go build -o $(BIN_NAME) $(MAC_LDFLAGS)
|
|
tar -czf gor_$(VERSION)$(PREFIX)_mac.tar.gz $(BIN_NAME)
|
|
mkdir -p /tmp/gor-build
|
|
mv ./$(BIN_NAME) /tmp/gor-build/$(BIN_NAME)
|
|
cd /tmp/gor-build
|
|
rm -f goreplay-$(VERSION).pkg
|
|
fpm $(FPMCOMMON) -a amd64 -t osxpkg ./=/usr/local/bin
|
|
rm -rf /tmp/gor-build
|
|
|
|
|
|
install:
|
|
go install $(MAC_LDFLAGS)
|
|
|
|
build:
|
|
docker build -t $(CONTAINER) -f Dockerfile.dev .
|
|
|
|
profile:
|
|
go build && ./$(BIN_NAME) --output-http="http://localhost:9000" --input-dummy 0 --input-raw :9000 --input-http :9000 --memprofile=./mem.out --cpuprofile=./cpu.out --stats --output-http-stats --output-http-timeout 100ms
|
|
|
|
lint:
|
|
$(RUN) golint $(PKG)
|
|
|
|
race:
|
|
$(RUN) go test ./... $(ARGS) -v -race -timeout 15s
|
|
|
|
test:
|
|
$(RUN) go test ./. -timeout 120s $(LDFLAGS) $(ARGS) -v
|
|
|
|
test_all:
|
|
$(RUN) go test ./... -timeout 120s $(LDFLAGS) $(ARGS) -v
|
|
|
|
testone:
|
|
$(RUN) go test ./. -timeout 60s $(LDFLAGS) -run $(TEST) $(ARGS) -v
|
|
|
|
cover:
|
|
$(RUN) go test $(ARGS) -race -v -timeout 15s -coverprofile=coverage.out
|
|
go tool cover -html=coverage.out
|
|
|
|
fmt:
|
|
$(RUN) gofmt -w -s ./..
|
|
|
|
vet:
|
|
$(RUN) go vet
|
|
|
|
bench:
|
|
$(RUN) go test $(LDFLAGS) -v -run NOT_EXISTING -bench $(BENCHMARK) -benchtime 5s
|
|
|
|
profile_test:
|
|
$(RUN) go test $(LDFLAGS) -run $(TEST) ./capture/. $(ARGS) -memprofile mem.mprof -cpuprofile cpu.out
|
|
$(RUN) go test $(LDFLAGS) -run $(TEST) ./capture/. $(ARGS) -c
|
|
|
|
# Used mainly for debugging, because docker container do not have access to parent machine ports
|
|
run:
|
|
$(RUN) go run $(LDFLAGS) $(SOURCE) --input-dummy=0 --output-http="http://localhost:9000" --input-raw-track-response --input-raw 127.0.0.1:9000 --verbose 0 --middleware "./examples/middleware/echo.sh" --output-file requests.gor
|
|
|
|
run-2:
|
|
$(RUN) go run $(LDFLAGS) $(SOURCE) --input-raw :8000 --input-raw-bpf-filter "dst port 8000" --output-stdout --output-http "http://localhost:8000" --input-dummy=0
|
|
|
|
run-3:
|
|
sudo -E go run $(SOURCE) --input-tcp :27001 --output-stdout
|
|
|
|
run-arg:
|
|
sudo -E go run $(SOURCE) $(ARGS)
|
|
|
|
file-server:
|
|
go run $(SOURCE) file-server $(FADDR)
|
|
|
|
readpcap:
|
|
go run $(SOURCE) --input-raw $(FILE) --input-raw-track-response --input-raw-engine pcap_file --output-stdout
|
|
|
|
record:
|
|
$(RUN) go run $(SOURCE) --input-dummy=0 --output-file=requests.gor --verbose --debug
|
|
|
|
replay:
|
|
$(RUN) go run $(SOURCE) --input-file=requests.bin --output-tcp=:9000 --verbose -h
|
|
|
|
bash:
|
|
$(RUN) /bin/bash
|
|
|
|
|
|
FPMCOMMON= \
|
|
--name gor \
|
|
--description "GoReplay is an open-source network monitoring tool which can record your live traffic, and use it for shadowing, load testing, monitoring and detailed analysis." \
|
|
-v $(VERSION) \
|
|
--vendor "Leonid Bugaev" \
|
|
-m "<support@goreplay.org>" \
|
|
--url "https://goreplay.org" \
|
|
-s dir \
|
|
-C /tmp/gor-build \
|
|
|
|
build_packages:
|
|
mkdir -p /tmp/gor-build
|
|
go build -i -o /tmp/gor-build/$(BIN_NAME)
|
|
fpm $(FPMCOMMON) -a amd64 -t deb ./=/usr/local/bin
|
|
fpm $(FPMCOMMON) -a amd64 -t rpm ./=/usr/local/bin
|