Hero Image
Bind JSON with jsoniter in Gin

Bind JSON with jsoniter in Gin simple go build -tags=jsoniter ./... custom implement BindingBody interface // github.com/gin-gonic/gin@v1.6.3/binding/binding.go:36 // Binding describes the interface which needs to be implemented for binding the // data present in the request such as JSON request body, query parameters or // the form POST. type Binding interface { Name() string Bind(*http.Request, interface{}) error } // BindingBody adds BindBody method to Binding. BindBody is similar with Bind, // but it reads the body from supplied bytes instead of req.Body. type BindingBody interface { Binding BindBody([]byte, interface{}) error } package custom import ( "bytes" "fmt" "io" "net/http" jsoniter "github.com/json-iterator/go" "github.com/gin-gonic/gin/binding" ) // BindingJSON replaces Gin's default binding and supports richer JSON features var BindingJSON = jsonBinding{} // You can customize jsoniter config or add plugins var json = jsoniter.ConfigCompatibleWithStandardLibrary type jsonBinding struct{} func (jsonBinding) Name() string { return "json" } func (jsonBinding) Bind(req *http.Request, obj interface{}) error { if req == nil || req.Body == nil { return fmt.Errorf("invalid request") } return decodeJSON(req.Body, obj) } func (jsonBinding) BindBody(body []byte, obj interface{}) error { return decodeJSON(bytes.NewReader(body), obj) } func decodeJSON(r io.Reader, obj interface{}) error { decoder := json.NewDecoder(r) if binding.EnableDecoderUseNumber { decoder.UseNumber() } if binding.EnableDecoderDisallowUnknownFields { decoder.DisallowUnknownFields() } if err := decoder.Decode(obj); err != nil { return err } return validate(obj) } func validate(obj interface{}) error { if binding.Validator == nil { return nil } return binding.Validator.ValidateStruct(obj) } // Replace binding.JSON with the custom one ctx.ShouldBindWith(ms, binding.JSON) ctx.ShouldBindBodyWith(ms, binding.JSON)

Hero Image
Fix Nginx 500 errors (too many open files, connection)

Fix Nginx 500 errors (too many open files, connection) Nginx 500 errors only show up in logs. Two common cases: socket() failed (24: Too many open files) while connecting to upstream $ sudo su - www-data $ ulimit -n # check current limit (ulimit -a shows all params) 1024 # vim /etc/security/limits.conf # set nofile (max number of open files) # add/modify the following two lines * soft nofile 655360 * hard nofile 655360 ulimit -n # log out and log back in to see the new value 655360 # If ulimit -n is not 655360, run ulimit -n 655360 to force set it # Then verify with ulimit -n or ulimit -Sn (soft) and ulimit -Hn (hard) (or ulimit -a). # Calculate and set from system level lsof | wc -l # count open files sudo vim /etc/sysctl.conf fs.file-max = 3268890 sudo sysctl -p 512 worker_connections are not enough while connecting to upstream # /etc/nginx/nginx.conf worker_connections 10240; # Refer to Nginx CoreModule # worker_processes 2; # worker_rlimit_nofile 10240; # events { # # worker_connections 10240; # } # Increasing Nginx connections can slow down overall speed because php-cgi is not enough. # Adjust as follows. # php-cgi was started with phpfcgid_children="10" and phpfcgid_requests="500" # ab was run on another server, connect via a switch using GBit ethernet # http://till.klampaeckel.de/blog/archives/30-PHP-performance-III-Running-nginx.html # vim /etc/nginx/nginx.conf worker_connections 10240; worker_rlimit_nofile # vim /etc/init.d/php-fcgi PHP_FCGI_CHILDREN=15 PHP_FCGI_MAX_REQUESTS=1000 change to PHP_FCGI_CHILDREN=512 # or 150 and increase gradually, watch MySQL connections PHP_FCGI_MAX_REQUESTS=10240 # The article's phpfcgid_stop() function is good and can be used if needed. # phpfcgid_stop() { # echo "Stopping $name." # pids=`pgrep php-cgi` # pkill php-cgi # wait_for_pids $pids # }