Scaling Go Applications: Difference between revisions

From bibbleWiki
Jump to navigation Jump to search
Line 15: Line 15:
*Centralized Logging
*Centralized Logging
AGAIN this is an approach and of course you can use third-party cloud solutions. This one will be confined to Docker and GO.
AGAIN this is an approach and of course you can use third-party cloud solutions. This one will be confined to Docker and GO.
==Initial Optimizations==
=Initial Optimizations=
==Content Compression==
One of the easiest things to do is to change the http messages to use compression in our messages.
===Gzip Handler===
For this we write a GzipHandler.
<syntaxhighlight lang="go">
package util
 
import (
"compress/gzip"
"net/http"
"strings"
)
 
type CloseableResponseWriter interface {
http.ResponseWriter
Close()
}
 
type gzipResponseWriter struct {
http.ResponseWriter
*gzip.Writer
}
 
func (w gzipResponseWriter) Write(data []byte) (int, error) {
return w.Writer.Write(data)
}
 
func (w gzipResponseWriter) Close() {
w.Writer.Close()
}
 
func (w gzipResponseWriter) Header() http.Header {
return w.ResponseWriter.Header()
}
 
type closeableResponseWriter struct {
http.ResponseWriter
}
 
func (w closeableResponseWriter) Close() {}
 
func GetResponseWriter(w http.ResponseWriter, req *http.Request) CloseableResponseWriter {
if strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") {
w.Header().Set("Content-Encoding", "gzip")
gRW := gzipResponseWriter{
ResponseWriter: w,
Writer:        gzip.NewWriter(w),
}
return gRW
} else {
return closeableResponseWriter{ResponseWriter: w}
}
}
 
type GzipHandler struct{}
 
func (h *GzipHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
responseWriter := GetResponseWriter(w, r)
defer responseWriter.Close()
 
http.DefaultServeMux.ServeHTTP(responseWriter, r)
}
</syntaxhighlight>
===Implement on Server===
To we can now use this within the server.
<syntaxhighlight lang="go">
func main() {
...
go http.ListenAndServe(":3000", new(util.GzipHandler))
</syntaxhighlight>
 
==Creating a Load Balancer==
==Creating a Load Balancer==
==Caching==
==Caching==
==Centralized Logging==
==Centralized Logging==

Revision as of 12:14, 28 January 2021

Introduction

Resources

When we look at scaling we must consider the following resources.

  • Network Bandwidth
  • Processing Power
  • Available Memory
  • Data Storage

For this page we will be looking a the challenges around breaking an application in to several servers and following an architecture such as below This not meant to be THE solution but a walkthrough on some of the challenges to scale. This will be split into

  • Initial Optimizations
  • Creating a Load Balancer
  • Caching
  • Centralized Logging

AGAIN this is an approach and of course you can use third-party cloud solutions. This one will be confined to Docker and GO.

Initial Optimizations

Content Compression

One of the easiest things to do is to change the http messages to use compression in our messages.

Gzip Handler

For this we write a GzipHandler.

package util

import (
	"compress/gzip"
	"net/http"
	"strings"
)

type CloseableResponseWriter interface {
	http.ResponseWriter
	Close()
}

type gzipResponseWriter struct {
	http.ResponseWriter
	*gzip.Writer
}

func (w gzipResponseWriter) Write(data []byte) (int, error) {
	return w.Writer.Write(data)
}

func (w gzipResponseWriter) Close() {
	w.Writer.Close()
}

func (w gzipResponseWriter) Header() http.Header {
	return w.ResponseWriter.Header()
}

type closeableResponseWriter struct {
	http.ResponseWriter
}

func (w closeableResponseWriter) Close() {}

func GetResponseWriter(w http.ResponseWriter, req *http.Request) CloseableResponseWriter {
	if strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") {
		w.Header().Set("Content-Encoding", "gzip")
		gRW := gzipResponseWriter{
			ResponseWriter: w,
			Writer:         gzip.NewWriter(w),
		}
		return gRW
	} else {
		return closeableResponseWriter{ResponseWriter: w}
	}
}

type GzipHandler struct{}

func (h *GzipHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	responseWriter := GetResponseWriter(w, r)
	defer responseWriter.Close()

	http.DefaultServeMux.ServeHTTP(responseWriter, r)
}

Implement on Server

To we can now use this within the server.

func main() {
...
	go http.ListenAndServe(":3000", new(util.GzipHandler))

Creating a Load Balancer

Caching

Centralized Logging