Skip to content

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

Closed
@tsingson

Description

@tsingson

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.

Activity

JimmyPettersson85

JimmyPettersson85 commented on Jun 22, 2015

@JimmyPettersson85

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

manucorporat

manucorporat commented on Jul 5, 2015

@manucorporat
Contributor

@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 
}
tsingson

tsingson commented on Jul 5, 2015

@tsingson
Author

@Slimmy @manucorporat thanks a lot!!

shen-xianpeng

shen-xianpeng commented on Aug 1, 2016

@shen-xianpeng

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

eubyte

eubyte commented on Dec 16, 2016

@eubyte

Is there support for multiple sites/vhosts?

appleboy

appleboy commented on Sep 28, 2017

@appleboy
Member

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)
	}
}
feiyuchuixue

feiyuchuixue commented on Oct 8, 2018

@feiyuchuixue

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

kai-zer-ru

kai-zer-ru commented on Aug 20, 2019

@kai-zer-ru

Hi! How to use graceful shutdown with multiple servers?

cdyue

cdyue commented on Feb 19, 2021

@cdyue

Hi! How to use graceful shutdown with multiple servers?

any update?

appleboy

appleboy commented on Feb 21, 2021

@appleboy
Member

What is the scenario on graceful shutdown with multiple servers?

KnBrBz

KnBrBz commented on Aug 6, 2021

@KnBrBz

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @appleboy@manucorporat@JimmyPettersson85@tsingson@kai-zer-ru

      Issue actions

        [question] help for multiple port or multiple instance for http services · Issue #346 · gin-gonic/gin