Commit f3d86fea authored by mohammad.salama's avatar mohammad.salama

Initial commit

parents
{
"listenPort": ":8080",
"healthCheckInterval": "5s",
"servers": [
"http://localhost:8001",
"http://localhost:8002"
]
}
\ No newline at end of file
package main
import (
"encoding/json"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"net/url"
"sync"
"time"
)
type Server struct {
URL *url.URL // URL of the backend server.
ActiveConnections int // Count of active connections
Mutex sync.Mutex // A mutex for safe concurrency
Healthy bool
}
type Config struct {
HealthCheckInterval string `json:"healthCheckInterval"`
Servers []string `json:"servers"`
ListenPort string `json:"listenPort"`
}
func loadConfig(file string) (Config, error) {
var config Config
bytes, err := ioutil.ReadFile(file)
if err != nil {
return config, err
}
err = json.Unmarshal(bytes, &config)
if err != nil {
return config, err
}
return config, nil
}
func nextServerLeastActive(servers []*Server) *Server {
leastActiveConnections := -1
leastActiveServer := servers[0]
for _, server := range servers {
server.Mutex.Lock()
if (server.ActiveConnections < leastActiveConnections || leastActiveConnections == -1) && server.Healthy {
leastActiveConnections = server.ActiveConnections
leastActiveServer = server
}
server.Mutex.Unlock()
}
return leastActiveServer
}
func (s *Server) Proxy() *httputil.ReverseProxy {
return httputil.NewSingleHostReverseProxy(s.URL)
}
func checkServer(s *Server , healthCheckInterval time.Duration) {
for range time.Tick(healthCheckInterval) {
res, err := http.Get(s.URL.String())
if err != nil || res.StatusCode >= 500 {
s.Healthy = false
} else {
s.Healthy = true
}
}
}
func performHealthChecks(servers []*Server , healthCheckInterval time.Duration) {
for _, server := range servers {
go checkServer(server , healthCheckInterval)
}
}
func main() {
config, err := loadConfig("config.json")
if err != nil {
log.Fatalf("Error loading configuration: %s", err.Error())
}
healthCheckInterval, err := time.ParseDuration(config.HealthCheckInterval)
if err != nil {
log.Fatalf("Invalid health check interval: %s", err.Error())
}
var servers []*Server
for _, serverUrl := range config.Servers {
u, _ := url.Parse(serverUrl)
servers = append(servers, &Server{URL: u})
}
performHealthChecks(servers , healthCheckInterval)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
server := nextServerLeastActive(servers)
server.Mutex.Lock()
server.ActiveConnections++
server.Mutex.Unlock()
server.Proxy().ServeHTTP(w, r)
server.Mutex.Lock()
server.ActiveConnections--
server.Mutex.Unlock()
})
log.Println("Starting server on port", config.ListenPort)
err = http.ListenAndServe(config.ListenPort, nil)
if err != nil {
log.Fatalf("Error starting server: %s\n", err)
}
}
<!DOCTYPE html>
<html>
<head>
<title>Hello from Server "1"</title>
<style>
body, html {
height: 100%;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.flashy-text {
font-size: 48px;
animation: flash 2s infinite;
}
@keyframes flash {
0% { opacity: 1; }
50% { opacity: 0; }
100% { opacity: 1; }
}
</style>
</head>
<body>
<div class="flashy-text">
Hello from Server "1 - One"
</div>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Hello from Server "2"</title>
<style>
body, html {
height: 100%;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.flashy-text {
font-size: 48px;
animation: flash 2s infinite;
}
@keyframes flash {
0% { opacity: 1; }
50% { opacity: 0; }
100% { opacity: 1; }
}
</style>
</head>
<body>
<div class="flashy-text">
Hello from Server "2 - Two"
</div>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Hello from Server "3"</title>
<style>
body, html {
height: 100%;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.flashy-text {
font-size: 48px;
animation: flash 2s infinite;
}
@keyframes flash {
0% { opacity: 1; }
50% { opacity: 0; }
100% { opacity: 1; }
}
</style>
</head>
<body>
<div class="flashy-text">
Hello from Server "3 - Three"
</div>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment