gin-gonic/gin

[question] help for multiple port or multiple instance for http services

tsingson opened this issue ยท 11 comments

hi,

func main() {
    router := gin.Default()
    router.GET("/", func(c *gin.Context) {
       ....
    })
    router.Run(":8080") // data services 

    routerAdmin := gin.Default()
    routerAdmin.GET("/", func(c *gin.Context) {
        .....
    })
    routerAdmin.Run(":8090") // admin and monitor services 
}

but , only one port ( 8080 port ) working

yet, i know there some others solution to split different URL rout for two propose.
i just want to know single program can service tow port or not.

some one help for this??
thanks a lot.

gin.Run() is blocking so you have to call them in separate goroutines if you want to accomplish that.

@tsingson @Slimmy is right.

func main() {
    router := gin.Default()
    router.GET("/", func(c *gin.Context) {
       ....
    })
    go router.Run(":8080") // data services 

    routerAdmin := gin.Default()
    routerAdmin.GET("/", func(c *gin.Context) {
        .....
    })
    routerAdmin.Run(":8090") // admin and monitor services 
}

@Slimmy @manucorporat thanks a lot!!

you can do it like this:
go func() { router1.Run("127.0.0.1:9000") }()
router2.Run("127.0.0.1:8000")

Is there support for multiple sites/vhosts?

See the PR #1119 and the following example:

package main

import (
	"log"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"golang.org/x/sync/errgroup"
)

var (
	g errgroup.Group
)

func router01() http.Handler {
	e := gin.New()
	e.Use(gin.Recovery())
	e.GET("/", func(c *gin.Context) {
		c.JSON(
			http.StatusOK,
			gin.H{
				"code":  http.StatusOK,
				"error": "Welcome server 01",
			},
		)
	})

	return e
}

func router02() http.Handler {
	e := gin.New()
	e.Use(gin.Recovery())
	e.GET("/", func(c *gin.Context) {
		c.JSON(
			http.StatusOK,
			gin.H{
				"code":  http.StatusOK,
				"error": "Welcome server 02",
			},
		)
	})

	return e
}

func main() {
	server01 := &http.Server{
		Addr:         ":8080",
		Handler:      router01(),
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
	}

	server02 := &http.Server{
		Addr:         ":8081",
		Handler:      router02(),
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
	}

	g.Go(func() error {
		return server01.ListenAndServe()
	})

	g.Go(func() error {
		return server02.ListenAndServe()
	})

	if err := g.Wait(); err != nil {
		log.Fatal(err)
	}
}

Hi, Run multiple service using Gin can use https ? I want create a http and https multiple service

Hi! How to use graceful shutdown with multiple servers?

cdyue commented

Hi! How to use graceful shutdown with multiple servers?

any update?

What is the scenario on graceful shutdown with multiple servers?

Can this considered graceful? Not full code, but main idea is shown

type CSrv struct {
	done    chan struct{}
	sig     chan struct{}	
	running bool
	mux     sync.RWMutex
}

func New() *CSrv {
	return &C{
		done: make(chan struct{}),
		sig:  make(chan struct{}),
	}
}

func (c *CSrv ) Run() (err error) {
	router := gin.New()
	//router.Use(middleware.CORS())
	router.Use(gin.Logger())
	router.Use(gin.Recovery())
	router.GET("someRoute", routeHandler)

	srv := &http.Server{
		Addr:    "localhost:1111",
		Handler: router,
	}
	go c.waitForStop(srv)
	return srv.ListenAndServe()
}

func (c *C) waitForStop(srv *http.Server) {
	c.setRunning(true)
	defer close(c.sig)
	<-c.done	
	log.Println("Shutdown")
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal(err)
	}
	log.Println("Shutdown chart")	
}

func (c *CSrv) Stop() {
	if c.isRunning() {
		c.setRunning(false)
		close(c.done)
		<-c.sig
	}
}

func (c *CSrv) isRunning() bool {
	c.mux.RLock()
	defer c.mux.RUnlock()
	return c.running
}

func (c *CSrv) setRunning(val bool) {
	c.mux.Lock()
	defer c.mux.Unlock()
	c.running = val
}

func TestRun(t *testing.T) {
	csrv := New()
	var errG errgroup.Group

	errG.Go(func() error {
		return srv.Run()
	})
	// making some requests, check some stuff...
	....
	chrt.Stop()
	if err = errG.Wait(); err != nil {
		if !strings.HasSuffix(err.Error(), "Server closed") {
			t.Fatal(err)
		}		
	}
}

For now using this only in tests.