Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

Load Test Rails Apps อย่างมีประสิทธิภาพด้วย Apache JMeter

ก่อน Release Software ให้ End-users เราทำ Tests หลากหลาย ให้แน่ใจว่า Application Bug-free และ Meet Business Requirements แม้ Test มาก แต่ไม่มั่นใจว่า Software Stable โดย Users ไม่ได้ใช้จริง หลัง End-users เริ่มใช้ สิ่งต่างๆ อาจทำให้ App ไม่ Behave ตามที่คาดหวัง เหตุผลบางอย่าง:

  • User Behavior Unpredictable
  • Users Distributed Across Locations
  • Large Number of Users ใช้ App พร้อมกัน

สำหรับ Large-scale Applications สิ่งเหล่านี้ Crucial ก่อน Full Release เพื่อให้ App Work As Expected ต้อง Consider ขณะ Roll Out:

  • Phased Rollout - ทดสอบโดย User กลุ่มเล็กก่อน ทุกคนเข้าถึง ฟังก์ชัน ช่วย Determine User Behavior
  • Load Testing - Phased Rollout รู้ User Behavior แต่ไม่รู้ Platform Works ยังไงเมื่อ Many Users ใช้พร้อมกันจาก Locations ต่างๆ

Load Testing คืออะไร ต่างจาก Performance Testing ยังไง?

3 Terms ต่อไปอาจคล้ายกันแตต่างกัน:

  • Performance Testing
  • Load Testing
  • Stress Testing

Performance Testing General Testing Mechanism Assess App Performance กับ Given Input อาจ Single-user หรือ Multiple Users Conducted เพื่อ Assess Metrics: Response Time, CPU/Memory Usage Load/Stress Testing เป็น Subset ของ Performance Testing

Load Testing Conducted ให้แน่ใจ App Perform As Expected กับ Specified Number of Users Concurrently Over Specified Time ช่วย Determine Users ที่ System Handle ได้

Stress Testing และ Load Testing เกี่ยวข้องกัน ใช้ Mechanism คล้ายกัน แต่ Goal ต่างกัน Goal Load Testing: Determine App Works กับ Specified Users Stress Testing: Determine App Behaves/Handles Failure หลัง Hit Load Limit

Based on Ramp-up Period Performance Testing Categorize: Spike Test (Sudden Spike Users Short Time) หรือ Soak Test (Slow Ramp-up Longer Duration)

ทำไม Performance Testing สำคัญ?

ใน Rails Project เราคาดการณ์ Growth Users มาก ใกล้ๆ นี้ อยาก Ensure App Perform As Expected Crucial Functionality Not Lost กับ Increased Users ทำยังไง? เรา Load Test Check App Handle Given Increase Users Performance Testing Important ใน Cases อื่นๆ:

  • App คาด Spike Users วันเฉพาะ (Black Friday) Spike Test Brief Ramp-up หา Potential Issues
  • Load Testing หา Bugs ที่ไม่เห็นหรือ Minimal ตอน Few Users
  • Evaluate Platform Speed Impact โดย Increased Load ถ้า Slow Lose Customers
  • Assess System Works Under Increased Load Crash ด้วย High CPU/Memory 10,000 Users?
  • Cost Running App สำหรับ Specific Users Determine ได้ด้วย Load Testing

เราเจอ Bug ใน Rails App ระหว่าง Load Test อธิบาย Scenario คล้ายกันที่เรา Identify Issue Hotel Booking App มี Open Booking Process Few Users Book Room Fine แต่ Multiple Users Book Same Room 2 Users Book Successfully ด้วย Load Testing เรา Identify Problem และ Fix Early Stage ก่อน Release Feature

ใช้ Apache JMeter Load Test Rails App

JMeter Apache 2.0-licensed Open-source Load Testing Tool Thread-based Load Testing ด้วย Thread-based Testing Simulate Stress ได้ง่ายเมื่อ Many Users ใช้ App Simultaneously JMeter ให้ Good Reporting Test Results

เราจะดูวิธีใช้ Apache JMeter Perform Load Tests Identify Potential Issues และ Response Time โดย Simulate Many Users

JMeter Download: https://jmeter.apache.org/download_jmeter.cgi#binaries

JMeter Terminologies ควรคุ้นเคย

  • Test Plan Top-level Thing 定義 Load Testing Components Global Configs/Variables ที่นี่
  • Thread Group Define Threads/Configs: Numbers of Threads, Ramp-up Periods, Delay Between Threads, Loops Treat As Parallel Users สำหรับ Load Test
  • Sampler Single Thread Execute Types: HTTP Request, SMTP Request, TCP Request
  • Pre/Post Processor Execute Before/After Sampler Runs Post-processors รับ Response Data จาก API Call หนึ่ง ส่งต่อ Next One
  • Listener Listen Response จาก Sampler Provide Aggregated Reports Response Time/Response จากแต่ละ Thread
  • Assertion Validate Response Data ตาม Expected จาก Sampler
  • Config Element Define Configs: HTTP Header, HTTP Cookies, CSV Dataset Configs

Run Load Test ต้องสร้าง JMX File Define JMeter Terminologies ข้างบน

เตรียม JMX File สำหรับ Load Test

JMX = JMeter Project File XML Format เขียน JMX Manual ยาก ใช้ JMeter Interface สร้าง File

Open JMeter Interface Locate Test Plan ภายใน Add Threads และ Load Test Configs

Load Test Rails Apps อย่างมีประสิทธิภาพด้วย Apache JMeter

Test Plan Rename ตาม Load Test Target Config Thread Group(Users) Keep Defaults Move On Create Threads Group

Add -> Threads(Users) -> Thread Group

ใน Thread Group Default Single Thread เปลี่ยน Number ตาม Simulate Users

Load Test Web-based Rails App Add HTTP Sampler Add Sampler ใน ThreadGroup Add -> Sampler -> HTTP Request

Config IP/Domain Load Test, HTTP Method, Request Body สำหรับ HTTP Endpoint

เพื่อ View Load Test Report Add Listener ใน Thread Group Add -> Listener -> View Result Tree

View Result Tree แสดง Response Time แต่ละ Thread Add Reports อื่นได้ 'View Result Tree' ใช้ Debugging Only ไม่ Actual Testing

Create Simple Test Plan Execute ได้เลย กด Play Icon Top Bar JMeter

Things to Consider ก่อน Load Test Rails App

Example ข้างบน Simple Single Endpoint HTTP Request ใน Rails App Endpoints Locked with Authentication ต้อง Ensure:

  • Web Cookie - HTTP Endpoints ต้อง Cookie Header ก่อน Load Test JMeter ให้ Functionality Add Cookie เมื่อ User Logged In Next Section: Record Browser Request Convert JMX File Load Test Cookie Recording
  • Rails CSRF Token - Rails Protect App CSRF Token ต้อง Ensure Request มี CSRF Auth ใน Header ก่อน Load Test CSRF Token อยู่ใน header ใน meta Tag ใน HTML

Rails CSRF Token Fetch ใน JMeter ด้วย Post-processor Right-click HTTP Request Load Web Page มี CSRF Token Select Add -> Post Processor -> Regular Expression Extractor Configs:

  • Reference Name: csrf_value
  • Regular Expression: name="csrfToken" content="(.+?)"
  • Template: $1$
  • Match No: 1

Variable csrf_value ใช้ทำ Request ได้

Recording Requests จาก Browser สร้าง JMX File

Few HTTP Endpoints สร้าง JMX จาก JMeter Interface Simple แต Larger Test Case ยาก อาจ Miss Actual Requests ผู้ใช้ทำ เราอยาก Actual Requests จาก Browser Recorded และ JMX Auto-created

JMeter เป็น Proxy ระหว่าง Rails App และ Browser MITM (Man in the Middle) Attack

Load Test Rails Apps อย่างมีประสิทธิภาพด้วย Apache JMeter

Create Recording JMeter: File -> Templates -> Recording Click Create Specify Hostname Recording Auto-generate Things: Cookie Manager Cookie Manager Save Cookie สำหรับ Authentication

Verify HTTPS Requests ด้วย JMeter SSL Certificate

Request จาก Browser Forward ไป JMeter JMeter Forward ไป Web Service Record Requests Run Load Test จาก Recording ถ้า App Require HTTPS SSL Certificate ต้อง Add Certificate ไป Browser Firefox/Other Browser Firefox: Settings > Privacy > Manage Certificate Add JMeter Certificate Browser Recognize Certificate Generated by JMeter

Enter cmd + sht + g Path /usr/local/Cellar/jmeter/5.2/libexec/bin/jmeter Add Certificate

Configure Firefox ใช้ JMeter As Proxy

Forward Request Firefox ไป JMeter Recording Script Firefox: Preferences -> Advanced -> Connection(settings) HTTP Proxy: "localhost" Port: "8080" Check "Use this proxy server for all protocols"

ไป JMeter Script Recording Section จาก Template ก่อนหน้า กด Start JMeter Accept Incoming Requests Firefox Browse App Load Test Record และ Convert JMX File Run Load Test

Distributed Load Testing กับ JMeter

Run Test จาก Local Machine OK ตอน Prepare Test Plan แต Actual Test ต้อง Change Single Machine มี Hardware Limitations (CPU, Memory) และ Request Location Limitations Tests Simulate Actual Users ต้อง Distribute Tests ไป Servers ต่างๆ Single Place View Results

JMeter ให้ Primary Node Orchestrate Test และ Secondary Nodes Run Test Simulate Real Users Distribute Testing Servers Regions ใกล้ Actual Users

Load Test Rails Apps อย่างมีประสิทธิภาพด้วย Apache JMeter

Perform Distributed Test: Install JMeter Primary และ Secondary Servers

Secondary Server:

  • jmeter/bin Execute jmeter-server Start Server Execute Test
  • CSV Input Needed Add Files This Server

Primary Server:

  • jmeter/bin Open jmeter.properties
  • Edit remote_hosts Add Secondary Server IPs Comma-separated remote_hosts=,
  • Run JMeter Test

Secondary Servers Run Actual Test Primary Server Aggregate Reports

Load Testing ใช้ CLI Command แทน Trigger จาก UI เพราะ Cause Performance Problems Load Testing Servers JMeter Command Specify JMX Filename:

> jmeter -n -t path/to/test.jxm -r

OR

> jmeter -n -t path/to/test.jxm -R s1_ip,s2_ip,…

-r ใช้ Remote Server ใน jmeter.properties

-n Run Without GUI Mode

-t Path to JMX File

เราตัดสินใจ Puma vs Unicorn สำหรับ Rails Server ยังไง

Puma และ Unicorn Web Servers สำหรับ Rails ทั้งคู่มี Benefits 選哪個ดี? ขึ้นกับ Application บาง App Unicorn ดี บาง App Puma เราเลือก Unicorn vs Puma สำหรับ Rails App Based on Data จาก Load Testing Load Test Rails App ครั้ง Unicorn อีกครั้ง Puma เปลี่ยนแค่ Web Server

ผลลัพธ์: Load Test Rails Apps อย่างมีประสิทธิภาพด้วย Apache JMeter

เราพบ Puma Perform Better สำหรับ Rails App เมื่อ Users เยอะ หมายถึง Handle More Users ด้วย Fewer App Servers

Note: ขึ้นอยู่กับ Server Instance Type และ Business Logic Processing ของ App

Common Failures ระหว่าง Stress Rails App และแก้ยังไง

  • Unoptimized Database Query
    • Eliminate N+1 Query Problem
    • Add Index ตาม Access Pattern
    • Use Redis-like Caching Layer หน้า Database
  • Slow Ruby Code Performance
    • Memoize Optimize Code
    • Figure Out O(n^2) Complexity Use Optimal Algorithms
  • Micro-service Architectures: HTTP Calls ระหว่าง Services เยอะ Network Calls Slow
    • Reduce HTTP Calls 用 Messaging System for Microservices
  • Same Record Created Twice เมื่อ Created Concurrently
    • Add Database-unique Constraint
    • Utilize FIFO Event (Queue)-based Resource Creation
  • Use Background Processing (Sidekiq) When Possible
  • Define SLA API Response Times Include Performance Testing ใน Development Lifecycle

Environment ไหนควรใช้ Load Testing?

Load Test ใน Production ไม่ Ideal เพราะ Cause Issues/Downtime ไม่อยากสร้างปัญหา Production แต่ยังอยาก Test Report Reflect True Data เหมือน Production สำหรับ Load/Stress Tests แนะนำ Replica Environment ของ Production รวม:

  • Number of Application Servers
  • Database Server Hardware Specs รวม Replicas
  • Production-like Data ใน Testing Database Nearly Equal Data Volume As Production

Production-like Environment Challenging และ Costly Based on Load Test Components Infrastructure Touching Those Components Only Upgrade Production-like Save Cost Load/Stress Test App Once Every 3 Months แต Performance Testing Single User Validate Response Time Under Standard (200ms) Add To Development Cycle

Load Testing ต้อง Data-points: CPU/Memory Usage Target Server Spike Memory/CPU Crash App Add Monitoring Tools (Prometheus) ก่อน Load Test

Apache JMeter Powerful Load Testing Tool เราใช้ JMeter Load Test Rails Apps แต่ใช้ได้กับ Any Stack Load Testing ช่วย Data-powered Decisions ใน Application Load Testing อาจดู Scary แตะกับ Little Investment เริ่มต้น Add Stability และ Reliability Long-term