Running two web server at the same time in one go programm - go

In a go program, I want to run two web servers at the same time,
obviously they will be serving on two different ports (and ip addresses if necessary),
the problem is with the call to http.handle, when I try to register handler for '/' for the second server, it panics and says there is already a handler associated with '/',
I guess I need to create a mux in addition to the DefaultServeMux and I tried to do it using the gorillaMux but couldn't figure it out,
Is there something fundamentally wrong with running two web servers in the same program/process.
To make it more clear, one of the two web servers is a being used as a regular web server, I need the second one to act as an RPC server to communicate stuff between instances of the program running on different nodes of a cluster,
EDIT: to make it a bit more clear, this is not the actual code but it is the gist
myMux := http.NewServeMux()
myMux.HandleFunc("/heartbeat", heartBeatHandler)
http.Handle("/", myMux)
server := &http.Server{
Addr: ":3400",
Handler: myMux,
}
go server.ListenAndServe()
gorillaMux := mux.NewRouter()
gorillaMux.HandleFunc("/", indexHandler)
gorillaMux.HandleFunc("/book", bookHandler)
http.Handle("/", gorillaMux)
server := &http.Server{
Addr: ":1234",
Handler: gorillaMux,
}
log.Fatal(server.ListenAndServe())

I think you just need remove these lines:
http.Handle("/", myMux)
http.Handle("/", gorillaMux)
All routes are already defined in myMux and gorillaMux.
Check this: http://play.golang.org/p/wqn4CZ01Z6

Related

Golang grpc.server: Understanding notions of server, and services

I am trying to understand the notions of Listener, Server and Services in the context of gRPC, Protobuf.
Let's use example on https://grpc.io/docs/languages/go/basics/ as a reference.
Here we have
Listener: lis
gRPC Server: grpcServer := grpc.NewServer()
Service: RouteGuide service
It appears we can also have more than one service registered to the same server.
That is, besides RouteGuide Service, we can have say SomeOther Service, SomeOtherOther Service.
And we can register all the three and expect the server to be able to serve methods belong to this three services (RouteGuide, SomeOther, SomeOtherOther).
Let's say RouteGuide, SomeOther, SomeOtherOther each have their own proto files specific to them. And all of the protos are in the same namespace (package value).
grpcServer := grpc.NewServer(opts...)
newRouteGuideService := pb.NewRouteGuideServer()
pb.RegisterRouteGuideServer(grpcServer, newRouteGuideService)
someOtherService := pb.NewSomeOtherServer()
pb.RegisterSomeOtherServer(grpcServer, someOtherService)
someOtherOtherService := pb.NewSomeOtherOtherServer()
pb.RegisterSomeOtherOtherService(grpcServer, someOtherOtherService)
lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", 80))
grpcServer.Serve(lis)
It appears the term Server is, so to speak, overloaded here.
Not only grpcServer, but also RouteGuide, SomeOther, and SomeOtherOther are also referred to as Servers.
I am trying to figure out how to model or understand the notions.
Can we say, the server gRPCServer through listener lis listens on port 80 and can serve the three services RouteGuide, SomeOther, SomeOtherOther which are registered with it (gRPCServer)?
Is having one server service multiple services error prone?
What are the caveats to keep in mind when using one server with multiple services?
Remember that Golang is Compositional. So if you lay this out in a stripped down pseudo manner:
// Simplified Example
//The interfaces would be made by your proto definition
type Service1 interface {
// does service 1 stuff
ServiceHandler1()
ServiceHandler2()
}
type S1 struct{}
func(*S1) ServiceHandler1() {
//do svc1 stuff
}
type S2 struct{}
func(*S2) ServiceHandler2() {
//do svc2 stuff
}
type S3 struct{
// compose s1, s2
S1
S2
}
The server is the top level of the GRPC that has a listener, then you register the services that satisfy the interface required by your GRPC proto definition.
So in the case above, I could have ServiceHandler1 and ServiceHander2 defined in proto rpc. Registering S1 wouldn't satisfy it, registering S2 wouldn't, but registering S3 would.
Similarly you can break up the rpc proto into two services, one for method 1 and one for method 2 and treat them independently. In this case you could register, S1 for service 1, S2 for service 2, and S3 as either of them.
When a request comes in:
Request --> Listener --> GRPC Server --> Multiplexed to Handler --> Spawns goroutine to Handle Request
TLDR; doesn't matter where the things come from as long as they satisfy the Service Interface. Registrations can even be changed at runtime dynamically.
The listener listens for connections on a given port, and when a client connects, it creates a new goroutine to handle that particular session. The listener continues listening on the port for new incoming connections while the goroutine handles that particular client connection.
The session simply listens for the requests from the connected client and dispatches them to one of the registered services. The incoming request includes the name of the service, the function to call, and the arguments to that function. When the service handles the request, the response is sent back to the client.
So, as you say, the server listens on a port and can serve all the registered services through that port. This is not error-prone, and not that different from having one registered service defining all those functions.
Can we say, the server gRPCServer through listener lis listens on port
80 and can serve the three services RouteGuide, SomeOther,
SomeOtherOther which are registered with it (gRPCServer)?
Yes. I could not describe better.
Is having one server service multiple services error prone?
No, no problem at all. You will eventually need to have a server serving multiple services, specially if you need side services (e.g. health checker, metrics, caching, etc.). So your clients do not have to know all methods from the main service.
What are
the caveats to keep in mind when using one server with multiple
services?
(opinion) I have nothing in mind at this moment, but of course you need to wisely choose which services will be served together because you do not want to overload your server or mix logic.

How does Golang's LDAP client library work with certificates?

I'm trying to connect to G Suite's LDAPS server with Golang's LDAP library.
However, in the example, I don't really understand two things.
It seems like it connects via non-encrypted LDAP first? Then it upgrades? Is that true, if so, can't I just start out by connecting encrypted?
Google supplies a .cer & .key file to connect to their ldap server. I don't see where it use these files. I do see in their docs that a lot of LDAP clients require the files to be combined into a .p12. Is that necessary for Go?
If the person that answers this could supply an example, that would really help. Thank you.
StartTLS, as you've noted, allows one to upgrade a connection to use a TLS later on in the connections lifecycle.
If you want to connect via TLS immediately, then use the well known ldaps port 636 (instead of 389) - and use DialTLS:
// l, err := ldap.Dial("tcp", "ldap.example.com:389"))
var tlsConf *tls.Config
ldaps, err := ldap.DialTLS("tcp", "gsuite.google.com:636", tlsConf)
You may also use DialURL which infers TLS or non-TLS by the schema e.g.
conn, err := ldap.DialURL("ldap://ldap.example.com") // non-TLS on default port 389
conn, err := ldap.DialURL("ldaps://ldap.example.com") // TLS on default port 636
conn, err := ldap.DialURL("ldaps://myserver.com:1234") // TLS on custom port 1234
// Note: there is no way to add a custom tls.Config with this method
So if using, DialTLS: since you are using a Google service, it's trust cert should already be in your keychain, so a simple tls.Config should suffice:
tlsConf = &tls.Config{ServerName:"gsuite.google.com"} // <- ensure this matches the hostname provided by the server
If you want to get things up an running for testing:
// DONT EVER USE THIS IN PRODUCTION...
tlsConf = &tls.Config{InsecureSkipVerify: true} // DO NOT USE EVER
To add a client cert for client-side authentication:
// Load cer & key files into a pair of []byte
cert, err := tls.X509KeyPair(cer, key)
if err != nil {
log.Fatal(err)
}
tlsCong := &tls.Config{Certificates: []tls.Certificate{cert}}

How to put sub-directory/sub-domain in another server (or shared hosting)

I have a Go server-side program hosted on an Ubuntu 18.04 server. I want to handle example.com with Go, then example.com/blog or blog.example.com with PHP in shared hosting.
I prefer to do this with Go itself, not with another web server (ex: Nginx),
How can I do this?
You need to handle the endpoints served by another server/process as a reverse proxy. The standard library gives you httputil.ReverseProxy, which acts as a standard http.Handler, to make this very easy.
Try something like this:
target, err := url.Parse("http://blog.example.com/")
if err != nil {
panic(err)
}
proxy := httputil.NewSingleHostReverseProxy(target)
mux.Handle("/blog", proxy)

http connections stuck in close_wait state

I'm using gin to build a simple api server. right now, after the server started a few minutes later, all of incoming requests were stuck. After checking connections state , I got a message like below :
I already have tried to set c.Request.Close=true or c.Header("Connection","close") or both of them, but it was not working. I was wondering if anyone can help me fix this issue.
UPDATE-1 the way to start server
runtime.GOMAXPROCS(runtime.NumCPU())
//start serving
r := gin.New()
r.Use(gin.LoggerWithWriter(logFile))
r.Use(gin.RecoveryWithWriter(logFile))
r.Use(handler.SetResponseHeader())
controller.Router.RegisterRouter(r, cfg)
//r.Run(cfg.SvcHost)
s := &http.Server{
Addr: cfg.SvcHost,
Handler: r,
}
s.ListenAndServe()
UPDATE-2
after temporarily disabling the global gorm.DB instance and creating a new db connection for each request, this issue didn't occur any more.
TCP is waiting for you to close those connections. Probably you have read end of stream from them and have ignored it.

How to multiplex requests for different domains to different servers using Go?

I want to host multiple domains on the same machine, with multiple servers running on the same machine and different ports. I am trying to write a multiplexer which will redirect requests for domain "A" to the server running locally on "portA", and requests for domain "B" to the server running on "portB". How can I route those requests, while making this redirect transparent to the user and search-engine bots?
Currently, I use something like this:
package main
import (
"net/http"
"log"
)
func main() {
mux := http.NewServeMux()
mux.Handle("mydomainA.com", http.RedirectHandler("http://localhost:1234", 302))
mux.Handle("mydomainB.com", http.RedirectHandler("http://localhost:4567", 302))
log.Fatal(http.ListenAndServe(":8080", mux))
}
(just posting #james-odoherty's comment as an answer since he hasn't)
You want to use the httputil.ReverseProxy type from the net/http/httputil package.

Resources