go-zero icon indicating copy to clipboard operation
go-zero copied to clipboard

Why v1.8.1 remove ServeHTTP method? This method works on serverless services

Open jaronnie opened this issue 5 months ago • 32 comments
trafficstars

Image

for example vercel(https://vercel.com/docs/functions/runtimes/go):

func Index(w http.ResponseWriter, r *http.Request) {
	server.ServeHTTP(w, r)
}

jaronnie avatar May 24 '25 06:05 jaronnie

It's only for test purpose.

The best practices is to create a rest.Server and addRoutes, then start the server.

kevwan avatar May 24 '25 08:05 kevwan

I want to deploy go-zero rest services using serverless architecture, such as vervcel serverless. If the server has ServeHTTP method, I can directly connect to the vercel function and deploy the service on vercel.

You can look https://vercel.com/docs/functions/runtimes/go

jaronnie avatar May 24 '25 09:05 jaronnie

Prior to version 1.8.1, go-zero services could be deployed on vercel, which is the best practice in serverless architecture.

jaronnie avatar May 24 '25 09:05 jaronnie

I think this method is not only used for testing, it has a greater purpose. Frameworks like gin, echo, etc. all support ServeHTTP and can be connected to the vercel platform.

jaronnie avatar May 24 '25 09:05 jaronnie

see this blog: https://www.minoic.top/%E5%9C%A8-vercel-%E4%B8%AD%E5%BB%BA%E7%AB%8B-go-gin-%E7%9A%84%E7%BD%91%E7%AB%99%E6%9C%8D%E5%8A%A1/

jaronnie avatar May 24 '25 09:05 jaronnie

Got it. I'll investigate this and if necessary, I'll add it back.

But for the previous implementation, bindRoutes will be called for each request. It causes memory leak, and it's only used in test purpose.

Thanks for your feedback!

kevwan avatar May 24 '25 16:05 kevwan

Ok, looking forward to ServeHTTP being added back

jaronnie avatar May 25 '25 03:05 jaronnie

hi @jaronnie

Would you please do a code review and check if the PR #4896 meets the requirement? Thanks!

kevwan avatar May 25 '25 08:05 kevwan

OK

jaronnie avatar May 25 '25 09:05 jaronnie

can you create a branch in zeromicro/go-zero. Then I can go get to test in workflows

jaronnie avatar May 25 '25 10:05 jaronnie

Would you please use it from https://github.com/kevwan/go-zero/tree/rest/feat-servehttp

kevwan avatar May 25 '25 12:05 kevwan

I will use replace to solve.

replace (
	github.com/zeromicro/go-zero => github.com/kevwan/go-zero v0.0.0-20250525082407-0d5bcc60fb34
)

jaronnie avatar May 25 '25 12:05 jaronnie

You can see: https://jzero-admin-deploy-server.vercel.app/api/version

jaronnie avatar May 25 '25 13:05 jaronnie

jzero-admin deployed repo: https://github.com/jaronnie/jzero-admin-deploy-server which support vercel and aliyun serverless platform.

jaronnie avatar May 25 '25 13:05 jaronnie

jzero admin repo is: https://github.com/jzero-io/jzero-admin

jaronnie avatar May 25 '25 13:05 jaronnie

How do you use it in serverless service? Would you please give me an example code?

kevwan avatar May 25 '25 13:05 kevwan

You can see this file: https://github.com/jaronnie/jzero-admin-deploy-server/blob/main/api/client.go

jaronnie avatar May 25 '25 13:05 jaronnie

I think I can write an example code in https://github.com/zeromicro/zero-examples

jaronnie avatar May 25 '25 13:05 jaronnie

I've update the PR.

kevwan avatar May 25 '25 13:05 kevwan

it looks easier now

jaronnie avatar May 25 '25 13:05 jaronnie

Does it work for you?

kevwan avatar May 25 '25 14:05 kevwan

after update, https://jzero-admin-deploy-server.vercel.app/api/version 404

jaronnie avatar May 25 '25 14:05 jaronnie

Did you start the server?

kevwan avatar May 25 '25 15:05 kevwan

before update the PR, it works for me. In serverless mode, just register handler to server then use server.Serve(w, r)

jaronnie avatar May 25 '25 16:05 jaronnie

Image you should bind routes to router

jaronnie avatar May 26 '25 01:05 jaronnie

You need to start the server, otherwise, options doesn't apply.

Also, bindRoutes for each request causes memory leak.

kevwan avatar May 26 '25 02:05 kevwan

Will using the Start() method result in listening to the port? Can NewRestServer add an option to not listen to the port?

jaronnie avatar May 26 '25 03:05 jaronnie

I'll start it and see if it works.

jaronnie avatar May 26 '25 03:05 jaronnie

Unfortunately it doesn't work properly. I think I still need to add a NewRestServer with option. Only bindRoutes when starting. Or is there any better way?

jaronnie avatar May 26 '25 03:05 jaronnie

add two methods:

// Serve is for serverless purpose.
// Don't use it when using the Server in regular HTTP server mode.
// see https://vercel.com/docs/functions/runtimes/go
func (s *Server) Serve(w http.ResponseWriter, r *http.Request) {
	s.router.ServeHTTP(w, r)
}

// BindRoutes binds the routes to the server.
// It's for serverless purpose.
// You should call it before calling Serve().
func (s *Server) BindRoutes() error {
	return s.ngin.bindRoutes(s.router)
}

usage:

func init() {
  server = rest.MustNewServer(c.Rest.RestConf, rest.WithCustomCors(func(header http.Header) {
		header.Set("Access-Control-Allow-Origin", "*")
		header.Add("Access-Control-Allow-Headers", "X-Request-Id")
		header.Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
	}, nil, "*"))
  logx.Must(server.BindRoutes())
}

func Index(w http.ResponseWriter, r *http.Request) {
	server.Serve(w, r)
}

it works ok with jzero-admin service ! Do you think this is okay? If it's ok, I can add this method to your branch

jaronnie avatar May 26 '25 04:05 jaronnie