Gorm is not connecting to AWS Postgres, but also not throwing an error. Just hanging

blov · · 749 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I&#39;m trying to use gorm as an ORM for an app, but gorm.Open doesn&#39;t appear to ever return, which is making my app hang. The only difference between my test case and all the examples I&#39;ve seen online is my test case is connected to an AWS box, whereas all the others are connecting to local Postgres instances. Does that matter?</p> <p>The code that I have is:</p> <pre><code>func initDB() { var err error db, err := gorm.Open(&#34;postgres&#34;, &#34;host=something.rds.amazonaws.com user=awsuser dbname=db sslmode=disable password=awspassword&#34;) if err != nil { panic(err) } log.Printf(&#34;Connected&#34;) defer db.Close() } </code></pre> <p>I&#39;ve tried switching sslmode, I&#39;ve tried using the postgres connection string (pulled straight from a postgres client so it is valid), I&#39;ve tried switching to sql.Open. I don&#39;t know what else there is to try. FWIW I can see that none of my requests are hitting AWS.</p> <p><em>edit</em> I connect from this machine all the time, so it is not an AWS Security Group misconfig.</p> <p><em>edit</em> Now using: </p> <pre><code>db, err := gorm.Open(&#34;postgresql&#34;, &#34;user:pass@something.rds.amazonaws.com:5432/db?connect_timeout=5&#34;) </code></pre> <p>Still no luck.</p> <hr/>**评论:**<br/><br/>robbles: <pre><p>Have you tried connecting with a command line postgres client from the same machine?</p> <p>If not, this is likely caused by a security group misconfiguration. Usually when an instance isn&#39;t allowing access to a port, you get this kind of hanging connection issue instead of just an error.</p></pre>MEAT_FIST: <pre><p>I connect from this machine all the time. I&#39;ll add that to the OP.</p></pre>robbles: <pre><p>It looks like you&#39;re not seeing the port to connect to. Maybe your other client has a different default?</p></pre>MEAT_FIST: <pre><p>Default for libpq is 5432, which is what I&#39;ve used to connect to this database since I&#39;ve started using it.</p></pre>tusharsingh: <pre><p>How are you importing postgres?</p></pre>MEAT_FIST: <pre><pre><code> _ &#34;github.com/jinzhu/gorm/dialects/postgres&#34; &#34;github.com/jinzhu/gorm&#34; </code></pre></pre>scrubby: <pre><p>Does Gorm use lib/pq under the covers? Because you might have to set the connect_timeout in the connection string for lib/pq to actually time out when it can&#39;t connect. </p></pre>MEAT_FIST: <pre><p>I&#39;m pretty new to Go, so I&#39;m not totally sure how to find out other than scowering the Gorm source itself.</p> <p>I can say, when I tried to run my app after installing Gorm, I got:</p> <pre><code>Alexs-iMac:app alex$ go run main.go ../../jinzhu/gorm/dialects/postgres/postgres.go:7:2: cannot find package &#34;github.com/lib/pq&#34; in any of: /usr/local/Cellar/go/1.7/libexec/src/github.com/lib/pq (from $GOROOT) /Users/alex/Code/go/src/github.com/lib/pq (from $GOPATH) </code></pre> <p>Which is why I then installed lib/pq</p></pre>scrubby: <pre><p>Looks like it then. </p> <p>Try adding connect_timeout=10 to your connection string above and see if it times out and gives you an error after 10 seconds. Might give you more insight into the connection problem.</p></pre>MEAT_FIST: <pre><pre><code>db, err := gorm.Open(&#34;postgresql&#34;, &#34;user:pass@something.rds.amazonaws.com:5432/db?connect_timeout=5&#34;) </code></pre> <p>Still did not return a value.</p></pre>niosop: <pre><blockquote> <p>I connect from this machine all the time, so it is not an AWS Security Group misconfig.</p> </blockquote> <p>Using Go, or another language/tool? If not Go, could you try just using github.com/lib/pq to see if it&#39;s a gorm or PostgreSQL issue? Also, try the IP of the instance instead of the hostname to eliminate potential DNS resolution issues.</p></pre>MEAT_FIST: <pre><p>I&#39;ve used PG Admin 3, SQL-Tabs, the command line, and a Node.js application to connect to this instance, which makes me think this issue is specific to Gorm.</p></pre>ecmdome: <pre><p>The gorm postgres driver seems to be at fault. As I suggested in another comment and <a href="/u/niosop" rel="nofollow">/u/niosop</a> suggested use lib/pq alongside gorm removing the gorm postgres package.</p></pre>MEAT_FIST: <pre><p>I totally removed Gorm and am just trying to connect with <code>database/sql</code> and <code>lib/pq</code> and am running into the exact same problem, which makes sense as Gorm&#39;s postgres dialect runs on lib/pq.</p></pre>ecmdome: <pre><p>And are you using just &#34;postgres&#34; as driver and not &#34;postgresql&#34; like in your example? Look at the link I posted.</p></pre>the_web_dev: <pre><p>I work on a web app that uses many different persistent connections (Postgres, Redis, Mongo, GRPC) and am pretty familiar with various drivers and ORMs for doing so. </p> <p>Many libraries have a different take on the Options{} struct that typically gets passed to a .Dial()-like function. Some accept full connection strings (postgres://), some might have a host attribute that expects a port as well, some do their own string concatenation or formatting. So my first step when working with a new library is to read the Godoc for configuration and find out what exactly it is I&#39;m working with. I know you just got started with Go and this may seem like a hassle, but it really is a pivotal part of the language to be simple enough that reading the docs is a breeze that makes things go much smoother in the long run.</p> <p>Second to this I&#39;ve found almost every driver/library has default settings that should be tweaked. Whether it&#39;s a timeout, reconnection attempts, whatever, you&#39;ll usually want to fix something if it&#39;s intended to be used in production. With postgres and redis for example you usually want to configure a pool with a large number of connections to increase throughput. </p> <p>Anyways, if you can&#39;t figure it out from that you have a few options:</p> <ul> <li><p>use just the pq driver to make sure it is a gorm specific issue</p></li> <li><p>change your format to something more standard like a connection string, ensure it&#39;s in your program (I use environmental variables for this and I frequently forget to add these before testing..), and parse then with net/url before feeding them to dial().</p></li> <li><p>raise an issue on github with as much context and code as possible</p></li> <li><p>try a different &#34;orm&#34;, personally I use gopkg.in/pg.v4 and it works really well.</p></li> </ul> <p>EDIT:</p> <p>After reading the code for GORMs .Open() it get&#39;s a little hairy and it&#39;s hard to follow the breadcrumbs back to the actual .Dial() block which makes the connection using the driver. GORMs been around for awhile and uses a lot of (IMO) non idiomatic abstraction that will make it harder for a beginner to dive in. I would recommend starting with something simpler. Go does not do ORMs well and though GORM may be a valid attempt at it it won&#39;t give you the same experience you might expect from ORMs in other languages.</p></pre>Justinsaccount: <pre><p>You&#39;re not setting the timeout.</p> <p>According to the docs for lib/pq:</p> <pre><code>* connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. </code></pre> <p><code>postgres://username:password@rds.host:5432/db</code> is not a thing. As far as I can tell it causes lib/pq to attempt to connect to localhost.</p> <p>So,</p> <pre><code>db, err := gorm.Open(&#34;postgres&#34;, &#34;host=something.rds.amazonaws.com user=awsuser dbname=db sslmode=disable password=awspassword connect_timeout=5&#34;) </code></pre> <blockquote> <p>FWIW I can see that none of my requests are hitting AWS.</p> </blockquote> <p>What method did you use to determine this?</p></pre>MEAT_FIST: <pre><p>I guess I assumed that because lib/pq link to the Postgres connection string documentation, they support Postgres connection strings.</p> <p>AWS&#39;s console to view connections and connection attempts, specifically.</p></pre>Justinsaccount: <pre><blockquote> <p>I guess I assumed that because lib/pq link to the Postgres connection string documentation, they support Postgres connection strings.</p> </blockquote> <p>I don&#39;t know... I did some quick tests and it did not appear to work at all. connect_timeout=5 added on to what you were using did work:</p> <pre><code>$ grep host foo.go;go run foo.go db, err := gorm.Open(&#34;postgres&#34;, &#34;host=10.10.10.10 user=awsuser dbname=db sslmode=disable password=awspassword connect_timeout=5&#34;) panic: dial tcp 10.10.10.10:5432: i/o timeout goroutine 1 [running]: panic(0x28f5a0, 0xc4201a2000) /usr/local/Cellar/go/1.7/libexec/src/runtime/panic.go:500 +0x1a1 main.main() /tmp/foo.go:14 +0x180 exit status 2 </code></pre> <p>Compared to</p> <pre><code>$ grep host foo.go;go run foo.go db, err := gorm.Open(&#34;postgres&#34;, &#34;host=10.10.10.10 user=awsuser dbname=db sslmode=disable password=awspassword&#34;) // connect_timeout=5&#34;) [hangs] </code></pre> <blockquote> <p>AWS&#39;s console to view connections and connection attempts, specifically.</p> </blockquote> <p>Ah, don&#39;t trust that.</p> <pre><code>sudo tcpdump -n -i eth0 host something.rds.amazonaws.com </code></pre> <p>When I do that with the foo.go with no timeout running It will just show</p> <pre><code>23:14:21.367137 IP 192.168.1.100.60096 &gt; 10.10.10.10.5432: Flags [S], seq 1325003949, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 1323636256 ecr 0,sackOK,eol], length 0 23:14:22.372454 IP 192.168.1.100.60096 &gt; 10.10.10.10.5432: Flags [S], seq 1325003949, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 1323637256 ecr 0,sackOK,eol], length 0 23:14:23.381828 IP 192.168.1.100.60096 &gt; 10.10.10.10.5432: Flags [S], seq 1325003949, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 1323638256 ecr 0,sackOK,eol], length 0 23:14:24.384735 IP 192.168.1.100.60096 &gt; 10.10.10.10.5432: Flags [S], seq 1325003949, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 1323639256 ecr 0,sackOK,eol], length 0 23:14:25.388429 IP 192.168.1.100.60096 &gt; 10.10.10.10.5432: Flags [S], seq 1325003949, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 1323640256 ecr 0,sackOK,eol], length 0 23:14:58.264175 IP 192.168.1.100.60103 &gt; 10.10.10.10.5432: Flags [S], seq 1171804356, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 1323673061 ecr 0,sackOK,eol], length 0 23:14:59.265943 IP 192.168.1.100.60103 &gt; 10.10.10.10.5432: Flags [S], seq 1171804356, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 1323674061 ecr 0,sackOK,eol], length 0 23:15:00.269278 IP 192.168.1.100.60103 &gt; 10.10.10.10.5432: Flags [S], seq 1171804356, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 1323675061 ecr 0,sackOK,eol], length 0 23:15:01.269956 IP 192.168.1.100.60103 &gt; 10.10.10.10.5432: Flags [S], seq 1171804356, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 1323676061 ecr 0,sackOK,eol], length 0 </code></pre> <p>as it tries and fails to connect over and over again.</p></pre>MEAT_FIST: <pre><p>I switched over to the style of <code>.Open</code> arguments you told me to, and am still not having any luck. I also totally removed Gorm from the equation and am just attempting to connect with <code>database/sql</code> and <code>lib/pq</code>, but it&#39;s still not returning an error or connecting (even with <code>connect_timeout=5</code> set).</p> <p>Another test I was told to try was just using <code>psql</code> and connecting to the instance from the CLI, so I did and it worked as expected.</p> <p>I&#39;m kind of running out of ideas.</p></pre>Justinsaccount: <pre><p>Well, I have tons of ideas still, plus the ones you have not tried yet. To start, no one really knows what code you are running since all you pasted was a fragment. Your problem could be elsewhere for all anyone knows. You could have misspelled connect_timeout like I did 3 times before I got my test program to work.</p> <p>Run this test program EXACTLY, do not change anything:</p> <pre><code>package main import ( &#34;database/sql&#34; &#34;log&#34; &#34;time&#34; _ &#34;github.com/lib/pq&#34; ) func main() { var err error now := time.Now() defer func() { log.Printf(&#34;Exited after %v&#34;, time.Since(now)) }() log.Printf(&#34;Opening...&#34;) db, err := sql.Open(&#34;postgres&#34;, &#34;host=10.10.10.10 user=awsuser dbname=db sslmode=disable password=awspassword connect_timeout=5&#34;) defer db.Close() if err != nil { log.Print(err) return } log.Printf(&#34;Opened, pinging...&#34;) err = db.Ping() if err != nil { log.Print(err) return } log.Printf(&#34;Ping ok!&#34;) } </code></pre> <p>Result of running this locally:</p> <pre><code>$ go run db.go 2016/10/08 21:22:48 Opening... 2016/10/08 21:22:48 Opened, pinging... 2016/10/08 21:22:53 dial tcp 10.10.10.10:5432: i/o timeout 2016/10/08 21:22:53 Exited after 5.000477025s </code></pre> <p>Times out and fails exactly at 5 seconds.</p> <p>Now, change the <code>10.10.10.10</code> to your something.rds.amazonaws.com and run it again.</p> <p>If it still acts weird, run tcpdump to see what it is doing.</p></pre>MEAT_FIST: <pre><p>Hey. This is awesome. Thanks. Your example worked exactly how you said in the first case, and then connected successfully in the second case.</p> <p>Since it was clear I <em>could</em> connect, as you said, something else about my code was wrong.</p> <p>In the main function of the app, the call to initialize the database was the line after <code>http.ListenAndServe(&#34;:8080&#34;, Router)</code>, which (for whatever reason) seemed to be the problem. If I move <code>initDB()</code> to the line before <code>http.ListenAndServe</code> I am able to connect successfully. Now I suppose I&#39;ll troubleshoot why that is...</p></pre>Justinsaccount: <pre><p>Because <code>http.ListenAndServe(&#34;:8080&#34;, Router)</code> blocks forever.</p></pre>MEAT_FIST: <pre><p>Lessons learned:</p> <ul> <li>Post a full code example</li> <li>Read more deeply into Go packages (in this case, http and http.ListenAndServe) before posting.</li> </ul></pre>r0y3: <pre><p>Try <a href="https://github.com/jmoiron/sqlx" rel="nofollow">https://github.com/jmoiron/sqlx</a> instead.

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

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