MongoDB 접속의 .NET 베스트 프랙티스
최근 GitHub의 C#드라이버를 사용하여 MongoDB를 가지고 놀고 있습니다(놀랍게도 빠릅니다).테스트하고 있는 작은 싱글 스레드 콘솔 앱에서는 모든 것이 정상적으로 동작하고 있습니다.싱글 스레드 실행으로 1,000,000개의 문서(네, 백만 개)를 8초 이내에 추가할 수 있습니다.이 퍼포먼스는 for 루프의 범위 밖에서 접속을 사용하는 경우에만 얻을 수 있습니다.즉, 각 인서트마다 접속하는 것이 아니라 각 인서트마다 접속을 열어 둡니다.확실히 그건 조작된 거야.
여러 개의 스레드에서 어떻게 작동하는지 보기 위해 한 단계 더 높여야겠다고 생각했습니다.여러 개의 동시 요청을 가진 웹 사이트를 시뮬레이션해야 하기 때문에 이 작업을 수행합니다.15~50 스레드 속도로 회전하고 있으며, 모든 케이스에 총 15만 개의 문서를 삽입하고 있습니다.스레드를 실행하기만 하면 각 삽입 작업에 대해 새로운 연결이 생성되므로 성능이 중단됩니다.
당연히 연결을 공유, 잠금 또는 풀링할 방법을 찾아야 합니다.문제는 여기에 있다.MongoDB 접속에 관한 베스트 프랙티스는 무엇입니까?앱 수명 동안 연결을 열어 두어야 합니까(각 작업에 대해 TCP 연결을 열고 닫는 데 상당한 지연 시간이 있음)?
MongoDB, 특히 기반이 되는 접속에 대해 실제 환경이나 생산 경험이 있는 사람이 있습니까?
삽입 작업을 위해 잠긴 정적 연결을 사용한 스레드 샘플입니다.웹 컨텍스트에서 성능과 신뢰성을 극대화할 수 있는 방법을 제안해 주십시오!
private static Mongo _mongo;
private static void RunMongoThreaded()
{
_mongo = new Mongo();
_mongo.Connect();
var threadFinishEvents = new List<EventWaitHandle>();
for(var i = 0; i < 50; i++)
{
var threadFinish = new EventWaitHandle(false, EventResetMode.ManualReset);
threadFinishEvents.Add(threadFinish);
var thread = new Thread(delegate()
{
RunMongoThread();
threadFinish.Set();
});
thread.Start();
}
WaitHandle.WaitAll(threadFinishEvents.ToArray());
_mongo.Disconnect();
}
private static void RunMongoThread()
{
for (var i = 0; i < 3000; i++)
{
var db = _mongo.getDB("Sample");
var collection = db.GetCollection("Users");
var user = GetUser(i);
var document = new Document();
document["FirstName"] = user.FirstName;
document["LastName"] = user.LastName;
lock (_mongo) // Lock the connection - not ideal for threading, but safe and seemingly fast
{
collection.Insert(document);
}
}
}
대부분의 답변은 오래된 것으로 .net 드라이버가 성숙하여 수많은 기능이 추가되었기 때문에 더 이상 적용되지 않습니다.
새로운 2.0 드라이버의 메뉴얼은, http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/connecting/ 를 참조해 주세요.
이제 .net 드라이버가 스레드 세이프가 되어 연결 풀링을 처리합니다.문서에 따라
MongoClient 인스턴스는 글로벌한 장소(스태틱 변수 또는 싱글톤의 라이프 타임을 가진 IoC 컨테이너)에 저장하는 것이 좋습니다.
정적 연결에 대해 기억해야 할 점은 연결이 모든 스레드 간에 공유된다는 것입니다.원하는 것은 스레드당 1개의 연결입니다.
mongodb-csharp 를 사용하는 경우는, ADO 접속과 같이 취급합니다.Mongo 오브젝트를 작성하면 풀에서 접속을 빌리고 풀은 폐기될 때까지 소유합니다.따라서 using block이 끝나면 연결은 풀로 돌아갑니다.몽고 오브젝트를 만드는 것은 싸고 빠르다.
예
for(var i=0;i<100;i++)
{
using(var mongo1 = new Mongo())
using(var mongo2 = new Mongo())
{
mongo1.Connect();
mongo2.Connect();
}
}
데이터베이스 로그
:54:21.0.1:58214 #16부터 되었습니다.27.0.0.1:58214 #1 입니다.
) 20:54accepted from 12701:58215 #26' 2' (') 20:54:21' '127.0.1:58215 #2' 입니다.
수) :21 errno error 127.1:" 2" "20::21 MessagingPort recv() errno:0" "127.0.1:58214"
수) :21 접속0.0.1: 2일2 일일20:54:21 접127.0.1:58214
수) 20 errno error 127.1:' 2' 20:54:21 MessagingPort recv() errno:0' 127.0.1:58215'
수) :21 접속0.0.1: 2일2 일:20:54:21 접127.0.1:58215
2개의 연결만 열었습니다.
나는 이것을 mongodb-csharp 포럼을 사용하여 정리했다.http://groups.google.com/group/mongodb-csharp/browse_thread/thread/867fa78d726b1d4
다소 흥미로운 점은 jLinq 개발자가 만든 MongoDB용 C# 드라이버 CSMongo입니다.다음은 샘플입니다.
//create a database instance
using (MongoDatabase database = new MongoDatabase(connectionString)) {
//create a new document to add
MongoDocument document = new MongoDocument(new {
name = "Hugo",
age = 30,
admin = false
});
//create entire objects with anonymous types
document += new {
admin = true,
website = "http://www.hugoware.net",
settings = new {
color = "orange",
highlight = "yellow",
background = "abstract.jpg"
}
};
//remove fields entirely
document -= "languages";
document -= new[] { "website", "settings.highlight" };
//or even attach other documents
MongoDocument stuff = new MongoDocument(new {
computers = new [] {
"Dell XPS",
"Sony VAIO",
"Macbook Pro"
}
});
document += stuff;
//insert the document immediately
database.Insert("users", document);
}
Connection Pool이 정답입니다.
이 기능은 개발 중입니다(자세한 내용은 http://jira.mongodb.org/browse/CSHARP-9 참조).
현시점에서는 웹 어플리케이션에서는 BeginRequest에서 접속하고 EndRequest에서 접속을 해제하는 것이 가장 좋습니다.그러나 Connection Pool이 없는 요청마다 비용이 너무 많이 든다고 생각합니다.그래서 글로벌한 Mongo 오브젝트를 사용하여 모든 스레드의 공유 리소스로 사용하기로 결정했습니다(지금 바로 github에서 최신 C# 드라이버를 가져오면 동시 처리 성능도 약간 향상됩니다).
Global Mongo 오브젝트를 사용할 때의 단점은 잘 모르겠습니다.그럼 다른 전문가의 코멘트를 기다려 봅시다.
하지만 기능(Connection Pool)이 완성될 때까지 버틸 수 있을 것 같습니다.
저는 csharp-mongodb 드라이버를 사용하고 있습니다만, 그의 접속 풀에서는 도움이 되지 않습니다.(웹 요청마다 약 10~20개의 mongodb에 대한 요구가 있습니다).(150명의 온라인 사용자 - 평균) 셸에서 통계를 감시하거나 mongodb에 접속할 수도 없습니다.
요청별로 연결을 열고 삭제하는 저장소를 만들었습니다.저는 다음과 같은 것에 의존하고 있습니다: 1) 드라이버에 커넥션 풀이 있습니다 2) 조사한 결과(이것에 대해 사용자 그룹에 몇 가지 질문을 올렸습니다) - mongo 오브젝트나 오픈 접속을 작성하는 것은 과중한 조작이 아니기 때문에 무거운 조작을 할 수 있다는 것을 알았습니다.
하지만 오늘 생산이 중단되었습니다: (요청마다 열려 있는 연결을 저장해야 할 수도 있습니다...
다음은 사용자 그룹 http://groups.google.com/group/mongodb-user/browse_thread/thread/3d4a4e6c5eb48be3#에 대한 링크입니다.
언급URL : https://stackoverflow.com/questions/2194047/net-best-practices-for-mongodb-connections
'programing' 카테고리의 다른 글
| ngRoute 모든 루트의 set base URL (0) | 2023.02.12 |
|---|---|
| Json.net을 사용하여 복합 키를 사용하여 사전을 직렬화할 수 없습니다. (0) | 2023.02.12 |
| DynamoDB vs MongoDB NoSQL (0) | 2023.02.12 |
| Type & Type Token이란? (0) | 2023.02.08 |
| cURL이 HTTP Response Body(JSON; 응답 본문)만 출력하고 다른 헤더는 출력하지 않도록 하는 방법 (0) | 2023.02.08 |