paint-brush
टर्बोचार्ज लोड परीक्षण: लाइटनिंग-फास्ट कोड जांच के लिए YandexTank + ghz कॉम्बो!द्वारा@mrdrseq
493 रीडिंग
493 रीडिंग

टर्बोचार्ज लोड परीक्षण: लाइटनिंग-फास्ट कोड जांच के लिए YandexTank + ghz कॉम्बो!

द्वारा Ilia Ivankin14m2023/11/23
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

संक्षेप में, जब आपको प्रति सेकंड 100+ अनुरोधों के भार को संभालने या संभावित कमजोरियों की पहचान करने के लिए अपनी सेवा की क्षमता का त्वरित मूल्यांकन करने की आवश्यकता होती है, तो टीमों को शामिल करने, AQA से सहायता लेने, या बुनियादी ढांचे की टीम पर भरोसा करने की जटिल प्रक्रियाएं शुरू करने की कोई आवश्यकता नहीं है। अक्सर, डेवलपर्स के पास सक्षम लैपटॉप और कंप्यूटर होते हैं जो एक छोटे लोड परीक्षण को निष्पादित कर सकते हैं। तो, आगे बढ़ें और इसे आज़माएं—अपना कुछ समय बचाएं!
featured image - टर्बोचार्ज लोड परीक्षण: लाइटनिंग-फास्ट कोड जांच के लिए YandexTank + ghz कॉम्बो!
Ilia Ivankin HackerNoon profile picture

नमस्ते!


कभी-कभी, त्वरित लोड परीक्षण की आवश्यकता उत्पन्न होती है, चाहे वह स्थानीय वातावरण में हो या परीक्षण प्लेटफ़ॉर्म पर। आमतौर पर, ऐसे कार्यों को विशेष उपकरणों का उपयोग करके निपटाया जाता है जो पूरी तरह से पूर्व समझ की मांग करते हैं। हालाँकि, उद्यमों और स्टार्टअप्स के भीतर जहां तेजी से समय-समय पर बाजार और त्वरित परिकल्पना सत्यापन सर्वोपरि है, अत्यधिक उपकरण परिचित होना एक विलासिता बन जाता है।


इस लेख का उद्देश्य डेवलपर-केंद्रित समाधानों पर प्रकाश डालना है जो गहन जुड़ाव की आवश्यकता को समाप्त करते हैं, दस्तावेज़ीकरण के पन्नों में उलझे बिना प्राथमिक परीक्षण की अनुमति देते हैं।


स्थानीय चल रहा है

आपको इंस्टॉल करना चाहिए::

  1. डॉकर - इसके लिए सभी सेवाएँ और उपकरण आवश्यक हैं।


  2. जावा 19+ - कोटलिन सेवा के लिए। इसके अलावा, आप जावा 8 संस्करण का उपयोग करने का प्रयास कर सकते हैं; इसे काम करना चाहिए, लेकिन आपको ग्रैडल सेटिंग्स बदलनी होंगी।


  3. गोलांग - सेवाओं में से एक गोलांग सेवा है =)


  4. पायथन 3+ - यांडेक्स टैंक के लिए।

तकनीकी आवश्यकताएँ

हमारी यात्रा शुरू करने से पहले, कुछ ऐसी सेवाएँ तैयार करने की सलाह दी जाती है जो परीक्षण उद्देश्यों के लिए उदाहरण के रूप में काम कर सकें।


स्टैक: कोटलिन + वेबफ्लक्स। r2dbc + पोस्टग्रेज़।


हमारी सेवा में है:

- सभी स्टॉक प्राप्त करें (सीमा 10) प्राप्त करें /api/v1/स्टॉक्स
- GET__ /api/v1/stock नाम से स्टॉक प्राप्त करें ?नाम=आप्पल
- स्टॉक सहेजें पोस्ट /
एपीआई/वी1/स्टॉक


यह एक आसान सेवा होनी चाहिए क्योंकि हमें लोड परीक्षण पर ध्यान केंद्रित करना होगा =)

कोटलिन और HTTP सेवा

आइए कुछ बुनियादी तर्क के साथ एक छोटी सी सेवा बनाकर शुरुआत करें। हम इस उद्देश्य के लिए एक मॉडल तैयार करेंगे:


 @Table("stocks") data class Stock( @field:Id val id: Long?, val name: String, val price: BigDecimal, val description: String )


सरल राउटर:

 @Configuration @EnableConfigurationProperties(ServerProperties::class) class StockRouter( private val properties: ServerProperties, private val stockHandler: StockHandler ) { @Bean fun router() = coRouter { with(properties) { main.nest { contentType(APPLICATION_JSON).nest { POST(save, stockHandler::save) } GET(find, stockHandler::find) GET(findAll, stockHandler::findAll) } } } }


और हैंडलर:

 @Service class StockHandlerImpl( private val stockService: StockService ) : StockHandler { private val logger = KotlinLogging.logger {} private companion object { const val DEFAULT_SIZE = 10 const val NAME_PARAM = "name" } override suspend fun findAll(req: ServerRequest): ServerResponse { logger.debug { "Processing find all request: $req" } val stocks = stockService.getAll(DEFAULT_SIZE) return ServerResponse.ok() .contentType(MediaType.APPLICATION_JSON) .body(stocks, StockDto::class.java) .awaitSingle() } override suspend fun find(req: ServerRequest): ServerResponse { logger.debug { "Processing find all request: $req" } val name = req.queryParam(NAME_PARAM) return if (name.isEmpty) { ServerResponse.badRequest().buildAndAwait() } else { val stocks = stockService.find(name.get()) ServerResponse.ok() .contentType(MediaType.APPLICATION_JSON) .body(stocks, StockDto::class.java) .awaitSingle() } } override suspend fun save(req: ServerRequest): ServerResponse { logger.debug { "Processing save request: $req" } val stockDto = req.awaitBodyOrNull(StockDto::class) return stockDto?.let { dto -> stockService.save(dto) ServerResponse .ok() .contentType(MediaType.APPLICATION_JSON) .bodyValue(dto) .awaitSingle() } ?: ServerResponse.badRequest().buildAndAwait() } }


पूरा कोड यहाँ: GitHub


एक डॉकर फ़ाइल बनाएँ:

 FROM openjdk:20-jdk-slim VOLUME /tmp COPY build/libs/*.jar app.jar ENTRYPOINT ["java", "-Dspring.profiles.active=stg", "-jar", "/app.jar"]


फिर, एक डॉकर छवि बनाएं और इसे ट्यून करें 🤤

 docker build -t ere/stock-service . docker run -p 8085:8085 ere/stock-service


लेकिन अभी के लिए, डॉकर कंटेनरों के माध्यम से सब कुछ चलाने के विचार पर कायम रहना और हमारी सेवा को डॉकर कंपोज़ सेटअप में स्थानांतरित करना बेहतर है।

 version: '3.1' services: db: image: postgres container_name: postgres-stocks ports: - "5432:5432" environment: POSTGRES_PASSWORD: postgres adminer: image: adminer ports: - "8080:8080" stock-service: image: ere/stock-service container_name: stock-service ports: - "8085:8085" depends_on: - db 



ठीक है ठीक है, परीक्षण कहाँ हैं?

आगे बढ़ते हुए: हम परीक्षण कैसे आगे बढ़ा सकते हैं? विशेष रूप से, हम अपनी हाल ही में विकसित सेवा के लिए मामूली लोड परीक्षण कैसे शुरू कर सकते हैं? यह जरूरी है कि परीक्षण समाधान स्थापित करने में आसान और उपयोगकर्ता के अनुकूल हो।


हमारी समय की कमी को देखते हुए, व्यापक दस्तावेज़ीकरण और लेखों में तल्लीन होना एक व्यवहार्य विकल्प नहीं है। सौभाग्य से, एक व्यवहार्य विकल्प है - यांडेक्स टैंक दर्ज करें। टैंक परीक्षण के लिए एक शक्तिशाली उपकरण है और इसमें महत्वपूर्ण एकीकरण हैं जेमीटर , लेकिन लेख में हम इसे एक सरल उपकरण के रूप में उपयोग करेंगे।


दस्तावेज़: https://yandextank.readthedocs.org/en/latest/


आइए अपने परीक्षणों के लिए एक फ़ोल्डर बनाकर शुरुआत करें। एक बार जब हम कॉन्फ़िगरेशन और अन्य आवश्यक फ़ाइलें - सौभाग्य से, उनमें से केवल कुछ - रख देंगे, तो हम पूरी तरह तैयार हो जाएंगे।

हमारी सेवा के लिए, हमें "सभी प्राप्त करें" और "बचाएँ" विधियों का परीक्षण करने की आवश्यकता है। खोज विधि के लिए पहला कॉन्फ़िगरेशन.

 phantom: address: localhost port: "8085" load_profile: load_type: rps schedule: line(100, 250, 30s) writelog: all ssl: false connection_test: true uris: - /api/v1/stocks overload: enabled: false telegraf: enabled: false autostop: autostop: - time(1s,10s) # if request average > 1s - http(5xx,100%,1s) # if 500 errors > 1s - http(4xx,25%,10s) # if 400 > 25% - net(xx,25,10) # if amount of non-zero net-codes in every second of last 10s period is more than 25


कॉन्फ़िगरेशन के लिए मुख्य सेटिंग्स:

  • पता और पोर्ट: हमारे एप्लिकेशन के समान।


  • लोड परीक्षण प्रोफ़ाइल (load_profile): हम 'पंक्तिबद्ध' प्रकार का उपयोग करेंगे, प्रति सेकंड 100 अनुरोधों से लेकर 30-सेकंड की सीमा के साथ 250 तक।


  • यूआरआई: परीक्षण किए जाने वाले यूआरएल की एक सूची।


  • ऑटोस्टॉप पैटर्न: यदि हमारी सेवा पहले ही बंद हो गई है तो तनाव-परीक्षण की कोई आवश्यकता नहीं है! =)


बैश स्क्रिप्ट (टैंक श) को कॉपी और पेस्ट करें:

 docker run \ -v $(pwd):/var/loadtest \ --net="host" \ -it yandex/yandex-tank


और भाग खड़ा हुआ!


परिणामस्वरूप हम क्या देखेंगे? यांडेक्स टैंक परीक्षण के दौरान वह सब कुछ लॉग करेगा जो वह उचित समझेगा। हम 99वें प्रतिशतक और प्रति सेकंड अनुरोध (आरपीएस) जैसे मेट्रिक्स का निरीक्षण कर सकते हैं।


टर्मिनल? वास्तव में?


तो, क्या अब हम टर्मिनल में फंस गए हैं? मुझे एक जीयूआई चाहिए! चिंता न करें, यांडेक्स टैंक के पास इसका भी समाधान है। हम ओवरलोड प्लगइन्स में से एक का उपयोग कर सकते हैं। इसे कैसे जोड़ें इसका एक उदाहरण यहां दिया गया है:

 overload: enabled: true package: yandextank.plugins.DataUploader job_name: "save docs" token_file: "env/token.txt"


हमें अपना टोकन जोड़ना चाहिए; बस यहां जाएं और GitHub द्वारा तर्क दें: https://overload.yandex.net

कोड


ठीक है, GET अनुरोध से निपटना सीधा है, लेकिन POST के बारे में क्या? हम अनुरोध की संरचना कैसे करते हैं? बात यह है कि, आप अनुरोध को यूं ही टैंक में नहीं फेंक सकते; आपको इसके लिए पैटर्न बनाने की आवश्यकता है! ये पैटर्न क्या हैं? यह सरल है - आपको एक छोटी सी स्क्रिप्ट लिखनी होगी, जिसे आप फिर से दस्तावेज़ से प्राप्त कर सकते हैं और हमारी आवश्यकताओं के अनुरूप थोड़ा बदलाव कर सकते हैं।


और हमें अपना स्वयं का मुख्य भाग और शीर्षलेख जोड़ना चाहिए:

 #!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys import json # http request with entity body template req_template_w_entity_body = ( "%s %s HTTP/1.1\r\n" "%s\r\n" "Content-Length: %d\r\n" "\r\n" "%s\r\n" ) # phantom ammo template ammo_template = ( "%d %s\n" "%s" ) method = "POST" case = "" headers = "Host: test.com\r\n" + \ "User-Agent: tank\r\n" + \ "Accept: */*\r\n" + \ "Connection: Close\r\n" def make_ammo(method, url, headers, case, body): """ makes phantom ammo """ req = req_template_w_entity_body % (method, url, headers, len(body), body) return ammo_template % (len(req), case, req) def generate_json(): body = { "name": "content", "price": 1, "description": "description" } url = "/api/v1/stock" h = headers + "Content-type: application/json" s1 = json.dumps(body) ammo = make_ammo(method, url, h, case, s1) sys.stdout.write(ammo) f2 = open("ammo/ammo-json.txt", "w") f2.write(ammo) if __name__ == "__main__": generate_json()


परिणाम:

 212 POST /api/v1/stock HTTP/1.1 Host: test.com User-Agent: tank Accept: */* Connection: Close Content-type: application/json Content-Length: 61 {"name": "content", "price": 1, "description": "description"}


इतना ही! बस स्क्रिप्ट चलाएँ, और हमारे पास ammo-json.txt होगा। कॉन्फिगर करने के लिए बस नए पैरामीटर सेट करें, और यूआरएल हटाएं:

 phantom: address: localhost:9001 ammo_type: phantom ammofile: ammo-json.txt


और इसे एक बार और चलाएँ!

जीआरपीसी का परीक्षण करने का समय आ गया है!

अभी तक नहीं?


HTTP विधियों को लोड करने से परिचित होने के बाद, GRPC के परिदृश्य पर विचार करना स्वाभाविक है। क्या हम इतने भाग्यशाली हैं कि हमारे पास जीआरपीसी के लिए एक टैंक की सादगी जैसा समान रूप से सुलभ उपकरण है? उत्तर सकारात्मक है. मुझे आपको 'ghz' से परिचित कराने की अनुमति दें। बस केवल एक नजर डाले:


लेकिन ऐसा करने से पहले, हमें एक अच्छी परीक्षण सेवा के रूप में गो और जीआरपीसी के साथ एक छोटी सेवा बनानी चाहिए।


एक छोटी प्रोटो फ़ाइल तैयार करें:

 syntax = "proto3"; option go_package = "stock-grpc-service/stocks"; package stocks; service StocksService { rpc Save(SaveRequest) returns (SaveResponse) {} rpc Find(FindRequest) returns (FindResponse) {} } message SaveRequest { Stock stock = 1; } message SaveResponse { string code = 1; } message Stock { string name = 1; float price = 2; string description = 3; } message FindRequest { enum Type { INVALID = 0; BY_NAME = 1; } message ByName { string name = 1; } Type type = 1; oneof body { ByName by_name = 2; } } message FindResponse { Stock stock = 1; }


और इसे उत्पन्न करें! (इसके अलावा, हमें प्रोटोक स्थापित करना चाहिए)

 protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative stocks.proto


हमारे परिणाम:
जीआरपीसी फ़ाइलें यहाँ!

कोडिंग का समय!

अगले चरण: जितनी जल्दी हो सके सेवाएँ बनाएँ।

हमारे लिए आसान!


  1. डीटीओ बनाएं (डीबी परत के लिए स्टॉक इकाई)

     package models // Stock – base dto type Stock struct { ID *int64 `json:"Id"` Price float32 `json:"Price"` Name string `json:"Name"` Description string `json:"Description"` }


  2. सर्वर लागू करें

     // Server is used to implement stocks.UnimplementedStocksServiceServer. type Server struct { pb.UnimplementedStocksServiceServer stockUC stock.UseCase } // NewStockGRPCService stock gRPC service constructor func NewStockGRPCService(emailUC stock.UseCase) *Server { return &Server{stockUC: emailUC} } func (e *Server) Save(ctx context.Context, request *stocks.SaveRequest) (*stocks.SaveResponse, error) { model := request.Stock stockDto := &models.Stock{ ID: nil, Price: model.Price, Name: model.Name, Description: model.Description, } err := e.stockUC.Create(ctx, stockDto) if err != nil { return nil, err } return &stocks.SaveResponse{Code: "ok"}, nil } func (e *Server) Find(ctx context.Context, request *stocks.FindRequest) (*stocks.FindResponse, error) { code := request.GetByName().GetName() model, err := e.stockUC.GetByID(ctx, code) if err != nil { return nil, err } response := &stocks.FindResponse{Stock: &stocks.Stock{ Name: model.Name, Price: model.Price, Description: model.Description, }} return response, nil }


पूरा कोड यहां: क्लिक करें, कृपया!

झसे आज़माओ!

  1. ब्रू के साथ GHz इंस्टॉल करें (हमेशा की तरह): लिंक


  2. आइए एक सरल उदाहरण देखें: लिंक


अब, हमें इसे थोड़ा बदलना चाहिए:

  1. प्रोटो फ़ाइलों वाले फ़ोल्डर में ले जाएँ।


  2. विधि जोड़ें: stocks.StocksService.Save


  3. सरल मुख्य भाग जोड़ें: '{"स्टॉक": {"नाम":"एपीपीएल", "मूल्य": "1.3", "विवरण": "सेब स्टॉक" } }'।


  4. 10 कनेक्शन 20 गोरौटाइन श्रमिकों के बीच साझा किए जाएंगे। 2 गोरूटाइन की प्रत्येक जोड़ी एक एकल कनेक्शन साझा करेगी।


  5. सेवा का पोर्ट सेट करें


और परिणाम:

 cd .. && cd stock-grpc-service/proto ghz --insecure \ --proto ./stocks.proto \ --call stocks.StocksService.Save \ -d '{"stock": { "name":"APPL", "price": "1.3", "description": "apple stocks"} }' \ -n 2000 \ -c 20 \ --connections=10 \ 0.0.0.0:5007


इसे चलाने के लिए!

 Summary: Count: 2000 Total: 995.93 ms Slowest: 30.27 ms Fastest: 3.11 ms Average: 9.19 ms Requests/sec: 2008.16 Response time histogram: 3.111 [1] | 5.827 [229] |∎∎∎∎∎∎∎∎∎∎∎ 8.542 [840] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ 11.258 [548] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ 13.973 [190] |∎∎∎∎∎∎∎∎∎ 16.689 [93] |∎∎∎∎ 19.405 [33] |∎∎ 22.120 [29] |∎ 24.836 [26] |∎ 27.551 [6] | 30.267 [5] | Latency distribution: 10 % in 5.68 ms 25 % in 6.67 ms 50 % in 8.27 ms 75 % in 10.49 ms 90 % in 13.88 ms 95 % in 16.64 ms 99 % in 24.54 ms Status code distribution: [OK] 2000 responses


और क्या, टर्मिनल में हर चीज़ को फिर से घूरें? नहीं, ghz के साथ, आप एक रिपोर्ट भी तैयार कर सकते हैं, लेकिन यांडेक्स के विपरीत, यह स्थानीय रूप से तैयार की जाएगी और ब्राउज़र में खोली जा सकती है। बस इसे सेट करें:

 ghz --insecure -O html -o reports_find.html \ ...

-O + html → आउटपुट स्वरूप

-ओ फ़ाइल नाम


परिणाम वेब पेज के रूप में :D


निष्कर्ष

:डी


संक्षेप में, जब आपको प्रति सेकंड 100+ अनुरोधों के भार को संभालने या संभावित कमजोरियों की पहचान करने के लिए अपनी सेवा की क्षमता का त्वरित मूल्यांकन करने की आवश्यकता होती है, तो टीमों को शामिल करने, AQA से सहायता लेने, या बुनियादी ढांचे की टीम पर भरोसा करने की जटिल प्रक्रियाएं शुरू करने की कोई आवश्यकता नहीं है।


अक्सर, डेवलपर्स के पास सक्षम लैपटॉप और कंप्यूटर होते हैं जो एक छोटे लोड परीक्षण को निष्पादित कर सकते हैं। तो, आगे बढ़ें और इसे आज़माएं—अपना कुछ समय बचाएं!


मुझे विश्वास है कि आपको यह संक्षिप्त लेख लाभदायक लगा होगा।

मूल्यवान दस्तावेज़ीकरण जिसे मैं पढ़ने की अनुशंसा करता हूँ:

यांडेक्स टैंक: डॉक्स लिंक

यांडेक्स टैंक गिटहब: गिटहब लिंक

यांडेक्स टैंक सेटिंग: लिंक

ghz आधिकारिक पेज: लिंक

GHz सेटिंग: लिंक
ghz कॉन्फिग: लिंक


बल आपके साथ हो!

एक बार फिर धन्यवाद, और शुभकामनाएँ! 🍀🕵🏻