<p>I'm trying to use gorm as an ORM for an app, but gorm.Open doesn't appear to ever return, which is making my app hang. The only difference between my test case and all the examples I'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("postgres", "host=something.rds.amazonaws.com user=awsuser dbname=db sslmode=disable password=awspassword")
if err != nil {
panic(err)
}
log.Printf("Connected")
defer db.Close()
}
</code></pre>
<p>I've tried switching sslmode, I've tried using the postgres connection string (pulled straight from a postgres client so it is valid), I've tried switching to sql.Open. I don'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("postgresql", "user:pass@something.rds.amazonaws.com:5432/db?connect_timeout=5")
</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'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'll add that to the OP.</p></pre>robbles: <pre><p>It looks like you'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've used to connect to this database since I've started using it.</p></pre>tusharsingh: <pre><p>How are you importing postgres?</p></pre>MEAT_FIST: <pre><pre><code> _ "github.com/jinzhu/gorm/dialects/postgres"
"github.com/jinzhu/gorm"
</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't connect. </p></pre>MEAT_FIST: <pre><p>I'm pretty new to Go, so I'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 "github.com/lib/pq" 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("postgresql", "user:pass@something.rds.amazonaws.com:5432/db?connect_timeout=5")
</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'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'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's postgres dialect runs on lib/pq.</p></pre>ecmdome: <pre><p>And are you using just "postgres" as driver and not "postgresql" 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'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've found almost every driver/library has default settings that should be tweaked. Whether it's a timeout, reconnection attempts, whatever, you'll usually want to fix something if it'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'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'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 "orm", 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's a little hairy and it'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't give you the same experience you might expect from ORMs in other languages.</p></pre>Justinsaccount: <pre><p>You'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("postgres", "host=something.rds.amazonaws.com user=awsuser dbname=db sslmode=disable password=awspassword connect_timeout=5")
</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'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'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("postgres", "host=10.10.10.10 user=awsuser dbname=db sslmode=disable password=awspassword connect_timeout=5")
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("postgres", "host=10.10.10.10 user=awsuser dbname=db sslmode=disable password=awspassword") // connect_timeout=5")
[hangs]
</code></pre>
<blockquote>
<p>AWS's console to view connections and connection attempts, specifically.</p>
</blockquote>
<p>Ah, don'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 > 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 > 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 > 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 > 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 > 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 > 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 > 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 > 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 > 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'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'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 (
"database/sql"
"log"
"time"
_ "github.com/lib/pq"
)
func main() {
var err error
now := time.Now()
defer func() {
log.Printf("Exited after %v", time.Since(now))
}()
log.Printf("Opening...")
db, err := sql.Open("postgres", "host=10.10.10.10 user=awsuser dbname=db sslmode=disable password=awspassword connect_timeout=5")
defer db.Close()
if err != nil {
log.Print(err)
return
}
log.Printf("Opened, pinging...")
err = db.Ping()
if err != nil {
log.Print(err)
return
}
log.Printf("Ping ok!")
}
</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(":8080", 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'll troubleshoot why that is...</p></pre>Justinsaccount: <pre><p>Because <code>http.ListenAndServe(":8080", 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.
Gorm is not connecting to AWS Postgres, but also not throwing an error. Just hanging
blov · · 749 次点击这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传