Skip to content

Instantly share code, notes, and snippets.

@mefellows
Last active September 22, 2015 12:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mefellows/28e613be093b1c18429d to your computer and use it in GitHub Desktop.
Save mefellows/28e613be093b1c18429d to your computer and use it in GitHub Desktop.
Nginx - DNSMasq, Docker, Gatling and Muxy
# (where docker is the ip of your docker host).
curl -v -H"Host: api.foo.com" docker:8001 # API via Nginx
curl -v docker:8002 # API directly
## Nginx, but using our stubbed out DNS and API endpoints
nginx:
build: ../
links:
- dns:dnsmasq
- api:api.foo.com
ports:
- "8001:80"
volumes:
- "./log:/var/log/nginx/"
## Responds to DNS queries and sends them to our Mock API
dns:
build: ../dnsmasq
ports:
- 53:53
links:
- api:api.foo.com
## Echo / Mock Server to pretend to be our real application
api:
build: mockapi
ports:
- "8002:80"
# This guy runs our Unit tests!
test:
build: integration-test
command: go test -v ./...
links:
- nginx:api.foo.com
nginx:
build: .
ports:
- "8001:80"
volumes:
- "/var/log/nginx:/var/log/nginx/"
links:
- dns:dnsmasq
- api:api.foo.local
api:
build: test/mockapi
ports:
- "8002:80"
dns:
build: ./dnsmasq
ports:
- "5353:53"
links:
- api:api.foo.local
func header(c web.C, w http.ResponseWriter, r *http.Request) {
key := c.URLParams["header"]
id := r.Header.Get(key)
if strings.ToLower(key) == "host" {
id = r.Host
}
w.Header().Add(key, id)
fmt.Fprintf(w, "%s=>%s", key, id)
}
func main() {
goji.Get("/header/:header", header)
goji.Serve()
}
package main
import (
"fmt"
"net/http"
"strings"
"sync"
"testing"
)
func Test100calls(t *testing.T) {
host := fmt.Sprintf("http://api.foo.com/header/x-host")
wait := &sync.WaitGroup{}
wait.Add(100)
for i := 0; i < 100; i++ {
go func() {
defer wait.Done()
resp, err := http.Get(host)
fmt.Println(resp)
checkErr(err, false, t)
if resp.StatusCode != 200 {
t.Fatalf("Expected 200 response code, but got %d", resp.StatusCode)
}
_body := make([]byte, 9)
resp.Body.Read(_body)
body := strings.TrimSpace(string(_body))
}()
}
fmt.Println("Waiting for all requests to finish...")
wait.Wait()
}
func checkErr(err error, expected bool, t *testing.T) {
if err != nil && !expected {
t.Fatalf("Error not expected: %s", err.Error())
} else if err == nil && expected {
t.Fatalf("Error expected, but did not get one")
}
}
./scripts/run-tests.sh muxy
## Test configuration name. Used for reporting.
name: Network and HTTP screwer.
## Test Description. Used for reporting
description: Slow network to mobile levels, and add 1s delay to all messages
## Specify log output level
##
## Log Levels supported:
## Trace (0), Debug (1), Info (2, Default), Warn (3), Error (4), Fatal (5)
loglevel: 0
## Configure a proxy that will handle your requests, and forward
## to proxied host.
##
## Currently supports `tcp_proxy` and `http_proxy`.
proxy:
## HTTP Proxy: Configures an HTTP Proxy
##
## NOTE: SSL is currently not supported
- name: http_proxy
config:
host: 0.0.0.0
port: 80
protocol: http
proxy_host: api.foo.com
proxy_port: 80
proxy_protocol: http
## Middleware
##
## Middleware are plugins that are given the opportunity to intervene
## before a request is dispatched to the proxied system (PRE_DISPATCH event)
## and afterwards (POST_DISPATCH event). They are given a reference to
## the current context (HTTP Context or []bytes) and can mutate them.
##
## Middleware are executed in the order specified in this config.
##
middleware:
## Request Logger - use this to see what's going in/out of the Proxy.
##
##
- name: logger
config:
hex_output: false # Display output as Hex instead of a string
## Network Shaper - Layer 4 Tamperer.
##
## Uses Comcast (github.com/tylertreat/comcast) to shape and interfere with network traffic,
## including bandwidth, latency, packet loss and jitter on specified ports, IPs and protocols.
##
## NOTE: This plugin requires root/sudo access to run
##
- name: network_shape
config:
latency: 1000 # Latency to add in ms
target_bw: 750 # Bandwidth in kbits/s
default_bw: 750
packet_loss: 50 # Packet loss, as a %
target_ports:
- "80"
target_protos: # Target protocols
- "tcp"
- "udp"
- "icmp"
target_ips:
- "0.0.0.0/0"
device: "eth0"
- name: http_tamperer
config:
response:
status: 500 # Override HTTP Status code
# Use a DNS resolver as part of the DNS caching hack (only required for free version)
#
# No need to use these, DHCP Option Sets should be properly configured per VPC
# DNSMasq will automatically recursively use these if there is no local match
resolver dnsmasq:5353;
package au.com.onegeek.nginxperf
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class Nginx extends Simulation {
val httpConf = http
.baseURL("http://api.foo.com")
.acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
.doNotTrackHeader("1")
.acceptLanguageHeader("en-US,en;q=0.5")
.acceptEncodingHeader("gzip, deflate")
.userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0")
val scn = scenario("BasicSimulation")
.repeat(10) {
exec(http("request_1")
.get("/header/host"))
}
setUp(
scn.inject(rampUsers(10000) over (1 seconds))
).protocols(httpConf)
}
./scripts/run-tests.sh perf
...
...
...
perf_1 | ================================================================================
perf_1 | 2015-09-21 09:07:40 84s elapsed
perf_1 | ---- BasicSimulation -----------------------------------------------------------
perf_1 | [##########################################################################]100%
perf_1 | waiting: 0 / active: 0 / done:10000
perf_1 | ---- Requests ------------------------------------------------------------------
perf_1 | > Global (OK=100000 KO=0 )
perf_1 | > request_1 (OK=100000 KO=0 )
perf_1 | ================================================================================
perf_1 |
perf_1 | Simulation finished
perf_1 | Parsing log file(s)...
perf_1 | Parsing log file(s) done
perf_1 | Generating reports...
perf_1 |
perf_1 | ================================================================================
perf_1 | ---- Global Information --------------------------------------------------------
perf_1 | > request count 100000 (OK=100000 KO=0 )
perf_1 | > min response time 0 (OK=0 KO=- )
perf_1 | > max response time 36233 (OK=36233 KO=- )
perf_1 | > mean response time 5637 (OK=5637 KO=- )
perf_1 | > std deviation 2542 (OK=2542 KO=- )
perf_1 | > response time 50th percentile 6217 (OK=6217 KO=- )
perf_1 | > response time 75th percentile 6911 (OK=6911 KO=- )
perf_1 | > mean requests/sec 1184.553 (OK=1184.553 KO=- )
perf_1 | ---- Response Time Distribution ------------------------------------------------
./scripts/run-tests.sh integration
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment