When does it make sense to use a goroutine?

agolangf · · 544 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Assuming I have an API. When someone calls /register, the password is hashed, stored in the database and something is written to the log file. Would it make sense to start a goroutine for the logging part? Or should one just keep it as it is?</p> <p>Another example might be /information/placexyz. One goroutine would look up api1, number 2 would request data from another api and number 3 would queue the database on the server itself. The &#34;main&#34; method waits for all routines to return their results and a json is send to the client.</p> <p>Just as examples. Is there any guideline when a goroutine would make sense / improve performance?</p> <hr/>**评论:**<br/><br/>bonekeeper: <pre><p>Whatever involves some I/O (like reading/writing to a database, remote API request, etc) is a good candidate, unless it is in a tight loop. Also, sometimes, having a fixed number of workers to offload that stuff to makes more sense than just blindly spawning new goroutines (for example, there is usually a limit to how many open connections a database will keep so just spawning a new goroutine and opening a new connection to the database everywhere would be detrimental - that&#39;s one of the reasons there is a pool of DB connections).</p></pre>ArghusSquare: <pre><p>Thank you</p></pre>tmornini: <pre><p>Use a goroutine when you want a function to run independently and asynchronously to the code that invokes the function.</p> <p>Your example of an endpoint that invoked other HTTP requests is a good example.</p> <p>Keep in mind that the net/http package calls your handlerfunc in a goroutine, so it runs asynchronously to all other requests already.</p> <p>One thing I don&#39;t understand is what you mean by &#34;queue the database&#34;</p> <p>And it&#39;s critical to understand that when you say &#34;waits for all routines to return their results&#34; that you mean &#34;receives results for all goroutines on channels&#34; :-)</p></pre>ArghusSquare: <pre><blockquote> <p>One thing I don&#39;t understand is what you mean by &#34;queue the database&#34;</p> </blockquote> <p>I&#39;m aware that the handlerfuncs are already goroutines. What I mean with queuing the database is getting data from my own database. For example the handler does the following:</p> <pre><code>[go?] getDataFromExternalAPI1() [go?] getDataFromExternalAPI2() [go?] getDataFromDB() // with func (*DB) Query [go?] logToDBFile() wait for results from channels </code></pre> <p>Currently I do not have a function for every single one of these actions. I guess the real question is: When is the overhead of goroutines too big so just keeping them in the handler function is better?</p></pre>nhooyr: <pre><p>You&#39;d have to benchmark it to really know.</p></pre>tmornini: <pre><p>Depends on what you mean by overhead.</p> <p>If the goal is CPU efficiency then don&#39;t use go routines.</p> <p>If the goal is minimum response time, use go routines.</p></pre>jerf: <pre><p>While I agree that you&#39;d have to benchmark to really know, goroutine overhead is on the order of 1 microsecond to start them up (give or take an order of magnitude), and relatively small numbers for task switching when IO occurs. External APIs are generally milliseconds away, so goroutine overhead is very likely lost in the shuffle there. For the cost of more complicated code than raw serial code, you&#39;ll get better responsiveness if you put those in goroutines because you&#39;ll get the answers in parallel, or in the worst case, at least be running your timeouts in parallel.</p> <p>A local DB is a closer call; it is possible to have queries that run fast enough that goroutine overhead could be noticeable. I say &#34;noticeable&#34; rather than dominant because you&#39;d have to be doing some awfully simple stuff to some awfully simple databases for an in-process goroutine to be the <em>dominant</em> cost of such an access. But I&#39;d say the vast majority of the time goroutine overhead on such a task will still be lost in the noise; hundreds of microseconds or entire milliseconds for a response from such things would be fairly normal.</p> <p>Logging is its own complicated topic. It has costs that people generally find non- or even counter-intuitive. You&#39;d have to benchmark it.</p></pre>ArghusSquare: <pre><p>Thanks, that helps :)</p></pre>karma_vacuum123: <pre><p>remember you need to synchronize your goroutines too....and that is a great place to make mistakes</p></pre>oh-thatguy: <pre><p>Ugh. Yes.</p></pre>dirkharrington: <pre><p>Your handler is already being called backed in a goroutine as part of the std library</p></pre>NikkoTheGreeko: <pre><p>Go routines should only be used if you need them. You only know if you need them by benchmarking and finding bottlenecks, blocking, etc after the program is built. I wouldn&#39;t recommend trying to plan out how to spawn off Go routines when you first start your project unless you really know what you&#39;re doing, or else you risk introducing a lot of unnecessary debugging nightmares.</p></pre>karma_vacuum123: <pre><p>the only reason to do this would be some implications for logging itself blocking. if you are using <code>rsyslog</code>, it is typically configured with udp so this should not be a concern. many other log aggregation mechanisms will default to udp for similar reasons...it is better for a logger to fail outright than block mainline execution</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

544 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传