๋ช ๋
๋์ mongoose
์ ์ฌ์ฉํ๋๋ฐ ์ต๊ทผ์๋ ์ฐ๊ฒฐ์ด ์ฌ๋ผ์ง๋ ๊ฒ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ง์ด ๋ฐ์ํฉ๋๋ค.
// Connecting to MongoDB 3.2.1
var connString = "mongodb://xxxxx:xxxxx<strong i="8">@xxxxx</strong>:xxxx,xxxx:xxxx/xxx?ssl=true";
var connOptions = {
"mongos": { "ssl": true, "sslValidate": false }
};
mongoose.connect(connString, connOptions, function(err, db) {
if(err) { console.log("Error connecting to db: "+err); }
});
๋ชฝ๊ตฌ์ค๋ ๋ค์ ์ ํ๋ฅผ ์ค๋จํฉ๋๋ค. ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง ์๊ณ ๋ฉ๋ชจ๋ฆฌ/cpu๊ฐ ๋ด ์๋ฒ ๋ฐ db์์ ์ ์์ด๋ฉฐ ๋ค๋ฅธ ์๋ฒ์์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค. ๋ค์ ์์ํ๋ฉด ํญ์ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ฉ๋๋ค.
db.Something.count({}, callback);
mongoose 4.4.11
, mongoose.connection.readyState === UNAUTHORIZED
์ฝ๋ฐฑ์ด ์ค์ง๋ ๋.
๊ทธ๋์ mongoose 4.6.0
์
๊ทธ๋ ์ด๋ ํ์ง๋ง 4์๊ฐ ์ด๋ด์ ์ฝ๋ฐฑ์ด ๋ค์ ์ค์ง๋์์ผ๋ฉฐ ์ด์ mongoose.connection.readyState === CONNECTED
์
๋๋ค.
์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์๋๋ก ํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์์ด๋์ด๊ฐ ์์ต๋๊น?
๋ ๋ง์ ๋๋ฒ๊น ์ ๋ณด๋ฅผ ์์งํ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค. ์ด๋ค ์ ๋ณด๋ฅผ ์ป์ ์ ์๋์ง ์๋ ค์ฃผ์ธ์.
๋ ๋ฆฝ ์คํํ, ๋ณต์ ๋ณธ ์ธํธ ๋๋ ๋ถํ ๋ ํด๋ฌ์คํฐ์ ์ฐ๊ฒฐํ๊ณ ์์ต๋๊น? ๋ํ SSL์ ์ฌ์ฉํ๊ณ ์๋์ง ํ์ธํ ์ ์์ต๋๊น?
์ด๊ฒ์ ์ง๋ ๋ฉฐ์น ๋์ ๋์๊ฒ ํฐ ๋ฌธ์ ์์ต๋๋ค. ์คํ ์ค์ธ ๋ชจ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ ๋๋ฆฌ๊ณ ๋ ๋๋ฆฐ ์ด๋ฒคํธ ๋ฃจํ๋ก ๋๋๊ณ ์ ์ฒด ์์คํ ์์ ์ง์ฐ ์๊ฐ์ด ์ฆ๊ฐํ์ต๋๋ค. ๋ ธ๋ ์์ฉ ํ๋ก๊ทธ๋จ์ ๋ค์ ์์ํ๋ฉด ๋งค๋ฒ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์์ผ๋ฉฐ ๋ช ๋ถ ๋๋ ๋ช ์๊ฐ ๋์ ์๋ํ ํ์ ๋ค์ ๋ํ๋ฉ๋๋ค.
mongoose 4.5.10์ผ๋ก ๋๋๋ฆฌ๋ฉด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์์ต๋๋ค.
์ฌ๊ธฐ 4.6.0๊ณผ ์ ์ฌํ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๋ณต์ ์ธํธ์ ์ฐ๊ฒฐํ๋์ง ์ฌ๋ถ๋ ํ์คํ์ง ์์ง๋ง SSL์ ์ฌ์ฉํ๋ ๊ฒ์ ํ์คํฉ๋๋ค.
FWIW, 4.6.0์ ์ง์์ ์ผ๋ก ์ฐ๊ฒฐ์ ๋์์ต๋๋ค. 4.5.10์ด ์ข์ต๋๋ค.
@djanowski ์ฐ๊ฒฐ ์ฝ๋๊ฐ ์ด๋ป๊ฒ ์๊ฒผ๋์ง, ๊ฐ์ง๊ณ ์๋ mongodb์ ๋ฒ์ ๊ณผ ๊ฐ์ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ ๊ณตํ ์ ์์ต๋๊น?
@ vkarpov15 ์ ๋ MongoDB 3.2.6์ ์ฌ์ฉํ๊ณ ์์์ต๋๋ค.
์ฐ๊ฒฐ ์ต์ :
auth: {
authMechanism: 'SCRAM-SHA-1',
},
mongos: {
ssl: true,
sslValidate: true,
sslCA: [cert],
},
๋จ์ผ ๋ชฝ๊ณ ๋๋ ๋ค์ค ๋ชฝ๊ณ ?
์ฌ๋ฌ ๋ชฝ๊ณ . Compose Mongo ๋ฐฐํฌ ์ฌ์ฉ.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ๋ ์ ์๋ ๋ค๋ฅธ ์์ ์ด ์์ต๋๊น? ์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ ์ต์ ๋ฒ์ ์ผ๋ก ์ด๋ํ๋ ๊ฒ์ ์ฐจ๋จํ๊ณ ์์ต๋๋ค...
์ฝ๋๋ฅผ ๋ณด์ง ์๊ณ ๋ ์ค์ ๊ฐ์ค์ ์ธ์ฐ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค. mongoose.connect
์ฐ๊ฒฐํ๋ ๊ฒฝ์ฐ ์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ธฐ ์์ํ ๋ mongoose.connection.readyState
๊ฐ์ ํ์ธํ๊ฒ ์ต๋๋ค. ๋ํ ๋ชจ๋ mongoose ์์
์ ๋ํด ์ฝ์์ ๋๋ฒ๊ทธ ๋ฉ์์ง๋ฅผ ์ธ์ํ๋ mongoose ๋๋ฒ๊ทธ ๋ชจ๋ mongoose.set('debug', true)
ํ์ฑํํฉ๋๋ค. ํด๋น ๋ฉ์์ง๊ฐ ์ธ์ ์ค์ธ์ง ์ฌ๋ถ๋ ๋๋ฒ๊ทธ์ ํ์คํ ๋์์ด ๋ ๊ฒ์
๋๋ค.
@vkarpov15 ์ด๊ฒ์ ๋ด๊ฐ ์ฐ๊ฒฐํ๋ ๋ฐ ์ฌ์ฉํ๋ ์ฝ๋์
๋๋ค. https://gist.github.com/sommestad/c0c6a7fa4feaadf84ecbb59cc3432c90
๊ฐ์ธ ๋ชจ๋์ ์ผ๋ถ์ด๋ฏ๋ก Gist.
_(์ฐ๊ฒฐ ๋ํ ๋ชจ๋์ ์ฌ์ฉํ๋ ์ด์ ๋ ์ญ์ฌ์ ์ผ๋ก mongoose์์ ์ ์๋ํ์ง ์์๋ ๋ค๋ฅธ private NPM ๋ชจ๋์์ ์ฐ๊ฒฐ์ด ๊ฐ๋ ์ฌ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ ๋๋ค.)_
์ด๋ฌํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ ๋ ์ฐ๊ฒฐ ์ํ ๋ก๊น ์ ํ์ฑํํ์ง๋ง ์ฐ๊ฒฐ ์์ฒด๋ ๋ณ๊ฒฝ๋์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค(์ต์ํ ์ด๋ฒคํธ๋ ๋ฐ์ํ์ง ์์). ๊ทธ๋์ ํด๋ผ์ด์ธํธ์ ์ฐ๊ฒฐ์ด ๋์ด์ง ๊ฒ ๊ฐ์ง ์์์ต๋๋ค.
URI์์ replicaSet
๋ก ์ฐ๊ฒฐ๋์ง ์์ต๋๋ค(๋์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ Compose Deployment ). ์ธ๊ธํ๋ฏ์ด SSL์ด ์ฌ์ฉ๋ฉ๋๋ค. ๋ํ ํธ๋ํฝ์ AWS NAT ๊ฒ์ดํธ์จ์ด๋ฅผ ํตํด ๋ผ์ฐํ
๋ฉ๋๋ค. AWS NAT๋ ์ ํด ์๊ฐ ์ ํ์ด 5๋ถ์ด์ง๋ง ์ด๋ฌํ ๋ฌธ์ ๋ ํธ๋ํฝ์ด ๋ง์ ๊ฒฝ์ฐ์๋ ๋ฐ์ํ์ต๋๋ค.
๋์๊ฒ ๋ช ๊ฐ์ง ๋ฌธ์ , ๋น์ ์ ๊ทธ๊ฒ์ ํด๊ฒฐ ํ์ต๋๊น?
@youth7 ์๋ ์์ด๋์ด๊ฐ ์์ต๋๋ค. ์์ฑ ๋ฐฐํฌ์๋ ์ฐ๊ฒฐํ๊ณ ์์ต๋๊น? ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ ๊ณตํ์ญ์์ค
์ด ๋ฌธ์ ์ ์์ธ์ ์ฐพ๊ธฐ ์ํด ๋ ํ ์ ์๋ ์ผ์ด ์์ต๋๊น? ์กฐ์ฌํ ์ ์๋ ์ด๋ก ์ด ์์ต๋๊น?
@sommestad๋ ๊ตฌ์ฒด์
mongoose 4.7.2
์๋ํ์ง๋ง 48์๊ฐ ํ์๋ ๋์ผํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค. ์ด ์์ ์์ ์ ๋ 4.4.11
์์ฒด์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
๋ก๊ทธ๋ฅผ ์์งํ๊ธฐ ์ํด ๋ฐ๋ชจ ์๋ฒ์ 4.7.2
๋ฅผ ์ค์นํ์ง๋ง ๋ฌธ์ ์์ด 2์ฃผ ๋์ ์คํ๋์์ต๋๋ค. ๋ฐ์ดํฐ/์ฐ๊ฒฐ/๊ธฐํ์ ๋ณผ๋ฅจ์ด ๋ฌธ์ ๋ฅผ ์ ๋ฐํฉ๋๊น?
์ผ๋จ ๋ฐ์ํ๊ธฐ ์์ํ๋ฉด ์ด๋ฅผ ์ฌํํ๋ ์ฝ๋๋ ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ์ฟผ๋ฆฌ์ ์ฝ๋ฐฑ์ด ์ฌ๋ผ์ง๋๋ค.
db.Something.find({}, callback); //this callback is never fired
๋ด๊ฐ ์ธ๊ธํ๋ฏ์ด ์ด ์ผ์ด ๋ฐ์ํ๋ฉด mongoose.connection.readyState === CONNECTED
๊ธฐ์ด ํ. mongodb ๋ก๊ทธ๋ฅผ ์๋ฏธํฉ๋๋ค. ํด๋น ์ค๋ฅ๊ฐ ๋ฐ์ํ ์์ ์ mongodb ์๋ฒ ๋ก๊ทธ๋ฅผ ๋คํํ ์ ์์ต๋๊น?
์ด ์ค๋ฅ๊ฐ ๋ฐ์ํ์ ๋ DB ๋ก๊ทธ๋ฅผ ์ค์บํ๋๋ฐ ๋น์ ์์ ์ธ ๊ฒ์ ๋ณผ ์ ์์์ต๋๋ค. ์ฐ๊ฒฐ ์, ์ฐ๊ฒฐ ๋๊น, ์ฐ๊ฒฐ ๋ฌธ์ ๋ฑ์ ๋ฌธ์ ๋ ์์์ต๋๋ค. ๋๋ ๋ํ ์์๊ฐ ์๋ชป๋ ๊ฒ์ ๋ณผ ์ ์์๋ Compose์ ์ฐ๋ฝํ์ต๋๋ค.
@bendytree HTTP ๋ถํ ํ ์คํธ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ํด๋น ๋ฐ๋ชจ ์๋ฒ์ ์ฝ๊ฐ์ ๋ณผ๋ฅจ์ ๋์ง ์ ์์ต๋๊น?
@bendytree ๋ํ Node์ ๋ชจ๋ ๋ฆด๋ฆฌ์ค ๋ผ์ธ(4.x, 6.x ๋ฐ 7.x)์์ ๋ฐ์ํฉ๋๊น?
@vkarpov15 ์ต์ MongoDB ๋๋ผ์ด๋ฒ๋ก ํ ์คํธํ ์ ์๋๋ก 4.7.7์
@vkarpov15 66d559b19a86c70e30a8f083d03eb22566571b7e ๊ฐ์ฌํฉ๋๋ค! ์๋ํด ๋ณด๊ฒ ์ต๋๋ค.
์ฌ๊ธฐ์์๋ ๋ง์ฐฌ๊ฐ์ง๋ก SSL ๋ณต์ ๋ณธ์ด ์์ต๋๋ค. ๋ช ๋ถ/์๊ฐ ํ์ ์์ฒญ์ด callback()์ผ๋ก ์ค์ง๋๊ณ (์ข ๋ ์์ธํ ๋ก๊น ์ ์ถ๊ฐํ์ต๋๋ค) ์ค๋ฅ๊ฐ ์์ต๋๋ค. ์ด์ ๋ฐค์ 4.7.7๋ก ์ ๊ทธ๋ ์ด๋ํ์ง๋ง ์ฌ์ ํ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
ํธ์ง: 4.7.0์ผ๋ก ๋ค์ด๊ทธ๋ ์ด๋ํ๋ ค๊ณ ํ์ง๋ง ์ต์ ์ด์์ต๋๋ค(5๋ถ ์ด๋ด์ ๋ฌธ์ ๊ฐ ๋ฐ์ํจ). 4.5.10์ ์๋ํ๊ณ ์์ต๋๋ค.
@gierschv ๋ ธ๋ 6.9.x?
@djanowski ์๋์, ์ฌ์ ํ 4.6/4.7.x LTS์ ์์ต๋๋ค.
@djanowski ๋ ธ๋ 4.4.2์์๋ง ์๋ํ์ต๋๋ค.
์ด ๋ฌธ์ ์ ๊ฐ๋ฅํ ์ค๋ณต ๋ชฉ๋ก ์ ์ง:
์ฐธ๊ณ ๋ก 4.5.10์ ์ฌ๊ธฐ์์ ์ ์๋ํ๋ ๊ฒ์ผ๋ก ๋ณด์ด๋ฉฐ ์ง๋ 5์๊ฐ ๋์ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค. ๋๋ ๋ํ ๋ค์ด๊ทธ๋ ์ด๋๋ก ์์ ๋ ๊ฒ์ผ๋ก ๋ณด์ด๋ ๋ชจ๋ ์ปดํจํฐ์์ #4690๊ณผ ๊ฐ์ ๋์ CPU ์ฌ์ฉ๋์ ๋ณด์์ต๋๋ค.
์ฌ๊ธฐ์ ์๋ก์ด ๊ฐ๋ฐ ์ฌํญ์ด ์์ต๋๊น? ๋ฒ๊ทธ๋ฅผ ์ฐพ๊ธฐ ์ํด ๋ ํ ์ ์๋ ์ผ์ด ์์ต๋๊น?
@sommestad ์ต์ ๋ชฝ๊ตฌ์ค์์ ์ฌ์ ํ ์ด ๋ฌธ์ ๊ฐ ์์ต๋๊น?
์ง๋๋ฒ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ฒด ์์คํ ์ ๋ง๊ฐ๋จ๋ ธ๊ธฐ ๋๋ฌธ์ ์์ง ์ ๊ทธ๋ ์ด๋๋ฅผ ๊ฐํ ํ์ง ์์์ต๋๋ค(๋ณ๊ฒฝ ์ฌํญ์ "์ผ๋ถ" ์๊ฐ ํ์ ๋ํ๋๋ฏ๋ก ์ค๋ ์คํํ์ง ์๊ณ ๋ ํ์ธํ๊ธฐ ์ด๋ ต์ต๋๋ค). ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์๋ค๊ณ ๋ฏฟ์ ๋งํ ์ด์ ๊ฐ ์๋ค๋ฉด ์์คํ ์ ๋ ๊ฒฉ๋ฆฌ๋ ๋ถ๋ถ์ ์๋ํด ๋ณผ ์ ์์ต๋๊น?
ํธ์ง: ping @varunjayaraman
์ ์ ์ฅ์์๋ ๋ช ์ฃผ ์ ์ Node 6.x LTS๋ก ์ ํํ๊ณ ๋ง์ง๋ง ๋ชฝ๊ตฌ์ค ๋ฒ์ ์ผ๋ก ์ ๊ทธ๋ ์ด๋ํ๋๋ฐ ๊ทธ ์ดํ๋ก๋ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค.
์ฐ๋ฆฌ๋ ์ฝ ๋ ๋ฌ ์ ์ Node 6.10.2, Mongoose 4.9.9๋ก ์ ๊ทธ๋ ์ด๋ํ์ต๋๋ค. ์ฌ์ ํ ๊ฐ์ ๋ฌธ์ ๊ฐ ํ์๋ฉ๋๋ค.
์ฐ๊ฒฐ ๋ฌธ์์ด์ ํ์์ mongodb://username:[email protected]:1234,db2.com:2345/db-name?ssl=true
์
๋๋ค.
console.log("fetching user...");
userCollection.findOne({_id: userId}, function(err, user){
console.log("done"); // this never happens
...
});
์ฝ๋ฐฑ์ด ์ค์ง๋๋ฉด ๋ค์ ์์๋์ง ์์ต๋๋ค. ํ๋ก์ธ์ค๋ฅผ ๋ค์ ์์ํ๋ฉด ์ ์ฐ๊ฒฐ๋ฉ๋๋ค.
๋ฌธ์ ํด๊ฒฐ์ ์ํด ์์งํ ์ ์๋ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด ๊ธฐ๊บผ์ด ๋์๋๋ฆฌ๊ฒ ์ต๋๋ค.
๋์ผํ ๋ฌธ์ ๊ฐ ํ์๋๋ฉฐ ์๋ ์ฝ๋๋ก ์ฌํํ ์ ์์ต๋๋ค(๋น ๋ฅธ ๋ชฉ์ /์ฝ๋ ์คํ์ผ์ ๋ํด ์ฃ์กํฉ๋๋ค).
์ฐ๊ฒฐ ์๊ฐ ์ด๊ณผ๋ฅผ ์๋ฎฌ๋ ์ด์ ํ๊ธฐ ์ํด poolSize๋ฅผ 1๋ก ๋ฎ์ถ๊ณ ๋ค์ ์์๋ก ํธ์ถ๋๋ 2๊ฐ์ ์๋ํฌ์ธํธ(์ผ๋ฐ/์ ์)์ ๋ํ ์์ฒญ์ ํธ๋ฆฌ๊ฑฐํ์ต๋๋ค.
๋ค์์ ์ฌ์ฉํ์ฌ ์ฌํ:
// Require modules
const mongoose = require('mongoose');
const express = require('express');
const request = require('request');
const parseJson = require('body-parser').json();
// Use native Promises in Mongoose
mongoose.Promise = Promise;
// Create the test schema
const testSchema = new mongoose.Schema({
name: {
type: String,
trim: true,
default: 'test'
}
});
// Create the mongoose model
mongoose.model('Test', testSchema, 'test');
// Create some test data
mongoose.model('Test').create([
{name: 'test1'},
{name: 'test2'},
{name: 'test3'},
{name: 'test4'},
{name: 'test5'}
]);
// Create the Express based app
const app = express();
// Create the express router
const router = express.Router();
// Create a normal route
router.route('/normal').get(parseJson, function (req, res, next) {
mongoose.model('Test').find({}).then(
function (data) {
res.status(200).json(data);
}
).catch(
function (err) {
res.status(400).json(err);
}
);
});
// Create up a slow route
router.route('/slow').get(parseJson, function (req, res, next) {
mongoose.model('Test').find({$where: 'sleep(10000) || true'}).then(
function (data) {
res.status(200).json(data);
}
).catch(
function (err) {
res.status(400).json(err);
}
);
});
// Add middleware to console log every request
var requestNumber = 1;
app.use(function (req, res, next) {
console.log('Request ' + requestNumber, req.method, req.url);
requestNumber++;
next();
});
// Use the router
app.use('/', router);
// Listen for requests
app.listen(4000, function () {
console.log('Server listening on port 4000');
});
// Catch any uncaught exceptions
process.on('uncaughtException', function (err) {
console.log('Uncaught exception', err);
});
// Catch any unhandled rejections
process.on('unhandledRejection', function (reason) {
console.error('Unhandled Rejection', reason);
});
// Database connection options
const connectionOpts = {
// Use the new connection logic
useMongoClient: true,
// Do not auto reconnect (the Node code will auto reconnect)
autoReconnect: false,
// Use a poolsize of 1 to simulate a timeout using multiple request to slow and normal endpoints
poolSize: 1
};
// Connection method with retry
const connectWithRetry = function () {
// Check if we still need to connect
if (mongoose.connection.readyState !== mongoose.Connection.STATES.connected) {
// Connect
return mongoose.connect('mongodb://localhost:27017/test', connectionOpts).catch(
function (err) {
console.log('Can not connect to mongo', err);
}
);
}
};
// Helper function to execute a request to the normal endpoint
const doRequestNormal = function () {
request({
url: 'http://localhost:4000/normal',
json: true,
timeout: 60000
}, function (error, response, body) {
if (error) {
console.log('Error on normal request', error, response);
}
console.log('Performed normal request, body:', body);
});
};
// Helper function to execute a request to the normal endpoint
const doRequestSlow = function () {
request({
url: 'http://localhost:4000/slow',
json: true,
timeout: 60000
}, function (error, response, body) {
if (error) {
console.log('Error on slow request', error, response);
}
console.log('Performed slow request', body);
});
};
// Helper function to simulate requests
const doRequests = function () {
doRequestNormal();
doRequestSlow();
doRequestNormal();
setTimeout(function () {
console.log('Do normal request after 1 minute');
doRequestNormal();
}, 60000);
};
// Connecting event
mongoose.connection.on('connecting', function () {
console.log('Connecting to database...');
});
// Connected event
mongoose.connection.on('connected', function () {
console.log('Database is connected, start requesting...');
doRequests();
});
// Timeout event
mongoose.connection.on('timeout', function (err) {
console.log('Database timeout error', err);
});
// Error event
mongoose.connection.on('error', function (err) {
console.log('Database connection error', err);
});
// Disconnected event
mongoose.connection.on('disconnected', function () {
console.error('Database got disconnected, reconnecting in 5 sec...');
// Reconnect in 5 seconds
setTimeout(connectWithRetry, 5000);
});
// Connect to the database with retry
connectWithRetry();
// Log the connection state every 10 seconds
setInterval(function () {
console.log('Mongoose connection readystate is', mongoose.connection.readyState);
}, 10000);
์ฝ์ ์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
Connecting to database...
Server listening on port 4000
Database is connected, start requesting...
Request 1 GET /normal
Request 2 GET /slow
Request 3 GET /normal
Performed normal request, body: [ { _id: '597f8c6f41bf2e119594ba1a', __v: 0, name: 'test1' },
{ _id: '597f8c6f41bf2e119594ba1b', __v: 0, name: 'test2' },
{ _id: '597f8c6f41bf2e119594ba1c', __v: 0, name: 'test3' },
{ _id: '597f8c6f41bf2e119594ba1d', __v: 0, name: 'test4' },
{ _id: '597f8c6f41bf2e119594ba1e', __v: 0, name: 'test5' } ]
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Performed slow request { name: 'MongoError',
message: 'connection 0 to localhost:27017 timed out' }
Performed normal request, body: { name: 'MongoError',
message: 'connection 0 to localhost:27017 timed out' }
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Do normal request after 1 minute
Request 4 GET /normal
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Error on normal request { Error: ESOCKETTIMEDOUT
at ClientRequest.<anonymous> (/Users/adriaanmeuris/Documents/Projecten/Mongoose timeout/node_modules/request/request.js:819:19)
at ClientRequest.g (events.js:291:16)
at emitNone (events.js:86:13)
at ClientRequest.emit (events.js:185:7)
at Socket.emitTimeout (_http_client.js:620:10)
at Socket.g (events.js:291:16)
at emitNone (events.js:86:13)
at Socket.emit (events.js:185:7)
at Socket._onTimeout (net.js:339:8)
at ontimeout (timers.js:365:14)
at tryOnTimeout (timers.js:237:5)
at Timer.listOnTimeout (timers.js:207:5) code: 'ESOCKETTIMEDOUT', connect: false } undefined
Performed normal request, body: undefined
Mongoose connection readystate is 1
Mongoose connection readystate is 1
10์ด๋ง๋ค ๋ฐ์ดํฐ๋ฒ ์ด์ค์ readyState๋ฅผ ๋ชจ๋ํฐ๋งํฉ๋๋ค. ์ด๋ ์ฐ๊ฒฐ์ด ์ฌ์ ํ ํ์ฑ ์ํ์์ ๋ํ๋ ๋๋ค. Mongoose ์ค๋ฅ/์๊ฐ ์ด๊ณผ ์ด๋ฒคํธ๊ฐ ํธ๋ฆฌ๊ฑฐ๋์ง ์๊ณ ์์ฒญ 4์ ์ฝ๋ฐฑ์ด ํธ์ถ๋์ง ์์ต๋๋ค(์์ฒญ ํจํค์ง๋ฅผ ์ฌ์ฉํ์ฌ 60์ด ํ์ ์๊ฐ ์ด๊ณผ๋จ). http://localhost :4000/slow ๋ฐ ๋ค์ http://localhost :4000/normal์ ๋ฐฉ๋ฌธํ์ฌ ํ ์คํธํ ์๋ ์์ต๋๋ค.
๋๋ https://team.goodeggs.com/reconnecting-to-mongodb-when-mongoose-connect-fails-at-startup-83ca8496ca02 ๊ธฐ๋ฐ์ ์๋ ์ฌ์ฐ๊ฒฐ ๋ก์ง์ ์ฌ์ฉํ๊ณ ์์ง๋ง, mongo๊ฐ ์ฐ๊ฒฐ์ ๋์ง ์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๊ฒฐ์ฝ ํธ๋ฆฌ๊ฑฐ๋์ง ์์ต๋๋ค.
์ด๋ค ๊ฒฝ์ฐ์๋ ์ผ๋ถ ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๋ ์ฝ๋์ ์ฃผ์์ ๋ฌ ๋ ์ฌํํ ์ ์์ต๋๋ค(๊ธฐ๋ณธ์ ์ผ๋ก ๋น ์ปฌ๋ ์ ์ ์ฟผ๋ฆฌํจ)
๊ฐ๋ฅํ ๊ด๋ จ ๋ฌธ์ :
๋์์ ์ฃผ์๋ฉด ๋๋จํ ๊ฐ์ฌํ๊ฒ ์ต๋๋ค.
๊ทธ๋์ mongoose๋ฅผ ์ฌ์ฉํ์ง ์๊ณ node-mongodb-native์ ํจ๊ป ์๋ํ๋๋ก ์์ ์คํฌ๋ฆฝํธ๋ฅผ ๋ค์ ์์ฑํ์ต๋๋ค. ๊ฒฐ๊ณผ๋ ์ง๊ธ ๋งค์ฐ ๋ค๋ฆ ๋๋ค.
์ฐ๊ฒฐ ์ค์ ๋ฐ ์์ฒญ์ ๋์ผํฉ๋๋ค.
์ํธ:
// Require modules
const MongoClient = require('mongodb').MongoClient;
const Server = require('mongodb').Server;
const express = require('express');
const request = require('request');
const parseJson = require('body-parser').json();
// The db reference
var db;
// Function to insert test data
function insertTestData() {
return new Promise(function (resolve, reject) {
// Get the test collection
var test = db.collection('test');
// Insert some documents
test.insertMany([
{name: 'test1'},
{name: 'test2'},
{name: 'test3'},
{name: 'test4'},
{name: 'test5'}
], function (err, result) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
// Create the Express based app
const app = express();
// Create the express router
const router = express.Router();
// Create a normal route
router.route('/normal').get(parseJson, function (req, res, next) {
// Get the documents collection
var collection = db.collection('test');
// Find some documents
collection.find({}).toArray(function (err, data) {
if (err) {
res.status(400).json(err);
} else {
res.status(200).json(data);
}
});
});
// Create up a slow route
router.route('/slow').get(parseJson, function (req, res, next) {
// Get the documents collection
var collection = db.collection('test');
// Find some documents
collection.find({$where: 'sleep(10000) || true'}).toArray(function (err, data) {
if (err) {
res.status(400).json(err);
} else {
res.status(200).json(data);
}
});
});
// Add middleware to console log every request
var requestNumber = 1;
app.use(function (req, res, next) {
console.log('Request ' + requestNumber, req.method, req.url);
requestNumber++;
next();
});
// Use the router
app.use('/', router);
// Listen for requests
app.listen(4000, function () {
console.log('Server listening on port 4000');
});
// Catch any uncaught exceptions
process.on('uncaughtException', function (err) {
console.log('Uncaught exception', err);
});
// Catch any unhandled rejections
process.on('unhandledRejection', function (reason) {
console.error('Unhandled Rejection', reason);
});
// Database connection options
const connectionOpts = {
// Do not auto reconnect (the Node code will auto reconnect)
autoReconnect: false,
// Use a poolsize of 1 to simulate a timeout using multiple request to slow and normal endpoints
poolSize: 1
};
// Connection method with retry
const connectWithRetry = function () {
return MongoClient.connect('mongodb://localhost:27017/test', connectionOpts).then(
function (database) {
db = database;
setupEvents();
console.log('Connected to mongo');
}
).catch(
function (err) {
console.log('Can not connect to mongo', err);
return err;
}
);
};
// Helper function to execute a request to the normal endpoint
const doRequestNormal = function () {
request({
url: 'http://localhost:4000/normal',
json: true,
timeout: 60000
}, function (error, response, body) {
if (error) {
console.log('Error on normal request', error, response);
}
console.log('Performed normal request, body:', body);
});
};
// Helper function to execute a request to the normal endpoint
const doRequestSlow = function () {
request({
url: 'http://localhost:4000/slow',
json: true,
timeout: 60000
}, function (error, response, body) {
if (error) {
console.log('Error on slow request', error, response);
}
console.log('Performed slow request', body);
});
};
// Helper function to simulate requests
const doRequests = function () {
doRequestNormal();
doRequestSlow();
doRequestNormal();
setTimeout(function () {
console.log('Do normal request after 1 minute');
doRequestNormal();
}, 60000);
};
// Helper function to setup mongo events
function setupEvents() {
// Connecting event
db.on('connecting', function () {
console.log('Connecting to database...');
});
// Connected event
db.on('connected', function () {
console.log('Database is connected, start requesting...');
});
// Timeout event
db.on('timeout', function (err) {
console.log('Database timeout error', err);
});
// Error event
db.on('error', function (err) {
console.log('Database connection error', err);
});
// Disconnected event
db.on('close', function () {
console.error('Database got disconnected, reconnecting in 5 sec...');
// Reconnect in 5 seconds
setTimeout(connectWithRetry, 5000);
});
}
// Connect to the database with retry
connectWithRetry().then(
function () {
return insertTestData();
}
).then(
function () {
doRequests();
}
);
์ฝ์ ์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
Server listening on port 4000
Connected to mongo
Request 1 GET /normal
Request 2 GET /slow
Request 3 GET /normal
Performed normal request, body: [ { _id: '598207c16caf9224cf3b8897', name: 'test1' },
{ _id: '598207c16caf9224cf3b8898', name: 'test2' },
{ _id: '598207c16caf9224cf3b8899', name: 'test3' },
{ _id: '598207c16caf9224cf3b889a', name: 'test4' },
{ _id: '598207c16caf9224cf3b889b', name: 'test5' } ]
Performed slow request [ { _id: '598207c16caf9224cf3b8897', name: 'test1' },
{ _id: '598207c16caf9224cf3b8898', name: 'test2' },
{ _id: '598207c16caf9224cf3b8899', name: 'test3' },
{ _id: '598207c16caf9224cf3b889a', name: 'test4' },
{ _id: '598207c16caf9224cf3b889b', name: 'test5' } ]
Performed normal request, body: [ { _id: '598207c16caf9224cf3b8897', name: 'test1' },
{ _id: '598207c16caf9224cf3b8898', name: 'test2' },
{ _id: '598207c16caf9224cf3b8899', name: 'test3' },
{ _id: '598207c16caf9224cf3b889a', name: 'test4' },
{ _id: '598207c16caf9224cf3b889b', name: 'test5' } ]
Do normal request after 1 minute
Request 4 GET /normal
Performed normal request, body: [ { _id: '598207c16caf9224cf3b8897', name: 'test1' },
{ _id: '598207c16caf9224cf3b8898', name: 'test2' },
{ _id: '598207c16caf9224cf3b8899', name: 'test3' },
{ _id: '598207c16caf9224cf3b889a', name: 'test4' },
{ _id: '598207c16caf9224cf3b889b', name: 'test5' } ]
Mongo ์ค๋ฅ/์๊ฐ ์ด๊ณผ ์ด๋ฒคํธ๋ ์ด์ ์คํฌ๋ฆฝํธ์ ๊ฐ์ด ํธ๋ฆฌ๊ฑฐ๋์ง ์์ง๋ง ์์ฒญ 2 ๋ฐ 3์ ์ฌ๋ฐ๋ฅด๊ฒ ํด๊ฒฐ๋๊ณ ์์ฒญ 4์ ์ฝ๋ฐฑ๋ ํธ๋ฆฌ๊ฑฐ๋ฉ๋๋ค. Mongoose๋ฅผ ์ฌ์ฉํ๋ ์คํฌ๋ฆฝํธ์ ๋์กฐ๋ฉ๋๋ค.
๋๋ ์ด๊ฒ์ด Mongoose ๋ Mongo ๋ฌธ์ ์ธ์ง ์ฌ๋ถ๋ฅผ ๋ฐฐ์ ํ๋ ค๊ณ ๋ ธ๋ ฅํ๊ณ ์์ผ๋ฏ๋ก ์ด๋ฌํ ์คํฌ๋ฆฝํธ์ ๊ฒฐ๊ณผ๋ฅผ ๋น๊ตํ๋ ๋ฐ ๋์์ ์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค. ์ด์ฉ๋ฉด @vkarpov15 ๊ฐ ์ด๊ฒ์ ๋ํด ์ฐจ์ํ ์ ์์ต๋๊น? ๊ฐ์ฌ ํด์!
@adriaanmeuris ์ด์ํฉ๋๋ค. ์ฒซ ๋ฒ์งธ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ์ฌ ์ป์ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
$ node gh-4513.js
Connecting to database...
Server listening on port 4000
Database is connected, start requesting...
Request 1 GET /normal
Request 2 GET /slow
Request 3 GET /normal
Performed normal request, body: [ { _id: '5998e4a79bb81d37ac4b1a26', __v: 0, name: 'test1' },
{ _id: '5998e4a79bb81d37ac4b1a27', __v: 0, name: 'test2' },
{ _id: '5998e4a79bb81d37ac4b1a28', __v: 0, name: 'test3' },
{ _id: '5998e4a79bb81d37ac4b1a29', __v: 0, name: 'test4' },
{ _id: '5998e4a79bb81d37ac4b1a2a', __v: 0, name: 'test5' } ]
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Mongoose connection readystate is 1
Performed slow request [ { _id: '5998e4a79bb81d37ac4b1a26', __v: 0, name: 'test1' },
{ _id: '5998e4a79bb81d37ac4b1a27', __v: 0, name: 'test2' },
{ _id: '5998e4a79bb81d37ac4b1a28', __v: 0, name: 'test3' },
{ _id: '5998e4a79bb81d37ac4b1a29', __v: 0, name: 'test4' },
{ _id: '5998e4a79bb81d37ac4b1a2a', __v: 0, name: 'test5' } ]
Performed normal request, body: [ { _id: '5998e4a79bb81d37ac4b1a26', __v: 0, name: 'test1' },
{ _id: '5998e4a79bb81d37ac4b1a27', __v: 0, name: 'test2' },
{ _id: '5998e4a79bb81d37ac4b1a28', __v: 0, name: 'test3' },
{ _id: '5998e4a79bb81d37ac4b1a29', __v: 0, name: 'test4' },
{ _id: '5998e4a79bb81d37ac4b1a2a', __v: 0, name: 'test5' } ]
Mongoose connection readystate is 1
Do normal request after 1 minute
Request 4 GET /normal
Performed normal request, body: [ { _id: '5998e4a79bb81d37ac4b1a26', __v: 0, name: 'test1' },
{ _id: '5998e4a79bb81d37ac4b1a27', __v: 0, name: 'test2' },
{ _id: '5998e4a79bb81d37ac4b1a28', __v: 0, name: 'test3' },
{ _id: '5998e4a79bb81d37ac4b1a29', __v: 0, name: 'test4' },
{ _id: '5998e4a79bb81d37ac4b1a2a', __v: 0, name: 'test5' } ]
Mongoose connection readystate is 1
Mongoose connection readystate is 1
^C
$
๋ชฝ๊ตฌ์ค๋ ์ฐ๊ฒฐ ์ํ๋ฅผ ์ ์งํฉ๋๋ค. mongodb, node ๋ฐ mongoose์ ๋ฒ์ ์ ๋ช ํํ ํ ์ ์์ต๋๊น?
ํ ์คํธํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค! ์ค์ ๋ก Mongoose๋ ํญ์ ์ฐ๊ฒฐ๋ ์ํ๋ฅผ ์ ์งํ์ง๋ง ์ฝ๋ฐฑ์ด ๋ฐ์ํ์ง ์์ต๋๋ค(Express๋ก ๋ค์ด์ค๋ ์์ฒญ์ ๋ณผ ์ ์์ง๋ง ์๊ฐ ์ด๊ณผ๋จ).
๋๋ ๋ค์๊ณผ ํจ๊ป ํ ์คํธํ์ต๋๋ค.
๋ค์๊ณผ ๊ฐ์ด ์ ๋ฐ์ดํธํ์ต๋๋ค.
๋ด๊ฐ ๊ฒ์ํ ์ฒซ ๋ฒ์งธ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ก์ปฌ์์ ์ฌ์ ํ ๋ฌธ์ ๋ฅผ ์ฌํํ ์ ์์ต๋๋ค. Mongo ์ฐ๊ฒฐ ์๊ฐ์ด ์ด๊ณผ๋ ๊ฒฝ์ฐ์๋ง ๋ฐ์ํ๋ฏ๋ก ๋ค์์ ์๋ฎฌ๋ ์ด์ ํ๋ ์ฟผ๋ฆฌ๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
mongoose.model('Test').find({$where: 'sleep(10000) || true'})
(์ด ์์ ์ด ๋ชจ๋ ์ปดํจํฐ์์ ์๊ฐ ์ด๊ณผ๋ฅผ ์ ๋ฐํ๋์ง ํ์คํ์ง ์์ผ๋ฏ๋ก ์ฌํ์ ์ํด ์ด ์ฟผ๋ฆฌ๋ฅผ ๋ณ๊ฒฝํด์ผ ํ ์๋ ์์ต๋๋ค.)
mongoose 4.10.4๋ก ์
๋ฐ์ดํธํ ํ ๋ ์ด์ ์ด๋ฌํ ๋ฌธ์ ๊ฐ ํ์๋์ง ์์ต๋๋ค.
๋ค๋ฅธ ์ฌ๋๋ค์ด ๋ฌธ์ ๋ฅผ ๊ฒฝํํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง ๋ฌธ์ ๊ฐ ๋ค์ ๋ฐ์ํ๋ ์งํ ์์ด ๋ช ์ฃผ ๋์ ๋ง์ ์๋น์ค๋ฅผ ์คํํ๊ธฐ ๋๋ฌธ์ ์ฝ๊ฐ ์ด์ํด ๋ณด์
๋๋ค. ๐ค
๊ทธ๋ฌ๋ ์ด์ ์ @adriaanmeuris ์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋ฌธ์ ๋ฅผ
๋ ธ๋ 8์ ์คํ ์ค์ ๋๋ค.
์ด ๋ฌธ์ ๋ ์ฌ์ ํ ์ฃผ๊ธฐ์ ์ผ๋ก ๋ฐ์ํฉ๋๋ค.
@adriaanmeuris ์ ์คํฌ๋ฆฝํธ๋ก๋ ๊ทธ๊ฒ์ ์ฌํํ ์ ์์์ง๋ง , ๋ค์์ ์ ๋ฅผ ์ํด ๋งค๋ฒ ๊ทธ๊ฒ์ ์ฌํํ๋ ์์ ๋ ๋ฒ์ ์ ๋๋ค:
@bendytree ์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ์คํฌ๋ฆฝํธ๋ก ์ ๋ ์ฌํํ ์ ์์ต๋๋ค.
7) Database connecting...
49) Database connected...
49) Dropping...
57) Creating...
156) FastQuery-A: starting...
166) FastQuery-A: success: 1
1158) SlowQuery: starting...
2158) FastQuery-B: starting...
362165) SlowQuery: failed: MongoError: connection 0 to localhost:27017 timed out
362167) FastQuery-B: failed: MongoError: connection 0 to localhost:27017 timed out
605159) FastQuery-C: starting...
1210149) Giving Up...
๋ณธ์ง์ ์ผ๋ก ๋ด ์คํฌ๋ฆฝํธ์ ๊ฐ์ง๋ง ์๊ฐ ์ด๊ณผ ๊ธฐ๊ฐ์ด ๋ ๊น๋๋ค. ๋ชจ๋ ์ฌ๋์ด ๋ด ์คํฌ๋ฆฝํธ(10์ด ์ ์ ์ฌ์ฉ)๋ก ์ฌํํ ์ ์๋ ๊ฒ์ ์๋๋ฏ๋ก ์ค์ ์ ๋ฐ๋ผ ์๊ฐ ์ด๊ณผ๋ฅผ ๋ก์ปฌ์์ ์๋ฎฌ๋ ์ด์ ํ๋ ๋ฐ ๋ ๋ง๊ฑฐ๋ ์ ์ ์๊ฐ์ด ์์๋ฉ๋๋ค.
@vkarpov15 ์ด ์ ๋ฐ์ดํธ๋ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํด ๋ณผ ์ ์์ต๋๋ค. ๋๋ mongoose 4.8.11๋ก ํ ์คํธ ๋ฐ ์ฌํํ์ต๋๋ค.
@bendytree ๋ก ์ฌํํ ์ socketTimeoutMS
๋๋ฌด ๋ฎ์ ๊ฒฝ์ฐ์
๋๋ค. NS
362591) SlowQuery: failed: MongoError: connection 0 to localhost:27017 timed out
362591) FastQuery-B: failed: MongoError: connection 0 to localhost:27017 timed out
๋ฉ์์ง๋ mongodb ๋๋ผ์ด๋ฒ์ ์์ผ ์๊ฐ ์ด๊ณผ๋ฅผ ๋ํ๋
๋๋ค. mongodb ๋๋ผ์ด๋ฒ๋ ๊ธฐ๋ณธ์ ์ผ๋ก 30์ด ํ์ ์๊ฐ์ด ์ด๊ณผ๋์ง๋ง OS์๋ ์๊ณ ์์ด์ผ ํ๋ ์์ผ ์๊ฐ ์ด๊ณผ๊ฐ ์์ผ๋ฏ๋ก ์ผ๋ฐ์ ์ผ๋ก 15์ด ์ด์ ๊ฑธ๋ฆฌ๋ ์ฟผ๋ฆฌ๋ ํผํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๊ทธ๋ฌ๋ socketTimeoutMS
์ต์
์ ์ฌ์ฉํ์ฌ mongodb์ ์์ผ ์๊ฐ ์ด๊ณผ๋ฅผ ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
mongoose.connect(DB_URL, {
useMongoClient: true,
autoReconnect: false,
poolSize: 1,
socketTimeoutMS: 0
}).catch((err)=>{ log('Connect failed', err); });
ํด๋น ์ต์ ์ 0์ผ๋ก ์ค์ ํ๋ฉด ์คํฌ๋ฆฝํธ๊ฐ ๋ด ์ปดํจํฐ์์ ๊ฑฐ์ ์ฑ๊ณตํ๊ณ 10๋ถ ์ฟผ๋ฆฌ๋ ์ฌ์ ํ ์ฃฝ์ง๋ง ์ฝ๋ฐฑ์ ๊ณ์๋ฉ๋๋ค.
$ node gh-4513.js
9) Database connecting...
43) Database connected...
43) Dropping...
53) Creating...
177) FastQuery-A: starting...
189) FastQuery-A: success: 1
1174) SlowQuery: starting...
2174) FastQuery-B: starting...
601181) SlowQuery: failed: MongoError: Interrupted by the host
601182) FastQuery-B: success: 1
605173) FastQuery-C: starting...
605174) FastQuery-C: success: 1
๊ทธ๋ฌ๋ ํ์ ์ฟผ๋ฆฌ๋ ์ฑ๊ณตํฉ๋๋ค.
์ด๋ ์ชฝ์ด๋ , ์ด ๊ฒฝ์ฐ ๋ชฝ๊ตฌ์ค๋ ์๊ฐ ์ด๊ณผ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์์ผ์ผ ํ๋ฏ๋ก ํด๋น ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๊ฒ์ ๋๋ค.
๋๋ ๋น์ ์ด connectTimeoutMS(๊ธฐ๋ณธ๊ฐ 30000ms)์ socketTimeoutMS(๊ธฐ๋ณธ๊ฐ 360000ms)๋ฅผ ํผ๋ํ๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
socketTimeoutMS๋ฅผ ๋๋ผ์ด๋ฒ๋ฅผ ํตํด ์คํ๋๋ ๊ฐ์ฅ ๋๋ฆฐ ์์ ๊ธธ์ด์ 2~3๋ฐฐ๋ก ์ค์ ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. socketTimeoutMS๋ฅผ 0์ผ๋ก ์ค์ ํ๋ ๊ฒ์ ์ค์ ๋ก ์ด์ ์ฒด์ ๊ธฐ๋ณธ ์์ผ ์๊ฐ ์ด๊ณผ ๊ฐ์ ์ ์ฉํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค(์์ธํ ์ ๋ณด๋ http://mongodb.github.io/ ์ฐธ์กฐ). node-mongodb-native/2.2/reference/faq/).
๋ฐ๋ผ์ ์ด ์ง๋ฌธ์ด ๋จ์ ์์ต๋๋ค. ์ด ์ ํ(๊ณ ์ ๋๋ ๊ธฐ๋ณธ OS ์๊ฐ ์ด๊ณผ)์ ๋๋ฌํ์ ๋ ์ด๋ฌํ ์ฝ๋ฐฑ์ด ๋ฐ์ํ์ง ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
@vkarpov15 with [email protected] , ์ด์ ์๊ฐ ์ด๊ณผ ์ด๋ฒคํธ๊ฐ ํ์๋ฉ๋๋ค. ๊ฐ์ฌํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ฌ์ ํ ์ด ์ฝ๋ฐฑ ๋ฌธ์ ๊ฐ ํ์๋ฉ๋๋ค( @bendytree ์ ์๋ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๋น ๋ฅธ ํ ์คํธ๋ฅผ ์ํด LONG_QUERY_DURATION_IN_MS๋ฅผ 2000์ผ๋ก, socketTimeoutMS๋ฅผ 1000์ผ๋ก ์ค์ ํ ์ ์์).
๋ ๋ง์ ํ
์คํธ๋ฅผ ์ํํ์ผ๋ฉฐ Mongoose ์์ด๋ ์ด๊ฒ์ด ์ฌํ๋ ์ ์๋ค๋ ๊ฒ์ ์์์ต๋๋ค. http://mongodb.github.io/node-mongodb-native/2.2/reference/faq/ ๋ฅผ ์ฝ์ ๋ ๋ค์์ ๋ฐ๊ฒฌํ์ต๋๋ค. Closing the socket forces a reconnect of the driverโs connection pool and introduces latency to any other operations which are queued up
mongoose.connection.readyState
๋ ํญ์ 1์ด์ง๋ง autoReconnect
๋ฅผ true
์ค์ ํ๋ ค๊ณ ์๋ํ์ผ๋ฉฐ ์คํฌ๋ฆฝํธ๋ฅผ ๋ค์ ์คํํ์ต๋๋ค.
8) Database connecting...
47) Database connected...
48) Dropping...
73) Creating...
123) FastQuery-A: starting...
129) FastQuery-A: success: 1
1122) SlowQuery: starting...
2126) FastQuery-B: starting...
3130) Database timeout...
3133) SlowQuery: failed: MongoError: connection 0 to localhost:27017 timed out
3133) FastQuery-B: failed: MongoError: connection 0 to localhost:27017 timed out
6063) Database timeout...
7122) FastQuery-C: starting...
7125) FastQuery-C: success: 1
8129) Database timeout...
11070) Database timeout...
13073) Database timeout...
๋ฐ๋ผ์ autoReconnect๊ฐ true๋ก ์ค์ ๋ ์ํ์์ ์ฝ๋ฐฑ์ด ์๋ํ๋ ๊ฒ ๊ฐ์ต๋๋ค ๐
์ด ๊ธฐ์ฌ๋ฅผ ๋ ์ฝ์ผ๋ฉด: http://mongodb.github.io/node-mongodb-native/2.0/tutorials/connection_failures/ , ํ์์์ ํ์ ์ฝ๋ฐฑ์ด ๋ฐ์ํ์ง ์๋ ์ด์ ๋ ์์ ์ด ์๋ฒ๊ฐ ๋ค์ ์ฐ๊ฒฐ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋ฒํผ๋ง๋ฉ๋๋ค.
๊ทธ๋์ autoReconnect
๋ฅผ false
autoReconnect
๋ค์ ์ค์ ํ๋ ค๊ณ ์๋ํ์ง๋ง bufferMaxEntries
๋ฅผ 0
ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์ต๋๋ค.
8) Database connecting...
51) Database connected...
51) Dropping...
58) Creating...
112) FastQuery-A: starting...
116) FastQuery-A: success: 1
1115) SlowQuery: starting...
2115) FastQuery-B: starting...
3123) Database timeout...
3123) SlowQuery: failed: MongoError: connection 0 to localhost:27017 timed out
3123) FastQuery-B: failed: MongoError: connection 0 to localhost:27017 timed out
7115) FastQuery-C: starting...
7117) FastQuery-C: failed: MongoError: no connection available for operation and number of stored operation > 0
์ด๋ @bendytree ์คํฌ๋ฆฝํธ์ ์ฒซ ๋ฒ์งธ ๋ฒ์ ์์ ์ฝ๋ฐฑ์ด ํธ๋ฆฌ๊ฑฐ๋์ง ์์ ์ด์ ๋ฅผ ์ค๋ช ํฉ๋๋ค.
@vkarpov15 ์ด์ 2๊ฐ์ง ์ง๋ฌธ์ด ๋จ์ต๋๋ค.
์ฌ๊ธฐ์ ์ ๋ฐ์ดํธ ๋ ์คํฌ๋ฆฝํธ (@bendytree์ ๊ธฐ๋ฐ์ ์คํฌ๋ฆฝํธ, [email protected] ๋ฐ [email protected] ํ ์คํธ๋)์ ๋๋ค :
const LONG_QUERY_DURATION_IN_MS = 2000;
const DB_URL = 'mongodb://localhost:27017/test_mongoose_callbacks';
const mongoose = require('mongoose');
mongoose.Promise = Promise;
var startTime = new Date().getTime();
var log = (msg) => {
var seconds = Math.round(new Date().getTime() - startTime);
console.log(seconds+") "+msg);
};
var Model = mongoose.model('Test', new mongoose.Schema({
name: { type: String, trim: true, default: 'test' }
}), 'test');
mongoose.connection.on('connecting', () => { log('Database connecting...'); });
mongoose.connection.on('timeout', () => { log('Database timeout...'); });
mongoose.connection.on('error', () => { log('Database error...'); });
mongoose.connection.on('disconnected', () => { log('Database disconnected...'); });
const doRequest = function (title, slow) {
var logRequest = (msg) => { log(title+": "+msg); };
logRequest("starting...");
var filter = slow ? {$where: 'sleep('+LONG_QUERY_DURATION_IN_MS+') || true'} : {};
Model.count(filter).exec((err, count) => {
logRequest(err ? "failed: "+err : "success: "+count);
});
};
mongoose.connection.on('connected', () => {
log("Database connected...");
log("Dropping...");
mongoose.connection.db.dropDatabase(function(){
log("Creating...");
Model.create([ {name: 'test1'} ], function(){
setTimeout(() => { doRequest("FastQuery-A", false); }, 0);
setTimeout(() => { doRequest("SlowQuery", true); }, 1000);
setTimeout(() => { doRequest("FastQuery-B", false); }, 2000);
setTimeout(() => { doRequest("FastQuery-C", false); }, LONG_QUERY_DURATION_IN_MS+5000);
setTimeout(() => { log("Giving Up..."); }, LONG_QUERY_DURATION_IN_MS+30000);
});
});
});
mongoose.connect(DB_URL, {
useMongoClient: true,
autoReconnect: true,
//bufferMaxEntries: 0, // Uncomment to disable buffering operations
poolSize: 1,
socketTimeoutMS: 1000
}).catch((err)=>{ log('Connect failed', err); });
setInterval(()=>{
if (mongoose.connection.readyState === 1) return;
log('Mongoose.readystate = ', mongoose.connection.readyState);
}, 1000);
๋ค ๋ง์์. ์ฐ๋ฆฌ๋ ์ด๊ฒ์ ๋ํด ๋ ์ํด์ผ ํฉ๋๋ค. timeout
์ด๋ฒคํธ๊ฐ ํ์ํ์ง๋ง ์ด ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ์๋ ์ถฉ๋ถํ์ง ์์ต๋๋ค.
'disconnected'๊ฐ ๋ฐ์ํ์ง ์๋ ์ด์ ๋ 'timeout'์ด ์ ์ฒด ํ์ด ์๋๋ผ ํ๋์ ์์ผ์ด ์๊ฐ ์ด๊ณผ๋์์์ ์๋ฏธํ๊ธฐ ๋๋ฌธ์ ๋๋ค. Mongoose๋ ํ์์์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋ ํ์ ์์ผ์ด ๋ช ๊ฐ๋ ์์ง ์ด์ ์๋์ง ์์์ผ ํ๋ฉฐ, ์ด๋ฅผ ์ํํ๋ ๋ฐฉ๋ฒ์ ์์๋ด๊ธฐ ์ํด ๋ ๋ง์ ์กฐ์ฌ๊ฐ ํ์ํฉ๋๋ค.
์๊ฐ ์ด๊ณผ ์ด๋ฒคํธ๊ฐ ๊ณ์ ์ฌ๋ฐํ๋ ์ด์ ๋ฅผ ๋ ์กฐ์ฌํ ๊ฒ์ ๋๋ค. ๊ธฐ๋ค๋ ค ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค :+1:
๋๋ ์ด๊ฒ์ mongodb ๋๋ผ์ด๋ฒ์ ๋ช ๊ฐ์ง ๋ฒ๊ทธ๋ก ์ถ์ ํ์ต๋๋ค: https://github.com/mongodb-js/mongodb-core/pull/215 . ๋ชฝ๊ตฌ์ค์ ํจ์น๋ฅผ ์ ์ฉํ๊ธฐ ์ ์ ๋ณํฉ๋๊ณ ๋ฐฐํฌ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํฉ๋๋ค.
๋ด ์์ ์ ํ
์คํธ์์ @vkarpov15 ๋๋ mongoose.connection.readyState
์ ๋ ๋ณํ์ง ์๋ ๊ฒ์ ๊ฒฝํํ๊ณ ์์ต๋๋ค. ์ด๊ฒ์ ๊ฐ์ ๋ฌธ์ ์
๋๊น?
@r3wt ๊ทธ ๋ฌธ์ ๋ 4.11.13์์ ์์ ๋์ด์ผ ํฉ๋๋ค. ์ด๋ค ๋ฒ์ ์ ์ฌ์ฉํ๊ณ ์์ต๋๊น?
@ vkarpov15 ๋ด ๊ฒ์๋ฌผ ๋น์ 4.11.11์ ์ฌ์ฉํ๊ณ ์์์ต๋๋ค. ๊ทธ๋ฌํ ๋ช ๋ฐฑํ ๋์ ํ๋์ด ๊ทธ๋ฌํ ์ฃผ๋ชฉํ ๋งํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ๋ก๋์ ์ ๋ชฐ๋ ๋ค์ด๊ฐ ์ ์๋ค๋ ๊ฒ์ ๋๋ดํฉ๋๋ค. ์๋ง๋ ๋ ๋์ ํ ์คํธ ์ ์ฐจ๊ฐ ํ์ํ ๊ฒ์ ๋๋ค. (๋๋ ๋ฌด๋กํ๊ฒ ํ๋ ค๊ณ ํ์ง ์๋๋ค, ๋๋ ์คํ ์์ค ํ๋ก์ ํธ๋ฅผ ์ ์งํ๋ ๊ฒ์ด ์ผ๋ง๋ ์ด๋ ค์ด์ง ์๊ณ ์๋ค. ๋๋๋ก ๊ทธ๊ฒ์ ์ง์ฆ๋๋ค)
@ vkarpov15 ์ ๋ ๋ชฝ๊ตฌ์ค ํ๋ฌ๊ทธ์ธ์ ๊ฐ๋ฐ ์ค์ ๋๋ค. ์ฐ๊ฒฐ์ด ์ค๋น๋ ๋๊น์ง ํ๋ฌ๊ทธ์ธ์ ์ฐจ๋จํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์ฐ๊ฒฐ์ ๊ธฐ๋ค๋ฆฌ๋ ๊ต์ฐฉ ์ํ๊ฐ ๋ฉ๋๋ค(์ด์ ๋ก ์ธํด). ์ฐ๊ฒฐ์ด ์ค๋น๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋ฐ ์ฌ์ฉํ๋ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
function ready(){
console.log('ready()');
return new Promise((resolve,reject)=>{
var _int = setInterval(()=>{
if(mongoose.connection.readyState == 1 || forceReady){
clearInterval(_int);
console.log('mongoose connected ready().resolve()')
resolve();
}
},200);
})
}
๋๋ ๋ํ mongoose.connnection.on('connected')
๋ฅผ ํตํด ๋ฃ๊ธฐ๋ฅผ ์๋ํ์ง๋ง ์์ ๊ทธ๊ฒ๋ ์๋ํ์ง ์์์ต๋๋ค. ๋น ์ค์น์์๋ ์ ์๋ํ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ค๋ฅธ mongoose ํ๋ฌ๊ทธ์ธ ๋ฐ ์ด๋ฒคํธ๋ฅผ ์์ ํ๋ ํญ๋ชฉ๊ณผ ํจ๊ป ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ๊ณณ์
๋๋ค. connection.readyState๋ ์์ํ 0์ผ๋ก ์ ์ง๋๋ฉฐ ์ฐ๊ฒฐ๋ ์ด๋ฒคํธ๋ ๋ฐ์ํ์ง ์์ต๋๋ค.
์ ์๊ฐ์๋ require('mongoose') !== require('mongoose')
๊ฒ ๊ฐ์ต๋๋ค. ์ด๊ฒ์ด ์๋ฏธ๊ฐ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
์ฆ:
require('mongoose')
require('mongoose')
require('mongoose')
์ฌ์ฉ์ ์คํฌ๋ฆฝํธ์ ํ๋ฌ๊ทธ์ธ์ ์ฐ๊ฒฐ์ ๋ํ ์ ๋ณด๋ฅผ ๋ฐ์ต๋๋ค. ๊ทธ๋ฌ๋ ํ๋ฌ๊ทธ์ธ b๋ ์ ๋ ๊ทธ๋ ์ง ์์ต๋๋ค. ๋ง์ด ๋ฉ๋๊น?
@r3wt ์ฐธ์ผ๋ก ๊ทธ ์ดํ ์ฌ๋ฐ๋ฅธ ์ผ ์ ํ์ต๋๋ค . ๋ถํธ์ ๋ผ์ณ๋๋ ค ์ฃ์กํฉ๋๋ค.
์ฐ๊ฒฐ์ด ์ค๋น๋ ๋๊น์ง ์ฐจ๋จํ๋ ค๋ฉด mongoose.connection.on('connected')
๊ฐ ์๋ํด์ผ ํฉ๋๋ค. ๋ค๋ฅธ ์ด๋ค ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ๊ณ ์์ต๋๊น? ์คํ ํด๋ณด์ญ์์ค npm list | grep "mongoose"
๊ฒ์, ๋น์ ์ ์ฃผ์ฅ์ require('mongoose') !== require('mongoose')
๋์๊ฒ ๋น์ ์ ๋ชฝ๊ตฌ์ค ๊ณณ์ ์ฌ๋ฌ ๋ฒ์ ์ ๊ฐ์ง๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ถํํ๋ mongodb ๋๋ผ์ด๋ฒ๊ฐ ๋ฆด๋ฆฌ์ค๋์ง ์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ค์ ๋ฐ์ด์ผ ํฉ๋๋ค. ์ฃ์กํ๊ณ ๊ธฐ๋ค๋ ค์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค :+1: ๐ด
@vkarpov15 ์ด ์์ ์์ ์ ๋ํด ์ ๋ง ๊ฐ์ฌํ๋ค๋ ๋ง์ ์ ํ๊ณ ์ถ์์ต๋๋ค. ์ฐ๋ฆฌ๋ 0 ๋ฌธ์ ๋ก ์ง๊ธ ๋ช ๋ฌ ๋์ ํ๋ก๋์ ์์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
@bendytree ์ด ๋ฌธ์ ๋ฅผ ์ฌํธ์งํ๋ ๋ฐ ์์ด ๋น์ ์ ์น์ ํ ๋ง๊ณผ ์ธ๋ด์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. mongodb ๋๋ผ์ด๋ฒ ํ์ mongodb 3.6 ๋ฆด๋ฆฌ์ค์ ๋ง์ถฐ 3.0์ ๋ฆด๋ฆฌ์คํ๋ ์์ ์ ๋ชฐ๋ํ์ต๋๋ค. ๊ทธ๋์ ๊ทธ๋ค์ ์์ง ์ด ์์ ์ผ๋ก 2.x ๋ฆด๋ฆฌ์ค๋ฅผ ๋ด๋์ ์ ์์์ต๋๋ค. ๋ค์ ping์ ๋ณด๋ด๊ฒ ์ต๋๋ค. ์ฆ๊ฑฐ์ด ํด์ผ ๋ณด๋ด์ธ์!
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๋ถํํ๋ mongodb ๋๋ผ์ด๋ฒ๊ฐ ๋ฆด๋ฆฌ์ค๋์ง ์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ค์ ๋ฐ์ด์ผ ํฉ๋๋ค. ์ฃ์กํ๊ณ ๊ธฐ๋ค๋ ค์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค :+1: ๐ด