Chapter 17Lesson 03~175 minutes

JMS, FTP, LDAP, TCP, and Other Protocol Test Patterns: Configuration, Design Patterns, and Trade-Offs

Protocol sampler choice is an architecture decision. A built-in sampler is attractive when it expresses the real wire/session behavior. A custom/plugin/client implementation is justified only when the built-in model cannot represent required framing, provider APIs, security, or correlation without distortion.

Built-in vs customPersistent socketsRequest/replyDirect protocolLocal vs container

Learning objectives

  • Choose built-in samplers before custom/plugin implementations when semantics fit.
  • Choose persistent or per-sample connections from the production client lifecycle.
  • Distinguish one-way messaging from request/reply latency.
  • Choose direct protocol or application-level tests from the layer under investigation.
  • Choose mandatory local fixtures or optional containers based on dependency/CI cost.
  • Connect configured and achieved load to generator/provider/target state.

1. Mandatory executable path remains TCP-only and local

Runnable examples remain 127.0.0.1:9100, ≤2 threads, ≤10 seconds. Broker, FTP, LDAP, Kubernetes, cloud services, public endpoints, corporate systems, third-party plugins, and paid telemetry are optional design contexts—not chapter requirements.

2. Built-in protocol sampler versus custom/plugin client

Built-in sampler Custom/plugin/client
Prefer when JMeter already models the needed connection/framing/session semantics. Use when vendor/binary/security semantics cannot be represented correctly.
Lower supply-chain/classpath/maintenance cost. Adds version/API/classloader/plugin compatibility and generator cost.
Primary docs define sample-result behavior. You must define response codes/timing/correlation semantics yourself.
Easier portability across local/CI JMeter installs. Every injector needs the same JARs/config/provider versions.

For TCP, try built-in TCPClientImpl, BinaryTCPClientImpl, or LengthPrefixedBinaryTCPClientImpl before writing a custom TCPClient. Custom code is justified only when real framing/encoding cannot be expressed safely.

3. Persistent versus per-sample TCP connections

Persistent sockets match clients that establish a session/connection and perform many messages. Per-sample connections match protocols/clients that connect for one operation or when connection setup itself is the metric.

Connection reuse changes target accept/TLS/login load and generator socket lifecycle. Keep it constant when comparing payload/query behavior, or explicitly label it as the independent variable.

4. Fire-and-forget versus request/reply messaging

Request only / fire-and-forget Request reply
Measures producer/client send path. Measures until a reply is received.
Good for broker ingress/producer throughput. Good for request-to-reply service latency.
Queue depth/consumer lag must be observed separately. Reply path/correlation and timeout become part of sample.
Can accumulate messages quickly if no consumer/cleanup. Requires reply queue/consumer/session correctness.

One-way send time can be very low while consumers are minutes behind. Always pair one-way publishing with broker depth/lag/acknowledgement telemetry appropriate to the provider.

5. JMS Subscriber receive versus listener strategy

Current JMeter JMS Subscriber supports a receive-based client that fetches messages only while the sampler is active and retains a connection between samples; this suits queues. The listener strategy remains active after the sample and stores incoming messages for later sampling; this suits topics.

That difference changes when work happens relative to sampler timing and generator memory/queue state.

6. Durable subscriptions and client IDs

Durable topic subscriptions create provider-side state. Current JMeter docs specifically warn that Client ID must be unique when more than one thread is used—for example by including ${__threadNum}. Reusing one durable ID/client ID can cause provider errors or unintended shared state.

Always document deletion/cleanup of run-scoped durable subscriptions after a disposable test.

7. FTP GET versus PUT and local I/O

GET tests server read/transfer and may optionally write local files or retain response bytes. PUT tests upload and mutates server state. Saving a large downloaded file also adds generator disk I/O; that can become part of elapsed/generator bottleneck.

Use a disposable FTP root and explicitly clean only files with the current run prefix. Do not point uploads at shared/corporate FTP locations.

8. LDAP basic versus Extended

Basic LDAP Request is easier for Add/Modify/Delete/Search examples. LDAP Extended is better when session realism matters because it models thread bind/unbind and other LDAP operations more directly.

For capacity claims about an application that uses LDAP through its own pool/cache, test the application too; direct LDAP bypasses those layers.

9. Direct protocol performance versus application-level test

Direct TCP/JMS/FTP/LDAP can isolate broker/directory/file/protocol behavior. It bypasses application validation, business orchestration, caches, retry logic, connection pools, and other services. Use direct protocol tests to answer protocol-layer questions and application tests for end-to-end questions.

10. Local process versus optional container stack

The mandatory TCP server is a plain local Python process: no image downloads, container network, volume, or orchestrator state. A containerized broker/FTP/LDAP service can improve reproducibility for teams that already use containers, but adds image version, startup health, port mapping, volumes, credentials, and resource caps.

If containers are used, pin versions, bind ports only to loopback, use disposable volumes, and preserve container CPU/memory/log evidence separately from JMeter.

11. Protocol security choices

Do not assume a sampler implies secure transport. Plain FTP is not SFTP; raw TCP is not TLS; LDAP versus LDAPS/StartTLS differ; JMS security depends on provider configuration. Use the actual authorized secure protocol/client configuration required by the system.

Never disable TLS/authentication checks to make a test pass. The local mandatory fixture intentionally has no credentials/TLS so no insecure workaround is needed.

12. Provider/client dependency management

Provider JARs belong in JMeter's runtime classpath on every injector. Pin versions and restart JMeter after classpath changes. A missing JMS provider JAR is not a broker saturation symptom. A plugin upgrade can alter sample semantics, so keep JMeter/provider/plugin versions with result evidence.

For every executed non-HTTP profile, preserve the raw JTL together with its matching jmeter.log, the exact JMX/data/properties, generator CPU/memory/socket state, and protocol-target evidence (for example TCP connection IDs, broker queue depth, FTP file hashes, or LDAP session/search evidence). Never substitute a public, corporate, shared, or production protocol endpoint for the local/explicitly authorized target.

13. Configuration-layer boundaries

Layer Examples Do not confuse with
JMeter core TCP/FTP/LDAP/JMS samplers, Config Elements, assertions, timers Provider/broker/directory business state.
Java/JVM provider JAR classpath, charset, TLS trust, heap/GC Queue depth or server file I/O.
OS/network sockets, DNS, TIME_WAIT, loopback/ports Application message acknowledgement.
Target/SUT broker queues, FTP files, LDAP entries, TCP service workers Generator listener/save cost.
Plugin/provider JMS provider JAR/custom TCP client/plugin version JMeter core availability.
CI/container image/volume/port/startup/resources/secrets Protocol semantics themselves.

14. Worked scenario

Requirement: “Measure order-worker request-to-reply latency over JMS and separately verify broker producer ingress.”

  • Request-to-reply profile: dedicated request/reply queues, unique correlation IDs, JMS Point-to-Point Request Response, reply timeout, consumer/server telemetry.
  • Producer profile: Request Only, explicit fixed message size/rate, queue-depth/consumer-lag telemetry, bounded backlog/cleanup.
  • Do not quote producer-send p95 as worker end-to-end p95.

15. Decision table

Question Preferred pattern Evidence
Text line-protocol request/reply Built-in TCPClientImpl + explicit EOL JTL + connection/request IDs + server timing.
Binary length-prefixed protocol Built-in LengthPrefixedBinaryTCPClientImpl if compatible Binary fixture + framing/timeouts.
JMS producer ingress Request Only + broker depth/lag Send samples + queue telemetry.
JMS service latency Request Response + correlation/reply queue Request/reply JTL + service/broker telemetry.
Directory session search LDAP Extended bind/search/unbind Session/bind/search telemetry.
End-user app behavior Application/API-level test App pool/cache/business + downstream telemetry.

16. Configured versus achieved load

Configured TCP samples, JMS publishes, FTP transfers, or LDAP searches are only intent. Achieved valid operations depend on connection reuse, provider/session setup, reply timeouts, queue backpressure, file I/O, directory limits, generator CPU/GC, and server saturation. Report achieved operation counts and protocol-specific target state.

Knowledge check

When should a custom TCP client be considered?

What target metric must accompany JMS Request Only load?

Why can FTP Save Local File change a performance test?

Why should JMS Client ID include a thread-unique value for durable subscriptions?

Why does a direct LDAP test not prove app-login capacity?

Next lesson

Diagnose framing, provider, queue, file, and session failures

Lesson 4 intentionally breaks TCP framing and analyzes the exact timeout, then covers missing JMS provider JARs, shared identifiers, accumulated messages/files, corporate targets, and unsafe security shortcuts.

Official references and version notes

Version and compatibility note

Version-sensitive statements were rechecked against current Apache JMeter primary documentation on 2026-09-05. The course baseline remains Apache JMeter 5.6.3 with a Java 17 JDK; JMeter 5.6.3 requires Java 8+. TCP Sampler is built in and the mandatory lab uses its default TCPClientImpl with explicit LF (EOL byte=10) framing. With connection reuse enabled, TCP connections are reused only by samplers in the same JMeter thread that use the exact same host string and port; different threads use different sockets. JMeter's FTP, LDAP/LDAP Extended, JMS Publisher/Subscriber/Point-to-Point, and TCP samplers are currently built in. JMS is different from TCP/FTP/LDAP because JMeter does not bundle a JMS provider implementation JAR: provider-specific client/JNDI libraries must be supplied in JMeter's lib directory and JMeter restarted. FTP sampler latency is the FTP login time, not full file-transfer elapsed time. JMS request-only measures the send-side sample; request-reply waits for a reply from the service and is the appropriate built-in pattern when request-to-reply latency is required. LDAP Extended models session operations such as thread bind/unbind. Core TCP login/password fields are not used by the supplied TCP clients and any entered password is stored unencrypted, so the TCP lab leaves them blank.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.