问题
Background: I'm running Go on GAE and using Mux for my router. In order to fetch a URL GAE requires that I use its built in urlFetch capability. I want to make this URL fetch happen during my modules init() but as far as I can tell I can only use urlFetch when invoked via a handler.
func init() {
r := mux.NewRouter()
r.HandleFunc("/", homeHandler)
r.HandleFunc("/about", anotherHandler)
http.Handle("/", r)
}
GAE suggests the following code for making a urlFetch:
c := appengine.NewContext(r)
client := urlfetch.Client(c)
... but its argument is an http router, and it doesn't want to work if I pass my mux router. So I'm out of ideas of how to make this urlFetch happen outside the scope of a URL handler.
Error when passing the mux router: "cannot use r (type *mux.Router) as type *http.Request in argument to "appengine".NewContext"
回答1:
You can't use AppEngine services that require a Context outside of handlers (because the creation of a Context
requires an *http.Request value). This by nature means you can't use them in package init()
functions either.
Note that you can use them from cron jobs and tasks added to task queues, because tasks and cron jobs are executed by issuing HTTP GET requests.
You have to restructure your code so that the service (urlFetch in your case) gets called from a handler.
A possible solution is to check if init completed in handlers that serve user requests. If not, perform the initialization function you would otherwise put in init()
before proceeding to serve the request.
Yes, this may cause first requests to take considerably longer to serve. For this purpose (to avoid this) I recommend you to utilize Warmup requests. A warmup request is issued to a new instance before it goes "live", before it starts serving user requests. In your app.yaml
config file you can enable warmup requests by adding -warmup
to the inbound_services
directive:
inbound_services:
- warmup
This will cause the App Engine infrastructure to first issue a GET
request to /_ah/warmup
. You can register a handler to this URL and perform initialization tasks. As with any other request, you will have an http.Request in the warmup handler.
But please note that:
..you may encounter loading requests, even if warmup requests are enabled in your app.
Which means that in rare cases it may happen a new instance will not receive a warmup request, so its best to check initialization state in user handlers too.
来源:https://stackoverflow.com/questions/29912318/fetching-a-url-from-the-init-func-in-go-on-appengine