Skip to content
Permalink
Browse files

Merge pull request #3 from sorah/isuroxy

Implemented proxy
  • Loading branch information...
rosylilly committed Oct 22, 2017
2 parents 2681545 + 2e11577 commit e2d5352794a1a7614518136089abf6c634db0c07
@@ -0,0 +1,3 @@
bin
pkg
src/github.com
@@ -0,0 +1,11 @@
GOPATH := ${PWD}
export GOPATH

build: bin/isuroxy

dependency: deps
@cat deps | xargs -n 1 go get -v

bin/isuroxy: dependency src/**/*.go
@mkdir -p bin
go build -o bin/isuroxy -v isuroxy
@@ -0,0 +1,9 @@
#!/bin/bash -ex

cd ~/isubata/proxy

make build

sudo cp isubata.proxy.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl restart isubata.proxy
@@ -0,0 +1 @@
github.com/go-redis/redis
@@ -0,0 +1,22 @@
[Unit]
Description = isucon7 qualifier proxy application for fetch

[Service]
WorkingDirectory=/home/isucon/isubata/proxy
EnvironmentFile=/home/isucon/env.sh
Environment=RACK_ENV=production

ExecStart = /home/isucon/isubata/proxy/bin/isuroxy

Restart = always
Type = simple
User = isucon
Group = isucon

RuntimeDirectory=isubata

LimitNOFILE=16384
LimitNOFILESoft=16384

[Install]
WantedBy = multi-user.target
@@ -0,0 +1,31 @@
package main

import (
"os"
"strconv"
"time"
)

func main() {
backend := os.Getenv("ISUROXY_BACKEND")
if len(backend) == 0 {
backend = "localhost:5000"
}

timeout := os.Getenv("ISUROXY_TIMEOUT")
if len(timeout) == 0 {
timeout = "5"
}

ts, err := strconv.Atoi(timeout)
if ts == 0 || err != nil {
ts = 5
}

s := &Server{
Backend: backend,
Timeout: time.Duration(ts) * time.Second,
}

s.Start()
}
@@ -0,0 +1,104 @@
package main

import (
"github.com/go-redis/redis"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"time"
)

const STREAM_KEY = "isubata:stream:message"

type receiver chan struct{}

type Server struct {
redis *redis.Client
receivers chan receiver

Backend string
Timeout time.Duration
}

func (s *Server) Wait() {
rec := make(receiver, 1)
s.receivers <- rec

select {
case <-rec:
return
case <-time.After(s.Timeout):
return
}
}

func (s *Server) Director(request *http.Request) {
s.Wait()
request.URL.Scheme = "http"
request.URL.Host = s.Backend
}

func (s *Server) initRedis() {
redisURL := os.Getenv("ISUBATA_REDIS_URL")
if len(redisURL) == 0 {
redisURL = "redis://localhost:6379/0"
}

u, err := url.Parse(redisURL)
if err != nil {
log.Println("Can't parse redis URL. Check your ISUBATA_REDIS_URL")
log.Fatal(err.Error())
}

s.redis = redis.NewClient(&redis.Options{
Addr: u.Host,
DB: 0, // use default DB
})

_, err = s.redis.Ping().Result()
if err != nil {
log.Println("Can't connect to redis. Check your ISUBATA_REDIS_URL")
log.Fatal(err.Error())
}

go func() {
for {
pubsub := s.redis.Subscribe(STREAM_KEY)

for {
_, err := pubsub.ReceiveMessage()
if err != nil {
log.Println("PubSub error")
log.Fatal(err.Error())
break
}

for rec := range s.receivers {
rec <- struct{}{}
}
}
}
}()
}

func (s *Server) Start() {
s.receivers = make(chan receiver, 1000)
s.initRedis()

rp := &httputil.ReverseProxy{Director: s.Director}
server := http.Server{
Addr: ":9000",
Handler: rp,
}

server.SetKeepAlivesEnabled(true)

log.Println("=== Started ===")
log.Printf("Backend: %s / Timeout: %s", s.Backend, s.Timeout)

if err := server.ListenAndServe(); err != nil {
log.Fatal(err.Error())
}
}

0 comments on commit e2d5352

Please sign in to comment.
You can’t perform that action at this time.