paint-brush
টার্বোচার্জ লোড টেস্টিং: লাইটনিং-ফাস্ট কোড চেকের জন্য ইয়ানডেক্সট্যাঙ্ক + গিগাহার্টজ কম্বো!দ্বারা@mrdrseq
486 পড়া
486 পড়া

টার্বোচার্জ লোড টেস্টিং: লাইটনিং-ফাস্ট কোড চেকের জন্য ইয়ানডেক্সট্যাঙ্ক + গিগাহার্টজ কম্বো!

দ্বারা Ilia Ivankin14m2023/11/23
Read on Terminal Reader

অতিদীর্ঘ; পড়তে

সংক্ষেপে, যখন প্রতি সেকেন্ডে 100+ অনুরোধের লোড পরিচালনা করার বা সম্ভাব্য দুর্বলতাগুলি সনাক্ত করার জন্য আপনার পরিষেবার ক্ষমতার দ্রুত মূল্যায়নের প্রয়োজন হয়, তখন দলগুলির সাথে জড়িত জটিল প্রক্রিয়াগুলি শুরু করার, AQA থেকে সহায়তা চাওয়া বা অবকাঠামো দলের উপর নির্ভর করার দরকার নেই৷ প্রায়শই নয়, বিকাশকারীদের কাছে সক্ষম ল্যাপটপ এবং কম্পিউটার রয়েছে যা একটি ছোট লোড পরীক্ষা চালাতে পারে। সুতরাং, এগিয়ে যান এবং এটি একটি শট দিন - নিজেকে কিছু সময় বাঁচান!
featured image - টার্বোচার্জ লোড টেস্টিং: লাইটনিং-ফাস্ট কোড চেকের জন্য ইয়ানডেক্সট্যাঙ্ক + গিগাহার্টজ কম্বো!
Ilia Ivankin HackerNoon profile picture

হাই, আছে!


মাঝে মাঝে, দ্রুত লোড পরীক্ষার প্রয়োজন দেখা দেয়, তা স্থানীয় পরিবেশে হোক বা পরীক্ষার প্ল্যাটফর্মে হোক। সাধারণত, এই জাতীয় কাজগুলি বিশেষ সরঞ্জামগুলি ব্যবহার করে মোকাবেলা করা হয় যা পুঙ্খানুপুঙ্খ পূর্ব বোঝার দাবি রাখে। যাইহোক, এন্টারপ্রাইজ এবং স্টার্টআপের মধ্যে যেখানে দ্রুত সময়ে-টু-বাজার এবং প্রম্পট হাইপোথিসিস বৈধতা সর্বাগ্রে, অত্যধিক টুল পরিচিতি একটি বিলাসিতা হয়ে ওঠে।


এই নিবন্ধটির লক্ষ্য হল ডেভেলপার-কেন্দ্রিক সমাধানগুলিকে আলোকিত করা যা গভীর ব্যস্ততার প্রয়োজনীয়তা দূর করে, ডকুমেন্টেশনের পৃষ্ঠাগুলিতে না গিয়ে প্রাথমিক পরীক্ষার অনুমতি দেয়।


স্থানীয় চলমান

আপনার ইনস্টল করা উচিত::

  1. ডকার - এর জন্য সমস্ত পরিষেবা এবং সরঞ্জাম প্রয়োজন।


  2. জাভা 19+ — কোটলিন পরিষেবার জন্য। এছাড়াও, আপনি Java 8 সংস্করণ ব্যবহার করার চেষ্টা করতে পারেন; এটি কাজ করা উচিত, কিন্তু আপনাকে Gradle সেটিংস পরিবর্তন করতে হবে।


  3. গোলং - একটি পরিষেবা হল গোলং পরিষেবা =)


  4. পাইথন 3+ — ইয়ানডেক্স ট্যাঙ্কের জন্য।

প্রযুক্তিগত প্রয়োজনীয়তা

আমাদের যাত্রা শুরু করার আগে, পরীক্ষার উদ্দেশ্যে দৃষ্টান্তমূলক উদাহরণ হিসাবে কাজ করতে পারে এমন কয়েকটি পরিষেবা তৈরি করার পরামর্শ দেওয়া হয়।


স্ট্যাক: কোটলিন + ওয়েবফ্লাক্স। r2dbc + postgres।


আমাদের পরিষেবা আছে:

- সমস্ত স্টক পান (সীমা 10) পান /api/v1/stocks
- GET__ /api/v1/stock নামে স্টক পান ?name=appl
- স্টক পোস্ট সংরক্ষণ করুন /
api/v1/স্টক


এটি একটি সহজ পরিষেবা হওয়া উচিত কারণ আমাদের লোড পরীক্ষার উপর ফোকাস করতে হবে =)

কোটলিন এবং 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() } }


সম্পূর্ণ কোড এখানে: গিটহাব


একটি ডকার ফাইল তৈরি করুন:

 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 



ঠিক আছে, পরীক্ষাগুলো কোথায়?

এগিয়ে যাওয়া: আমরা কীভাবে পরীক্ষা চালিয়ে যেতে পারি? বিশেষভাবে, কিভাবে আমরা আমাদের সাম্প্রতিক বিকশিত পরিষেবার জন্য একটি পরিমিত লোড পরীক্ষা শুরু করতে পারি? এটি অপরিহার্য যে পরীক্ষার সমাধানটি ইনস্টল করার জন্য সহজ এবং ব্যবহারকারী-বান্ধব উভয়ই।


আমাদের সময় সীমাবদ্ধতার প্রেক্ষিতে, বিস্তৃত ডকুমেন্টেশন এবং নিবন্ধগুলির মধ্যে অনুসন্ধান করা একটি কার্যকর বিকল্প নয়। সৌভাগ্যবশত, একটি কার্যকর বিকল্প আছে — Yandex ট্যাঙ্কে প্রবেশ করুন। ট্যাঙ্কটি পরীক্ষার জন্য একটি শক্তিশালী যন্ত্র এবং এর সাথে গুরুত্বপূর্ণ একীকরণ রয়েছে জেমিটার , কিন্তু নিবন্ধে, আমরা এটি একটি সহজ টুল হিসাবে ব্যবহার করব।


ডক্স: 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


কনফিগারেশনের জন্য মূল সেটিংস:

  • ঠিকানা এবং পোর্ট: আমাদের অ্যাপ্লিকেশন হিসাবে একই.


  • লোড টেস্ট প্রোফাইল (লোড_প্রোফাইল): আমরা 'রেখাযুক্ত' প্রকার ব্যবহার করব, প্রতি সেকেন্ডে 100টি অনুরোধ থেকে 250টি 30-সেকেন্ডের সীমা সহ।


  • URI: পরীক্ষা করার জন্য URL-এর একটি তালিকা।


  • অটোস্টপ প্যাটার্ন: আমাদের পরিষেবা ইতিমধ্যেই কমে গেলে চাপ-পরীক্ষা করার দরকার নেই! =)


ব্যাশ স্ক্রিপ্ট কপি এবং পেস্ট করুন (ট্যাঙ্ক sh):

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


এবং চালান!


এর ফলে আমরা কী দেখব? ইয়ানডেক্স ট্যাঙ্ক পরীক্ষার সময় যোগ্য বলে মনে করা সমস্ত কিছু লগ করবে। আমরা 99তম পার্সেন্টাইল এবং অনুরোধ প্রতি সেকেন্ড (আরপিএস) এর মতো মেট্রিকগুলি পর্যবেক্ষণ করতে পারি।


টার্মিনাল? সত্যিই?


তাহলে, আমরা কি এখন টার্মিনালের সাথে আটকে আছি? আমি একটি GUI চাই! চিন্তা করবেন না, ইয়ানডেক্স ট্যাঙ্ক এর জন্যও একটি সমাধান রয়েছে। আমরা ওভারলোড প্লাগইনগুলির একটি ব্যবহার করতে পারি। এটি কীভাবে যুক্ত করবেন তার একটি উদাহরণ এখানে:

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


আমাদের টোকেন যোগ করা উচিত; শুধু এখানে যান এবং GitHub দ্বারা যুক্তি: https://overload.yandex.net

কোড


ঠিক আছে, একটি GET অনুরোধের সাথে মোকাবিলা করা সহজ, কিন্তু পোস্ট সম্পর্কে কী? আমরা কিভাবে অনুরোধ গঠন করব? ব্যাপারটা হল, আপনি শুধু অনুরোধটিকে ট্যাঙ্কে নিক্ষেপ করতে পারবেন না; আপনি এর জন্য নিদর্শন তৈরি করতে হবে! এই নিদর্শন কি? এটি সহজ — আপনাকে একটি ছোট স্ক্রিপ্ট লিখতে হবে, যা আপনি আবার ডকুমেন্টেশন থেকে আনতে পারেন এবং আমাদের প্রয়োজন অনুসারে কিছুটা পরিবর্তন করতে পারেন।


এবং আমাদের নিজেদের শরীর এবং শিরোনাম যোগ করা উচিত:

 #!/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 থাকবে। কনফিগার করার জন্য নতুন প্যারাম সেট করুন এবং URL গুলি মুছুন:

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


এবং এটি আরও একবার চালান!

এটা GRPC পরীক্ষা করার সময়!

এখনো না?


এইচটিটিপি পদ্ধতি লোড করার সাথে পরিচিত হওয়ার পরে, জিআরপিসি-এর পরিস্থিতি বিবেচনা করা স্বাভাবিক। আমরা কি সৌভাগ্যবান যে GRPC-এর জন্য সমানভাবে অ্যাক্সেসযোগ্য টুল আছে, যা একটি ট্যাঙ্কের সরলতার মতো? উত্তরটি ইতিবাচক। আমাকে 'GHz' এর সাথে পরিচয় করিয়ে দেওয়ার অনুমতি দিন। একমূহুর্তের জন্য তাকাও:


কিন্তু আমরা তা করার আগে, আমাদের উচিত Go এবং GRPC-এর সাথে একটি ভাল পরীক্ষা পরিষেবা হিসাবে একটি ছোট পরিষেবা তৈরি করা।


একটি ছোট প্রোটো ফাইল প্রস্তুত করুন:

 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


আমাদের ফলাফল:
grpc ফাইল এখানে!

কোডিং সময়!

পরবর্তী পদক্ষেপ: যত দ্রুত সম্ভব পরিষেবা তৈরি করুন।

আমাদের জন্য সহজ!


  1. dto তৈরি করুন (ডিবি স্তরের জন্য স্টক সত্তা)

     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. সরল বডি যোগ করুন: '{“স্টক”: { “নাম”:”APPL”, “দাম”: “1.3”, “বিবরণ”: “আপেল স্টক”} }'।


  4. 20 গোরুটিন কর্মীদের মধ্যে 10 সংযোগ ভাগ করা হবে। 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 দিয়ে, আপনি একটি প্রতিবেদনও তৈরি করতে পারেন, কিন্তু Yandex-এর বিপরীতে, এটি স্থানীয়ভাবে তৈরি হবে এবং ব্রাউজারে খোলা যাবে। শুধু এটি সেট করুন:

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

-O + html → আউটপুট ফরম্যাট

-o ফাইলের নাম


ওয়েব পেজ হিসাবে ফলাফল : ডি


উপসংহার

:D


সংক্ষেপে, যখন প্রতি সেকেন্ডে 100+ অনুরোধের লোড পরিচালনা করার বা সম্ভাব্য দুর্বলতাগুলি সনাক্ত করার জন্য আপনার পরিষেবার ক্ষমতার দ্রুত মূল্যায়নের প্রয়োজন হয়, তখন দলগুলির সাথে জড়িত জটিল প্রক্রিয়াগুলি শুরু করার, AQA থেকে সহায়তা চাওয়া বা অবকাঠামো দলের উপর নির্ভর করার দরকার নেই৷


প্রায়শই নয়, বিকাশকারীদের কাছে সক্ষম ল্যাপটপ এবং কম্পিউটার রয়েছে যা একটি ছোট লোড পরীক্ষা চালাতে পারে। সুতরাং, এগিয়ে যান এবং এটি একটি শট দিন - নিজেকে কিছু সময় বাঁচান!


আমি বিশ্বাস করি আপনি এই সংক্ষিপ্ত নিবন্ধটি উপকারী পেয়েছেন।

মূল্যবান ডকুমেন্টেশন আমি পড়ার সুপারিশ করছি:

ইয়ানডেক্স ট্যাঙ্ক: ডক্স লিঙ্ক

ইয়ানডেক্স ট্যাঙ্ক গিটহাব: গিটহাব লিঙ্ক

ইয়ানডেক্স ট্যাঙ্ক সেটিং: লিঙ্ক

GHz অফিসিয়াল পেজ: লিঙ্ক

GHz সেটিং: লিঙ্ক
GHz কনফিগারেশন: লিঙ্ক


বল আপনার সাথে হতে পারে!

আবারও ধন্যবাদ, এবং শুভকামনা! 🍀🕵🏻