Example #1
0
/* TODO: Implement more probes */
func (s *Server) probe_backends(probe time.Duration) {
	transport := http.Transport{Dial: dialTimeout}
	client := &http.Client{
		Transport: &transport,
	}

	for {
		time.Sleep(probe)
		for vhost, backends := range s.proxy {
			fmt.Println(backends)
			err := s.populate_proxies(vhost)
			if err != nil {
				utils.Log(fmt.Sprintf("Cleaned entries from vhost: %s", vhost))
				continue
			}
			is_dead := make(map[string]bool)
			removed := 0
			for backend := range backends {
				backend = backend - removed
				utils.Log(fmt.Sprintf(
					"vhost: %s backends: %s", vhost, s.proxy[vhost][backend].Backend))
				if is_dead[s.proxy[vhost][backend].Backend] == true {
					utils.Log(fmt.Sprintf("Removing dead backend: %s", s.proxy[vhost][backend].Backend))
					s.mu.Lock()
					s.proxy[vhost] = s.proxy[vhost][:backend+copy(s.proxy[vhost][backend:], s.proxy[vhost][backend+1:])]
					s.vcount[vhost][s.proxy[vhost][backend].Backend]--
					s.mu.Unlock()
					removed++
					continue
				}

				_, err := client.Get(s.proxy[vhost][backend].Backend)
				if err != nil {
					utils.Log(fmt.Sprintf("Removing dead backend: %s with error %s", s.proxy[vhost][backend].Backend, err))
					is_dead[s.proxy[vhost][backend].Backend] = true
					s.mu.Lock()
					s.proxy[vhost] = s.proxy[vhost][:backend+copy(s.proxy[vhost][backend:], s.proxy[vhost][backend+1:])]
					s.vcount[vhost][s.proxy[vhost][backend].Backend]--
					s.mu.Unlock()
					removed++
				} else {
					utils.Log(fmt.Sprintf("Alive: %s", s.proxy[vhost][backend].Backend))
				}
			}
		}
		transport.CloseIdleConnections()
	}
}
Example #2
0
/* TODO: Implement more balance algorithms */
func (s *Server) Next(vhost string) http.Handler {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.backend[vhost]++
	total := len(s.proxy[vhost])
	if s.backend[vhost] >= total {
		s.backend[vhost] = 0
	}
	utils.Log(fmt.Sprintf(
		"Using backend: %s Url: %s", s.proxy[vhost][s.backend[vhost]].Backend, vhost))
	return s.proxy[vhost][s.backend[vhost]].handler
}
Example #3
0
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if h := s.handler(r); h != nil {
		client := xff(r)
		utils.Log(fmt.Sprintf("Request from: %s Url: %s", client, r.Host))
		r.Header.Add("X-Forwarded-For‎", client)
		r.Header.Add("X-Real-IP", client)
		h.ServeHTTP(w, r)
		// probe should act here
		fmt.Println(w.Header())
		return
	}
	http.Error(w, "Not found.", http.StatusNotFound)
}
Example #4
0
func (s *Server) handler(req *http.Request) http.Handler {
	vhost := req.Host
	if i := strings.Index(vhost, ":"); i >= 0 {
		vhost = vhost[:i]
	}

	_, ok := s.proxy[vhost]
	if !ok {
		err := s.populate_proxies(vhost)
		if err != nil {
			utils.Log(fmt.Sprintf("%s for vhost %s", err, vhost))
			return nil
		}
	}
	return s.Next(vhost)
}
Example #5
0
func main() {
	utils.Log("Starting Hot Potato Router...")
	probe_interval, _ := strconv.Atoi(cfg.Options["hpr"]["probe_interval"])
	if probe_interval == 0 {
		probe_interval = 10
	}
	s, err := http_server.NewServer(time.Duration(probe_interval) * time.Second)
	utils.CheckPanic(err, "Unable to spawn")

	if cfg.Options["hpr"]["https_addr"] != "" {
		cert, err := tls.LoadX509KeyPair(cfg.Options["hpr"]["cert_file"], cfg.Options["hpr"]["key_file"])
		utils.CheckPanic(err, "Unable to load certificate")

		c := &tls.Config{Certificates: []tls.Certificate{cert}}
		l := tls.NewListener(http_server.Listen(cfg.Options["hpr"]["https_addr"]), c)
		go func() {
			utils.CheckPanic(http.Serve(l, s), "Problem with https server")
		}()
	}
	utils.CheckPanic(
		http.Serve(http_server.Listen(cfg.Options["hpr"]["http_addr"]), s),
		"Problem with http server")
}
Example #6
0
func (s *Server) populate_proxies(vhost string) (err error) {
	s.mu.RLock()
	defer s.mu.RUnlock()
	f, _ := rc.ZRange(fmt.Sprintf("hpr-backends::%s", vhost), 0, -1, true)
	if len(f) == 0 {
		if len(s.proxy[vhost]) > 0 {
			delete(s.proxy, vhost)
			delete(s.backend, vhost)
			delete(s.vcount, vhost)
		}
		return errors.New("Backend list is empty")
	}

	var url string
	for _, be := range f {
		count, err := strconv.Atoi(be)
		if err != nil {
			url = be
			continue
		}
		backend := fmt.Sprintf("http://%s", url)
		for r := 1; r <= count; r++ {
			if r <= s.vcount[vhost][backend] {
				continue
			}
			s.proxy[vhost] = append(s.proxy[vhost], Proxy{backend, makeHandler(url)})
			v, ready := s.vcount[vhost]
			if !ready {
				v = make(map[string]int)
				s.vcount[vhost] = v
			}
			s.vcount[vhost][backend]++
			utils.Log(fmt.Sprintf("Backend %s with %d handlers for %s", backend, s.vcount[vhost][backend], vhost))
		}
	}
	return
}