>백엔드 개발 >Golang >요청당 항목을 처리하는 방법 - Go!

요청당 항목을 처리하는 방법 - Go!

Barbara Streisand
Barbara Streisand원래의
2024-11-05 04:45:02725검색

How I processed over Entries per request - With Go!

시작하기 전에 제가 누구인지, 그리고 이 경우 그것이 왜 중요한지에 대해 간략하게 설명하겠습니다. 저는 Notebook Manufacturing Company의 소프트웨어 개발자로 지난 2년 동안 이곳에서 일하고 있습니다. 현재 제가 속한 팀에서 저는 Go 및 Grafana를 사용한 데이터 파이프라인, 자동화, 모니터링 시스템의 생성, 모니터링 및 유지 관리를 담당하는 유일한 개발자입니다.
또 하나 덧붙이자면, 저는 작년에 인턴이었습니다. 그리고 저는 독학을 했습니다.

좋아요, 그런데 그게 왜 중요한가요?

글쎄요, 제가 스스로 알아낼 수 없는 장애물이나 문제에 직면했을 때 저를 안내해 줄 수 있는 선임 개발자나 내부로부터 어떤 형태의 안내도 없었습니다. 그게 제가 글을 쓰는 주된 이유입니다. 즐거운 일이라 생각하고 공유하고 싶습니다. 놀라운 소프트웨어나 혁신 같은 것은 아니지만 처음부터 다시 구축하는 것이 가능하다는 점을 상기시켜 줍니다. 백만 명의 10x 개발자 중 한 명일 필요는 없습니다.

P.S: 저는 neovim을 사용합니다.

백만 줄

이 숫자는 과장된 것처럼 보일 수도 있고, 그랬으면 좋겠지만 그렇지 않습니다. 제조소 환경에서 작업할 때 각 구성 요소에 대해 많은 제조 대기열의 모든 지점을 추적해야 할 때 필요한 항목 수와 생성되는 데이터의 양을 고려하지 않는 경우가 있습니다.
작은 나사든, 최신 세대 CPU든, 타임스탬프를 사용하여 추적해야 합니다!
그렇습니다. 생성된 데이터의 양은 정확하며 이는 시작에 불과합니다. 문제를 멋지게 만드는 다른 멋진 포인트는 다음과 같습니다(내 관점에서는).

  • 이 데이터의 소스는 압축이나 그런 것이 아니어서 날씨가 좋은 날 평균 요청 시간이 2~3분에 가까웠습니다. 소스가 렉이 걸리면 5분 이상 걸릴 수도 있습니다(저보다 오래된 자바 시스템입니다.).
  • 형식에 대해서는 XML 응답 또는 CSV 응답 중에서 선택할 수 있습니다. 물론 저는 CSV 경로를 선택했습니다. 나는 마조히스트가 아닙니다.
  • 그리고 데이터를 가져오는 간격을 최소 1시간으로 선택해야 했습니다(아니요, 이유는 모르겠습니다. 예, 약간의 간격을 시도했습니다).
  • 소스에는 지연 로딩이나 캐시 시스템이 없었기 때문에 두 개의 동일한 요청이 서로 다른 시간에 동일한 응답을 생성했습니다.
  • 마지막으로, SQL Server Reporting Services로 알려진 Microsoft의 제품이며 자체적으로 모호한 주의 사항이 있습니다. 아, 그리고 꼭 사용해야 하는 데이터베이스가 MSSQL인데, 그게 귀찮네요.

전체 맥락은 이렇습니다. 이제 재미있는 부분이 시작됩니다.

첫 번째 반복 - DMP

제가 소프트웨어에 접근하는 방식은 매우 간단합니다. 보기 흉하고 거의 기능하지 않게 만드세요 -> 보기 흉하게 유지하고 기능을 개선하십시오 -> 여전히 추악하지만 최적화가 더 좋습니다 -> 예쁘고 최적화되었으며 작동 중 -> 그리고 관리자는 귀하가 수행한 작업이 너무 훌륭하고 소스가 이를 처리할 수 없어 가동 중단이 발생했다고 말합니다. FML.

어쨌든 DMP는 Dumb Mode Protocol의 약자입니다. 가능한 한 가장 멍청한 방식으로 작동하게 하세요. 즉, 거의 작동하지 않게 만드는 것입니다.

첫 번째 라운드의 목표는 간단하고, 인증하고, 요청하고, 데이터를 구문 분석하고, 데이터베이스로 보내는 것이었습니다. 아주 간단하죠? 그리고 논문에서 제가 사용해야 했던 인증 및 권한 부여 방법은 제가 몰랐던 시도-응답 인증 방법인 ntlmssp라는 사실을 발견하기 전까지였습니다. 사실, 이를 찾으려면 레거시 .NET 4 코드로 들어가야 했습니다. 저는 C#을 해본 적이 없습니다.
나보다 오래된 레거시 코드를 살펴본 후, 어떤 이유로 그것을 작성한 사람이 이를 추상화, 생성자 및 OOP의 5개 계층으로 숨기는 것이 좋은 생각이라고 생각했기 때문에 이해하려고 노력했습니다. 재미없고 겸손해지는 경험입니다. 그리고 나서 나는 그것을 작동하게 만들었습니다. 한 시간 후에 소스에 속도 제한이 있기 때문에 사용자가 차단되었습니다. 하지만 캐시나 지연 로딩은 없습니다.

그런 다음에는 쿼리 매개변수를 전달하고 데이터를 가져오기만 하면 되며 소스와 더 이상 복잡해지지 않습니다. 좋습니다. 쿼리 매개변수에 대한 문서를 찾아보겠습니다.

...

이 시점에서는 모든 것을 고려했을 때 아마 추측이 맞았을 것입니다. 선적 서류 비치? 실리콘밸리에서만 맛볼 수 있는 이국적인 음식인가요?
어쨌든, 열심히 고민한 후에 이 SQL Server Reporting Services의 사이트/인터페이스를 조사하기로 결정했고, 기쁘기도 하고 싫기도 했지만 필터와 그 값을 알 수 있는 방법이 있었습니다.

페이지의 ("모두") 필터, 즉 모든 제조 라인을 선택한다는 것만 알면 모든 상자를 선택하는 추상화에 불과합니다. 자, 필터를 복사하여 쿼리 문자열에 넣고 인코딩하고 행복해지자!

성공했어요! 아니면 그렇게 생각했습니다.

내가 내 사용자를 차단했다고 말했던 것을 기억하시나요? 글쎄요, 그러한 작업을 수행할 수 있는 관리자 권한을 갖고 최고 경영진으로부터 이를 수행하도록 승인받는 것(사실 최고 경영진이 요청한 것임)만으로는 여러 요청을 수행하는 데 충분하지 않은 것 같습니다. 제 유저가 차단됐는데 매니저한테는 "아무 일도 없었어요"라고 하는 것과 같았어요. 다행히도 꽤 빨리 차단을 해제할 수 있었습니다.

그동안 저는 이 프로젝트의 나머지 부분에 접근하는 방식으로 작업하기로 결정했습니다. 이 시점에서 나는 이미 그 샘플을 가지고 있었고, 그것은 게시물의 제목에 걸맞은 수준이었습니다. 이 7자리 숫자를 보니 이 정도 데이터량에 대한 경험이 전혀 없었기 때문에 과연 내가 할 수 있을까 하는 의문이 들었습니다.

내 아이디어를 구체화하기 위해 엑스칼리드로우에 희망을 걸고 내가 하고 싶은 것을 디자인했습니다. 작업자 풀의 개념을 알고 있었지만 이전에는 구현해 본 적이 없었습니다. 그래서 나는 그것에 대해 읽고, 몇 가지 구현을 보았고, 나에게 많은 도움을 준 친구에게 물었습니다. 나한테 없던 선배인데.

의사 코드로 작성하고 나서 생각했습니다.

"와, 이거 정말 깔끔하네요. 모든 채널과 고루틴에서 메모리 누수가 발생하지 않을 것 같죠?"

그렇습니다. 정확한 단어는 아닐 수도 있지만 그런 맥락이었습니다. 첫 번째 반복을 수행하고 (차단되지 않고) 요청을 처리하고 메모리에 로드한 후 작업자 풀 개념을 적용했습니다.

그리고 BSOD를 마주하게 되었습니다. 웃기게도 그날은 CrowdStrike 파업이 있었던 날이었는데, 제가 제조업에 큰 정전을 초래했다고는 생각하지 못했습니다.
그리고 네, 일하려면 창문을 사용해야 하지만 걱정하지 마세요! 저는 WSL2를 사용합니다.

첫 번째 스택 오버플로의 엄청난 스택 트랙을 살펴본 후 실수를 발견했습니다. 소비자 채널에 데이터를 보낼 때 주로 기본 키 위반이나 단순히 오류를 제대로 처리하지 않았기 때문에 일부 데이터에 오류가 발생할 수 있다는 점을 고려하지 않았습니다.

배운 교훈은 오류 채널을 사용하여 심각한 문제를 피하는 것입니다. 간단한 문자열 확인(추악하지만 작동함)을 통해 오류를 처리하거나 단순히 최상위 수준에서 기록하고 만족하세요. 제가 겪은 오류는 심각하지 않았기 때문에 계속 진행할 수 있었습니다.

두 번째 반복. 메모리 누수.

이 단계에서 발생한 메모리 누수로 인해 C를 하고 있는 줄 알았어요. 하지만 이는 단지 중요한 기술 문제였을 뿐입니다.
어쨌든 다음과 같이 생각할 수도 있습니다.

"어떻게 이렇게 간단한 과정에서 메모리 누수를 발생시켰나요?"

간단해요. 배우고 노력하고 있었어요.

이 단계의 가장 큰 문제는 순진하게도 데이터가 제대로 삽입되었는지 확인하지 못했고, 기본 키를 위반하는 양이 내 메모리를 침해한다는 점이었습니다. 이건 내가 해결할 수 있는 문제였으니 데이터를 캐시하자!
각 행이 고유하다는 점을 고려하여 각 행에 대한 고유 식별자를 어떻게 생성합니까?

이제 많은 사람들이 저를 비웃을 부분이 바로 그 부분입니다. 공정하게 말하면 바로 그 부분이 저를 가장 아프게 하기 때문입니다. 단순히 현재 정보 행에 합류하여 해시 함수로 구문 분석했고, 해당 해시가 지도의 키가 되었습니다.

"Redis를 사용하면 안 되는 이유는 무엇입니까?" - 스스로 자문해 볼 수도 있습니다.

간단한 관료주의입니다. 작은 회사는 아닙니다. 사실, 여러분 중 상당수는 아마도 자신이 제조한 노트북을 사용하고 있을 것입니다. Redis 인스턴스를 요청하는 간단한 작업에는 최소한 영업일 기준 3일, 4번의 회의, 관료주의 신을 위한 희생, 이유와 방법을 설명하는 완전한 문서가 소요됩니다.
네, 간단한 해시 맵을 사용하여 첫 번째 실행 전에 사전 초기화해 보겠습니다. 전체 로딩 시간이 늘어나지만 요청한 것보다 빠릅니다.

그렇게 하면 새 모터가 있는 것처럼 전반적인 프로세스가 개선되고, 멤리크가 중지되고, 배치가 매번 실패하지 않고, 오류와 연결 끊김의 양도 줄어들었습니다. 꽤 괜찮죠? 그렇죠?

지금쯤이면 뭔가가 뒤죽박죽된 것 같군요.

세 번째 반복. 인생은 좋을 수 있습니다.

제가 고려하지 않은 한 가지 점은 일괄 삽입을 통해 데이터가 검증된다는 사실이었습니다. 다음은 흐름을 간단하게 표현한 것입니다.

데이터 가져오기 -> 해시맵에 데이터의 해시가 존재하는지 확인하세요. -> 일괄 및 삽입

그리고 그게 무슨 문제인가요? 배치의 단일 삽입이 실패하면 어떻게 되나요? 항목 없이 다시 시도할까요? 그렇다면 시스템을 복잡하게 만들고 작업자 풀 구현의 이점을 잃지 않고 얼마나 많은 재시도를 할 수 있습니까?
알아낼 수 있는 방법은 단 하나! 확인해 보겠습니다.
한 가지 추가할 수 있는 점은 이 소스가 25개가 넘는 열을 반환했기 때문에 MSSQL 제한인 2100개 매개 변수를 초과하지 않도록 배치당 삽입하는 데이터 양에 주의해야 했습니다.

이 시점에서 저는 이미 제한된 리소스로 생산 공간을 모방한 도커 컨테이너에서 작업을 실행하고 있었습니다. 컨텍스트를 추가하기 위해 이 프로세스는 1GB RAM과 약 0.5CPU로 실행되었습니다. 더 많은 자원을 할당할 수도 있었지만, 그것은 단순히 무차별적인 강제로 빠져나가는 일이 될 것입니다.
컨테이너 내에서 이 새로운 반복을 실행하고 일부 타임스탬프를 추가하고 나중에 분석하기 위해 파일에 로그아웃합니다. 재시도 횟수로 인해 약 5분 정도 증가한 것을 발견했습니다. 이 방법은 작동하지 않습니다. '더러운' 항목을 제거하는 것은 선택 사항이 아니었습니다.

네 번째 반복. 인생은 좋다.

이 문제를 해결하기 위해 직원 수를 늘렸습니다. 50명 정도의 워커를 사용하고 있었는데, ThePrimagen 최상위권에 있는 디스코드 사용자의 무작위 추측 덕분에 1000명으로 늘리고, 각 워커가 트랜잭션의 각 항목을 검증하도록 만들었습니다. 거래가 실패할 경우 간단히 롤백했습니다.
이를 통해 핵심 문제를 해결하고 전반적인 프로세스 속도를 향상시킬 수 있었습니다. 이제는 prod에 넣고 모니터링할 시간입니다. 왜냐하면 prod goblins가 소프트웨어를 뒤죽박죽으로 만들 수 있기 때문입니다. (스킬 문제라고도 하는데 이 이름은 금지입니다.)

실시간에 가깝게 만들도록 요청된 이 시스템의 가져오기 간격을 줄이는 것을 알고(즉, 지연을 인지하지 못할 만큼 빠르다는 의미) 이번에는 조금 더 강력한 새 컨테이너를 만들었습니다. 부하를 견딜 수 있는지 확인하고 간격을 3분으로 설정합니다. 가져오는 평균 시간을 생각하면 겹치는 부분이 있을 수 있겠지만 어떻게 될지 꼭 보고 싶었습니다.

나중에 확인하기 위해 밤새 실행하고 결과를 기록했는데, 놀랍게도 근무일이 끝나기 전에 매니저로부터 전화를 받았습니다. 주의하세요. 그는 기술 전문가나 그런 사람이 아닙니다.

"야, '우리'가 [공개할 수 없는 시스템 이름]과 상호 작용하는 것을 배포했나요?"

"예, 요청하신 데이터 가져오기 시스템을 실시간으로 배포했습니다. 왜죠?"

"그만 좀 해주실 수 있나요? 정전이 발생해서 여기서는 일을 할 수 없어요."_

이것은 완전히 다른 수준의 획기적인 제품입니다. 말 그대로 20개가 넘는 생산 라인을 1분 정도 멈췄습니다. 어쨌든 시스템을 종료하고 모든 것이 정상으로 돌아왔습니다.
다음 날, 가져오기 간격을 3분이 아닌 30분으로 늘려달라는 요청을 받았습니다. 괜찮을 것 같습니다. 거짓말은 안 하고 최대 속도로 작동하는 모습을 볼 수 없어서 조금 아쉬웠지만 적어도 작동하게 만들었습니다.

이 새로운 시스템을 통해 이 데이터를 사용한 보고서의 평균 업데이트 시간이 8~10초로 단축되었으며, 이로 인해 동일한 소스의 보고서가 동일한 방식으로 관리자에게 요청되는 경우가 훨씬 더 많아졌습니다. 좋은 일은 더 많은 노력으로 보상받습니다!

고려사항

Go가 실제로 얼마나 강력한지 깨닫게 해주었기 때문에 재미있는 경험이었습니다. Google 크롬보다 적은 메모리, Microsoft 앱보다 적은 저장 공간, Windows 계산기보다 적은 CPU 성능을 사용하여 문자 그대로 무차별 대입 방식으로 진행되는 기존 프로세스를 개선할 수 있었습니다(삽입하기 전에 문자 그대로 데이터베이스의 각 줄을 확인했습니다. 저는 그렇지 않습니다. 이전 사람이 그것이 좋은 생각이라고 어떻게 생각했는지 모르겠습니다.). 정말 재미있었어요.

어쨌든 이 모든 과정에 대한 생각, 어떻게 접근하고 무엇을 다르게 했을지 자유롭게 공유해 주세요. 개발 동료가 없어서 더 많은 의견을 듣고 싶습니다.

위 내용은 요청당 항목을 처리하는 방법 - Go!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.