🎯 Introduction
AWS Load Balancers are critical components for building highly available, fault-tolerant, and scalable applications in the cloud. They distribute incoming traffic across multiple targets, ensuring optimal resource utilization and system reliability. This comprehensive guide explores all AWS Load Balancer types, their unique features, and when to use each one for maximum effectiveness.
Understanding the nuances between Application Load Balancer (ALB), Network Load Balancer (NLB), Gateway Load Balancer (GWLB), and Classic Load Balancer (CLB) is essential for architecting robust cloud solutions that can handle varying traffic patterns and requirements.
🔍 AWS Load Balancer Overview
📊 Load Balancer Types Comparison
graph TD
A[AWS Load Balancers] --> B[Application Load Balancer<br/>ALB - Layer 7]
A --> C[Network Load Balancer<br/>NLB - Layer 4]
A --> D[Gateway Load Balancer<br/>GWLB - Layer 3]
A --> E[Classic Load Balancer<br/>CLB - Layer 4/7]
B --> F[HTTP/HTTPS<br/>Content-based routing<br/>Microservices<br/>Container workloads]
C --> G[TCP/UDP<br/>Ultra-low latency<br/>High performance<br/>Static IP support]
D --> H[Third-party appliances<br/>Firewalls<br/>Intrusion detection<br/>Security inspection]
E --> I[Legacy applications<br/>Basic load balancing<br/>EC2-Classic<br/>Deprecated]
style B fill:#4ecdc4
style C fill:#ff6b6b
style D fill:#feca57
style E fill:#95a5a6
🏗️ High-Level Architecture
graph TD
subgraph "Internet"
Client[Client]
end
subgraph "AWS Load Balancers"
ALB[Application LB<br/>Layer 7]
NLB[Network LB<br/>Layer 4]
GWLB[Gateway LB<br/>Layer 3]
end
subgraph "Target Groups"
TG1[Web Servers<br/>EC2, ECS, Lambda]
TG2[App Servers<br/>EC2, ECS]
TG3[Security Appliances<br/>Third-party]
end
Client --> ALB
Client --> NLB
Client --> GWLB
ALB --> TG1
NLB --> TG2
GWLB --> TG3
style Client fill:#3498db
style ALB fill:#2ecc71
style NLB fill:#e74c3c
style GWLB fill:#f39c12
🌐 Application Load Balancer (ALB)
📋 Overview and Features
Application Load Balancer operates at Layer 7 (Application Layer) and is ideal for HTTP/HTTPS traffic routing with advanced features for modern applications.
✅ Key Features:
- Content-based routing using URL paths, hostnames, headers, and query strings
- HTTP/2 and WebSocket support
- Native IPv6 support
- Integration with AWS services (ECS, EKS, Lambda, etc.)
- Advanced health checks
- SSL/TLS termination and offloading
- User authentication (OIDC, SAML)
- Request tracing and detailed metrics
🛠️ ALB Implementation with Java
Maven Dependencies for ALB Management:
1<dependencies>
2 <!-- AWS SDK for ELB v2 -->
3 <dependency>
4 <groupId>software.amazon.awssdk</groupId>
5 <artifactId>elasticloadbalancingv2</artifactId>
6 <version>2.21.29</version>
7 </dependency>
8
9 <!-- AWS SDK for EC2 (for target management) -->
10 <dependency>
11 <groupId>software.amazon.awssdk</groupId>
12 <artifactId>ec2</artifactId>
13 <version>2.21.29</version>
14 </dependency>
15
16 <!-- Spring Boot for application -->
17 <dependency>
18 <groupId>org.springframework.boot</groupId>
19 <artifactId>spring-boot-starter-web</artifactId>
20 </dependency>
21
22 <!-- Metrics and monitoring -->
23 <dependency>
24 <groupId>io.micrometer</groupId>
25 <artifactId>micrometer-registry-cloudwatch</artifactId>
26 </dependency>
27</dependencies>
🔧 ALB Configuration Service
1@Service
2@Slf4j
3public class ApplicationLoadBalancerService {
4
5 private final ElasticLoadBalancingV2Client elbClient;
6 private final Ec2Client ec2Client;
7 private final String region;
8 private final String accountId;
9
10 public ApplicationLoadBalancerService(@Value("${aws.region}") String region,
11 @Value("${aws.account-id}") String accountId) {
12 this.region = region;
13 this.accountId = accountId;
14 this.elbClient = ElasticLoadBalancingV2Client.builder()
15 .region(Region.of(region))
16 .build();
17 this.ec2Client = Ec2Client.builder()
18 .region(Region.of(region))
19 .build();
20 }
21
22 public String createApplicationLoadBalancer(ALBConfiguration config) {
23 try {
24 // 1. Create the load balancer
25 CreateLoadBalancerRequest request = CreateLoadBalancerRequest.builder()
26 .name(config.getName())
27 .scheme(config.isInternetFacing() ? Scheme.INTERNET_FACING : Scheme.INTERNAL)
28 .type(LoadBalancerTypeEnum.APPLICATION)
29 .ipAddressType(config.getIpAddressType())
30 .subnets(config.getSubnetIds())
31 .securityGroups(config.getSecurityGroupIds())
32 .tags(Tag.builder()
33 .key("Environment")
34 .value(config.getEnvironment())
35 .build(),
36 Tag.builder()
37 .key("Application")
38 .value(config.getApplicationName())
39 .build())
40 .build();
41
42 CreateLoadBalancerResponse response = elbClient.createLoadBalancer(request);
43 String loadBalancerArn = response.loadBalancers().get(0).loadBalancerArn();
44
45 log.info("Created Application Load Balancer: {} with ARN: {}", config.getName(), loadBalancerArn);
46
47 // 2. Create target group
48 String targetGroupArn = createTargetGroup(config, loadBalancerArn);
49
50 // 3. Create listener
51 createListener(loadBalancerArn, targetGroupArn, config);
52
53 // 4. Configure health checks
54 configureHealthCheck(targetGroupArn, config.getHealthCheckConfig());
55
56 return loadBalancerArn;
57
58 } catch (Exception e) {
59 log.error("Failed to create Application Load Balancer: {}", config.getName(), e);
60 throw new RuntimeException("ALB creation failed", e);
61 }
62 }
63
64 private String createTargetGroup(ALBConfiguration config, String loadBalancerArn) {
65 try {
66 CreateTargetGroupRequest request = CreateTargetGroupRequest.builder()
67 .name(config.getName() + "-tg")
68 .protocol(ProtocolEnum.HTTP)
69 .port(config.getTargetPort())
70 .vpcId(config.getVpcId())
71 .targetType(config.getTargetType())
72 .healthCheckEnabled(true)
73 .healthCheckPath(config.getHealthCheckConfig().getPath())
74 .healthCheckProtocol(ProtocolEnum.HTTP)
75 .healthCheckPort("traffic-port")
76 .healthCheckIntervalSeconds(config.getHealthCheckConfig().getInterval())
77 .healthyThresholdCount(config.getHealthCheckConfig().getHealthyThreshold())
78 .unhealthyThresholdCount(config.getHealthCheckConfig().getUnhealthyThreshold())
79 .healthCheckTimeoutSeconds(config.getHealthCheckConfig().getTimeout())
80 .matcher(Matcher.builder()
81 .httpCode(config.getHealthCheckConfig().getSuccessCodes())
82 .build())
83 .tags(Tag.builder()
84 .key("LoadBalancer")
85 .value(loadBalancerArn)
86 .build())
87 .build();
88
89 CreateTargetGroupResponse response = elbClient.createTargetGroup(request);
90 String targetGroupArn = response.targetGroups().get(0).targetGroupArn();
91
92 log.info("Created target group: {} with ARN: {}", config.getName() + "-tg", targetGroupArn);
93 return targetGroupArn;
94
95 } catch (Exception e) {
96 log.error("Failed to create target group for ALB: {}", config.getName(), e);
97 throw new RuntimeException("Target group creation failed", e);
98 }
99 }
100
101 private void createListener(String loadBalancerArn, String targetGroupArn, ALBConfiguration config) {
102 try {
103 CreateListenerRequest.Builder requestBuilder = CreateListenerRequest.builder()
104 .loadBalancerArn(loadBalancerArn)
105 .protocol(ProtocolEnum.HTTP)
106 .port(80)
107 .defaultActions(Action.builder()
108 .type(ActionTypeEnum.FORWARD)
109 .targetGroupArn(targetGroupArn)
110 .build());
111
112 // Add HTTPS listener if SSL certificate is provided
113 if (config.getSslCertificateArn() != null) {
114 // Create HTTPS listener
115 CreateListenerRequest httpsRequest = CreateListenerRequest.builder()
116 .loadBalancerArn(loadBalancerArn)
117 .protocol(ProtocolEnum.HTTPS)
118 .port(443)
119 .certificates(Certificate.builder()
120 .certificateArn(config.getSslCertificateArn())
121 .build())
122 .sslPolicy(config.getSslPolicy())
123 .defaultActions(Action.builder()
124 .type(ActionTypeEnum.FORWARD)
125 .targetGroupArn(targetGroupArn)
126 .build())
127 .build();
128
129 elbClient.createListener(httpsRequest);
130
131 // Redirect HTTP to HTTPS
132 requestBuilder.defaultActions(Action.builder()
133 .type(ActionTypeEnum.REDIRECT)
134 .redirectConfig(RedirectActionConfig.builder()
135 .protocol("HTTPS")
136 .port("443")
137 .statusCode(HttpRedirectActionStatusCodeEnum.HTTP_301)
138 .build())
139 .build());
140 }
141
142 elbClient.createListener(requestBuilder.build());
143 log.info("Created listeners for ALB: {}", loadBalancerArn);
144
145 } catch (Exception e) {
146 log.error("Failed to create listeners for ALB: {}", loadBalancerArn, e);
147 throw new RuntimeException("Listener creation failed", e);
148 }
149 }
150
151 public void registerTargets(String targetGroupArn, List<String> targetIds) {
152 try {
153 List<TargetDescription> targets = targetIds.stream()
154 .map(id -> TargetDescription.builder()
155 .id(id)
156 .build())
157 .collect(Collectors.toList());
158
159 RegisterTargetsRequest request = RegisterTargetsRequest.builder()
160 .targetGroupArn(targetGroupArn)
161 .targets(targets)
162 .build();
163
164 elbClient.registerTargets(request);
165 log.info("Registered {} targets to target group: {}", targetIds.size(), targetGroupArn);
166
167 } catch (Exception e) {
168 log.error("Failed to register targets to target group: {}", targetGroupArn, e);
169 throw new RuntimeException("Target registration failed", e);
170 }
171 }
172
173 public void createAdvancedRoutingRules(String listenerArn, List<RoutingRule> rules) {
174 try {
175 List<Rule> listenerRules = new ArrayList<>();
176 int priority = 100;
177
178 for (RoutingRule rule : rules) {
179 Rule listenerRule = Rule.builder()
180 .priority(String.valueOf(priority++))
181 .conditions(createRuleConditions(rule))
182 .actions(createRuleActions(rule))
183 .build();
184
185 listenerRules.add(listenerRule);
186 }
187
188 CreateRuleRequest request = CreateRuleRequest.builder()
189 .listenerArn(listenerArn)
190 .priority(String.valueOf(priority))
191 .conditions(listenerRules.get(0).conditions())
192 .actions(listenerRules.get(0).actions())
193 .build();
194
195 for (Rule rule : listenerRules) {
196 CreateRuleRequest ruleRequest = CreateRuleRequest.builder()
197 .listenerArn(listenerArn)
198 .priority(rule.priority())
199 .conditions(rule.conditions())
200 .actions(rule.actions())
201 .build();
202
203 elbClient.createRule(ruleRequest);
204 }
205
206 log.info("Created {} advanced routing rules for listener: {}", rules.size(), listenerArn);
207
208 } catch (Exception e) {
209 log.error("Failed to create routing rules for listener: {}", listenerArn, e);
210 throw new RuntimeException("Rule creation failed", e);
211 }
212 }
213
214 private List<RuleCondition> createRuleConditions(RoutingRule rule) {
215 List<RuleCondition> conditions = new ArrayList<>();
216
217 if (rule.getPathPattern() != null) {
218 conditions.add(RuleCondition.builder()
219 .field("path-pattern")
220 .values(rule.getPathPattern())
221 .build());
222 }
223
224 if (rule.getHostHeader() != null) {
225 conditions.add(RuleCondition.builder()
226 .field("host-header")
227 .values(rule.getHostHeader())
228 .build());
229 }
230
231 if (rule.getHttpHeader() != null) {
232 conditions.add(RuleCondition.builder()
233 .field("http-header")
234 .httpHeaderConfig(HttpHeaderConditionConfig.builder()
235 .httpHeaderName(rule.getHttpHeader().getKey())
236 .values(rule.getHttpHeader().getValue())
237 .build())
238 .build());
239 }
240
241 if (rule.getQueryString() != null) {
242 conditions.add(RuleCondition.builder()
243 .field("query-string")
244 .queryStringConfig(QueryStringConditionConfig.builder()
245 .values(QueryStringKeyValuePair.builder()
246 .key(rule.getQueryString().getKey())
247 .value(rule.getQueryString().getValue())
248 .build())
249 .build())
250 .build());
251 }
252
253 return conditions;
254 }
255
256 private List<Action> createRuleActions(RoutingRule rule) {
257 List<Action> actions = new ArrayList<>();
258
259 switch (rule.getActionType()) {
260 case FORWARD:
261 actions.add(Action.builder()
262 .type(ActionTypeEnum.FORWARD)
263 .targetGroupArn(rule.getTargetGroupArn())
264 .build());
265 break;
266
267 case REDIRECT:
268 actions.add(Action.builder()
269 .type(ActionTypeEnum.REDIRECT)
270 .redirectConfig(RedirectActionConfig.builder()
271 .protocol(rule.getRedirectConfig().getProtocol())
272 .host(rule.getRedirectConfig().getHost())
273 .port(rule.getRedirectConfig().getPort())
274 .path(rule.getRedirectConfig().getPath())
275 .statusCode(HttpRedirectActionStatusCodeEnum.fromValue(rule.getRedirectConfig().getStatusCode()))
276 .build())
277 .build());
278 break;
279
280 case FIXED_RESPONSE:
281 actions.add(Action.builder()
282 .type(ActionTypeEnum.FIXED_RESPONSE)
283 .fixedResponseConfig(FixedResponseActionConfig.builder()
284 .statusCode(rule.getFixedResponse().getStatusCode())
285 .contentType(rule.getFixedResponse().getContentType())
286 .messageBody(rule.getFixedResponse().getMessageBody())
287 .build())
288 .build());
289 break;
290
291 case WEIGHTED_FORWARD:
292 actions.add(Action.builder()
293 .type(ActionTypeEnum.FORWARD)
294 .forwardConfig(ForwardActionConfig.builder()
295 .targetGroups(rule.getWeightedTargets().stream()
296 .map(wt -> TargetGroupTuple.builder()
297 .targetGroupArn(wt.getTargetGroupArn())
298 .weight(wt.getWeight())
299 .build())
300 .collect(Collectors.toList()))
301 .build())
302 .build());
303 break;
304 }
305
306 return actions;
307 }
308
309 private void configureHealthCheck(String targetGroupArn, HealthCheckConfig healthConfig) {
310 try {
311 ModifyTargetGroupRequest request = ModifyTargetGroupRequest.builder()
312 .targetGroupArn(targetGroupArn)
313 .healthCheckEnabled(true)
314 .healthCheckPath(healthConfig.getPath())
315 .healthCheckIntervalSeconds(healthConfig.getInterval())
316 .healthCheckTimeoutSeconds(healthConfig.getTimeout())
317 .healthyThresholdCount(healthConfig.getHealthyThreshold())
318 .unhealthyThresholdCount(healthConfig.getUnhealthyThreshold())
319 .matcher(Matcher.builder()
320 .httpCode(healthConfig.getSuccessCodes())
321 .build())
322 .build();
323
324 elbClient.modifyTargetGroup(request);
325 log.info("Configured health check for target group: {}", targetGroupArn);
326
327 } catch (Exception e) {
328 log.error("Failed to configure health check for target group: {}", targetGroupArn, e);
329 throw new RuntimeException("Health check configuration failed", e);
330 }
331 }
332
333 // Supporting configuration classes
334 public static class ALBConfiguration {
335 private String name;
336 private boolean internetFacing;
337 private IpAddressType ipAddressType = IpAddressType.IPV4;
338 private List<String> subnetIds;
339 private List<String> securityGroupIds;
340 private String vpcId;
341 private String environment;
342 private String applicationName;
343 private int targetPort = 80;
344 private TargetTypeEnum targetType = TargetTypeEnum.INSTANCE;
345 private String sslCertificateArn;
346 private String sslPolicy = "ELBSecurityPolicy-TLS-1-2-2017-01";
347 private HealthCheckConfig healthCheckConfig = new HealthCheckConfig();
348
349 // Constructors, getters, setters
350 public ALBConfiguration() {}
351
352 public ALBConfiguration(String name, List<String> subnetIds, List<String> securityGroupIds, String vpcId) {
353 this.name = name;
354 this.subnetIds = subnetIds;
355 this.securityGroupIds = securityGroupIds;
356 this.vpcId = vpcId;
357 this.internetFacing = true;
358 this.environment = "production";
359 }
360
361 // Getters and setters
362 public String getName() { return name; }
363 public void setName(String name) { this.name = name; }
364 public boolean isInternetFacing() { return internetFacing; }
365 public void setInternetFacing(boolean internetFacing) { this.internetFacing = internetFacing; }
366 public IpAddressType getIpAddressType() { return ipAddressType; }
367 public void setIpAddressType(IpAddressType ipAddressType) { this.ipAddressType = ipAddressType; }
368 public List<String> getSubnetIds() { return subnetIds; }
369 public void setSubnetIds(List<String> subnetIds) { this.subnetIds = subnetIds; }
370 public List<String> getSecurityGroupIds() { return securityGroupIds; }
371 public void setSecurityGroupIds(List<String> securityGroupIds) { this.securityGroupIds = securityGroupIds; }
372 public String getVpcId() { return vpcId; }
373 public void setVpcId(String vpcId) { this.vpcId = vpcId; }
374 public String getEnvironment() { return environment; }
375 public void setEnvironment(String environment) { this.environment = environment; }
376 public String getApplicationName() { return applicationName; }
377 public void setApplicationName(String applicationName) { this.applicationName = applicationName; }
378 public int getTargetPort() { return targetPort; }
379 public void setTargetPort(int targetPort) { this.targetPort = targetPort; }
380 public TargetTypeEnum getTargetType() { return targetType; }
381 public void setTargetType(TargetTypeEnum targetType) { this.targetType = targetType; }
382 public String getSslCertificateArn() { return sslCertificateArn; }
383 public void setSslCertificateArn(String sslCertificateArn) { this.sslCertificateArn = sslCertificateArn; }
384 public String getSslPolicy() { return sslPolicy; }
385 public void setSslPolicy(String sslPolicy) { this.sslPolicy = sslPolicy; }
386 public HealthCheckConfig getHealthCheckConfig() { return healthCheckConfig; }
387 public void setHealthCheckConfig(HealthCheckConfig healthCheckConfig) { this.healthCheckConfig = healthCheckConfig; }
388 }
389
390 public static class HealthCheckConfig {
391 private String path = "/health";
392 private int interval = 30;
393 private int timeout = 5;
394 private int healthyThreshold = 5;
395 private int unhealthyThreshold = 2;
396 private String successCodes = "200";
397
398 // Constructors, getters, setters
399 public HealthCheckConfig() {}
400
401 public String getPath() { return path; }
402 public void setPath(String path) { this.path = path; }
403 public int getInterval() { return interval; }
404 public void setInterval(int interval) { this.interval = interval; }
405 public int getTimeout() { return timeout; }
406 public void setTimeout(int timeout) { this.timeout = timeout; }
407 public int getHealthyThreshold() { return healthyThreshold; }
408 public void setHealthyThreshold(int healthyThreshold) { this.healthyThreshold = healthyThreshold; }
409 public int getUnhealthyThreshold() { return unhealthyThreshold; }
410 public void setUnhealthyThreshold(int unhealthyThreshold) { this.unhealthyThreshold = unhealthyThreshold; }
411 public String getSuccessCodes() { return successCodes; }
412 public void setSuccessCodes(String successCodes) { this.successCodes = successCodes; }
413 }
414
415 public static class RoutingRule {
416 private String pathPattern;
417 private String hostHeader;
418 private KeyValue httpHeader;
419 private KeyValue queryString;
420 private ActionType actionType;
421 private String targetGroupArn;
422 private RedirectConfig redirectConfig;
423 private FixedResponseConfig fixedResponse;
424 private List<WeightedTarget> weightedTargets;
425
426 public enum ActionType {
427 FORWARD, REDIRECT, FIXED_RESPONSE, WEIGHTED_FORWARD
428 }
429
430 // Constructors, getters, setters
431 public RoutingRule() {}
432
433 public String getPathPattern() { return pathPattern; }
434 public void setPathPattern(String pathPattern) { this.pathPattern = pathPattern; }
435 public String getHostHeader() { return hostHeader; }
436 public void setHostHeader(String hostHeader) { this.hostHeader = hostHeader; }
437 public KeyValue getHttpHeader() { return httpHeader; }
438 public void setHttpHeader(KeyValue httpHeader) { this.httpHeader = httpHeader; }
439 public KeyValue getQueryString() { return queryString; }
440 public void setQueryString(KeyValue queryString) { this.queryString = queryString; }
441 public ActionType getActionType() { return actionType; }
442 public void setActionType(ActionType actionType) { this.actionType = actionType; }
443 public String getTargetGroupArn() { return targetGroupArn; }
444 public void setTargetGroupArn(String targetGroupArn) { this.targetGroupArn = targetGroupArn; }
445 public RedirectConfig getRedirectConfig() { return redirectConfig; }
446 public void setRedirectConfig(RedirectConfig redirectConfig) { this.redirectConfig = redirectConfig; }
447 public FixedResponseConfig getFixedResponse() { return fixedResponse; }
448 public void setFixedResponse(FixedResponseConfig fixedResponse) { this.fixedResponse = fixedResponse; }
449 public List<WeightedTarget> getWeightedTargets() { return weightedTargets; }
450 public void setWeightedTargets(List<WeightedTarget> weightedTargets) { this.weightedTargets = weightedTargets; }
451 }
452
453 // Additional supporting classes...
454 public static class KeyValue {
455 private String key;
456 private String value;
457
458 public KeyValue() {}
459 public KeyValue(String key, String value) { this.key = key; this.value = value; }
460
461 public String getKey() { return key; }
462 public void setKey(String key) { this.key = key; }
463 public String getValue() { return value; }
464 public void setValue(String value) { this.value = value; }
465 }
466
467 public static class RedirectConfig {
468 private String protocol = "HTTPS";
469 private String host = "#{host}";
470 private String port = "443";
471 private String path = "/#{path}";
472 private String statusCode = "301";
473
474 // Constructors, getters, setters
475 public RedirectConfig() {}
476
477 public String getProtocol() { return protocol; }
478 public void setProtocol(String protocol) { this.protocol = protocol; }
479 public String getHost() { return host; }
480 public void setHost(String host) { this.host = host; }
481 public String getPort() { return port; }
482 public void setPort(String port) { this.port = port; }
483 public String getPath() { return path; }
484 public void setPath(String path) { this.path = path; }
485 public String getStatusCode() { return statusCode; }
486 public void setStatusCode(String statusCode) { this.statusCode = statusCode; }
487 }
488
489 public static class FixedResponseConfig {
490 private String statusCode = "200";
491 private String contentType = "text/plain";
492 private String messageBody = "OK";
493
494 // Constructors, getters, setters
495 public FixedResponseConfig() {}
496
497 public String getStatusCode() { return statusCode; }
498 public void setStatusCode(String statusCode) { this.statusCode = statusCode; }
499 public String getContentType() { return contentType; }
500 public void setContentType(String contentType) { this.contentType = contentType; }
501 public String getMessageBody() { return messageBody; }
502 public void setMessageBody(String messageBody) { this.messageBody = messageBody; }
503 }
504
505 public static class WeightedTarget {
506 private String targetGroupArn;
507 private Integer weight;
508
509 public WeightedTarget() {}
510 public WeightedTarget(String targetGroupArn, Integer weight) {
511 this.targetGroupArn = targetGroupArn;
512 this.weight = weight;
513 }
514
515 public String getTargetGroupArn() { return targetGroupArn; }
516 public void setTargetGroupArn(String targetGroupArn) { this.targetGroupArn = targetGroupArn; }
517 public Integer getWeight() { return weight; }
518 public void setWeight(Integer weight) { this.weight = weight; }
519 }
520}
🎯 ALB Use Cases
✅ When to Use ALB:
- Microservices architecture with path-based routing
- Modern web applications requiring HTTP/2 support
- Container workloads (ECS, EKS) with dynamic port mapping
- Lambda functions as targets
- Content-based routing based on headers, paths, or query strings
- User authentication integration needed
- WebSocket applications
❌ When NOT to Use ALB:
- Ultra-low latency requirements (use NLB instead)
- Non-HTTP protocols (TCP, UDP)
- Static IP address requirements
- Simple load balancing with no advanced features needed
🚀 Network Load Balancer (NLB)
📋 Overview and Features
Network Load Balancer operates at Layer 4 (Transport Layer) and is designed for ultra-high performance and low latency applications.
✅ Key Features:
- Ultra-low latency (microsecond-level)
- Handles millions of requests per second
- Static IP addresses and Elastic IP support
- Preserves source IP addresses
- TCP, UDP, and TLS protocol support
- Cross-zone load balancing available
- Flow hash algorithm for connection affinity
- Integration with PrivateLink
🛠️ NLB Implementation
1@Service
2@Slf4j
3public class NetworkLoadBalancerService {
4
5 private final ElasticLoadBalancingV2Client elbClient;
6 private final Ec2Client ec2Client;
7
8 public NetworkLoadBalancerService() {
9 this.elbClient = ElasticLoadBalancingV2Client.builder().build();
10 this.ec2Client = Ec2Client.builder().build();
11 }
12
13 public String createNetworkLoadBalancer(NLBConfiguration config) {
14 try {
15 // 1. Allocate Elastic IPs if needed
16 List<String> allocationIds = new ArrayList<>();
17 if (config.isUseStaticIps()) {
18 allocationIds = allocateElasticIPs(config.getSubnetIds().size());
19 }
20
21 // 2. Create load balancer
22 CreateLoadBalancerRequest.Builder requestBuilder = CreateLoadBalancerRequest.builder()
23 .name(config.getName())
24 .scheme(config.isInternetFacing() ? Scheme.INTERNET_FACING : Scheme.INTERNAL)
25 .type(LoadBalancerTypeEnum.NETWORK)
26 .ipAddressType(config.getIpAddressType());
27
28 // Configure subnets with static IPs if specified
29 if (config.isUseStaticIps() && !allocationIds.isEmpty()) {
30 List<SubnetMapping> subnetMappings = new ArrayList<>();
31 for (int i = 0; i < config.getSubnetIds().size(); i++) {
32 subnetMappings.add(SubnetMapping.builder()
33 .subnetId(config.getSubnetIds().get(i))
34 .allocationId(i < allocationIds.size() ? allocationIds.get(i) : null)
35 .build());
36 }
37 requestBuilder.subnetMappings(subnetMappings);
38 } else {
39 requestBuilder.subnets(config.getSubnetIds());
40 }
41
42 requestBuilder.tags(
43 Tag.builder().key("Environment").value(config.getEnvironment()).build(),
44 Tag.builder().key("Application").value(config.getApplicationName()).build(),
45 Tag.builder().key("Type").value("NetworkLoadBalancer").build()
46 );
47
48 CreateLoadBalancerResponse response = elbClient.createLoadBalancer(requestBuilder.build());
49 String loadBalancerArn = response.loadBalancers().get(0).loadBalancerArn();
50
51 log.info("Created Network Load Balancer: {} with ARN: {}", config.getName(), loadBalancerArn);
52
53 // 3. Create target group
54 String targetGroupArn = createNLBTargetGroup(config);
55
56 // 4. Create listener
57 createNLBListener(loadBalancerArn, targetGroupArn, config);
58
59 return loadBalancerArn;
60
61 } catch (Exception e) {
62 log.error("Failed to create Network Load Balancer: {}", config.getName(), e);
63 throw new RuntimeException("NLB creation failed", e);
64 }
65 }
66
67 private List<String> allocateElasticIPs(int count) {
68 List<String> allocationIds = new ArrayList<>();
69
70 for (int i = 0; i < count; i++) {
71 try {
72 AllocateAddressRequest request = AllocateAddressRequest.builder()
73 .domain(DomainType.VPC)
74 .build();
75
76 AllocateAddressResponse response = ec2Client.allocateAddress(request);
77 allocationIds.add(response.allocationId());
78
79 log.info("Allocated Elastic IP: {} ({})", response.publicIp(), response.allocationId());
80
81 } catch (Exception e) {
82 log.error("Failed to allocate Elastic IP", e);
83 throw new RuntimeException("Elastic IP allocation failed", e);
84 }
85 }
86
87 return allocationIds;
88 }
89
90 private String createNLBTargetGroup(NLBConfiguration config) {
91 try {
92 CreateTargetGroupRequest.Builder requestBuilder = CreateTargetGroupRequest.builder()
93 .name(config.getName() + "-nlb-tg")
94 .protocol(ProtocolEnum.fromValue(config.getProtocol().toUpperCase()))
95 .port(config.getTargetPort())
96 .vpcId(config.getVpcId())
97 .targetType(config.getTargetType())
98 .healthCheckEnabled(true)
99 .healthCheckProtocol(ProtocolEnum.fromValue(config.getHealthCheckProtocol().toUpperCase()))
100 .healthCheckPort("traffic-port")
101 .healthCheckIntervalSeconds(config.getHealthCheckInterval())
102 .healthyThresholdCount(config.getHealthyThreshold())
103 .unhealthyThresholdCount(config.getUnhealthyThreshold());
104
105 // Configure health check path for HTTP/HTTPS
106 if (config.getHealthCheckProtocol().equalsIgnoreCase("HTTP") ||
107 config.getHealthCheckProtocol().equalsIgnoreCase("HTTPS")) {
108 requestBuilder.healthCheckPath(config.getHealthCheckPath());
109 }
110
111 // Configure deregistration delay
112 requestBuilder.targetGroupAttributes(
113 TargetGroupAttribute.builder()
114 .key("deregistration_delay.timeout_seconds")
115 .value(String.valueOf(config.getDeregistrationDelay()))
116 .build(),
117 TargetGroupAttribute.builder()
118 .key("preserve_client_ip.enabled")
119 .value(String.valueOf(config.isPreserveClientIp()))
120 .build(),
121 TargetGroupAttribute.builder()
122 .key("proxy_protocol_v2.enabled")
123 .value(String.valueOf(config.isProxyProtocolV2()))
124 .build()
125 );
126
127 CreateTargetGroupResponse response = elbClient.createTargetGroup(requestBuilder.build());
128 String targetGroupArn = response.targetGroups().get(0).targetGroupArn();
129
130 log.info("Created NLB target group: {} with ARN: {}", config.getName() + "-nlb-tg", targetGroupArn);
131 return targetGroupArn;
132
133 } catch (Exception e) {
134 log.error("Failed to create NLB target group for: {}", config.getName(), e);
135 throw new RuntimeException("NLB target group creation failed", e);
136 }
137 }
138
139 private void createNLBListener(String loadBalancerArn, String targetGroupArn, NLBConfiguration config) {
140 try {
141 CreateListenerRequest.Builder requestBuilder = CreateListenerRequest.builder()
142 .loadBalancerArn(loadBalancerArn)
143 .protocol(ProtocolEnum.fromValue(config.getProtocol().toUpperCase()))
144 .port(config.getListenerPort())
145 .defaultActions(Action.builder()
146 .type(ActionTypeEnum.FORWARD)
147 .targetGroupArn(targetGroupArn)
148 .build());
149
150 // Add TLS configuration if needed
151 if (config.getProtocol().equalsIgnoreCase("TLS") && config.getSslCertificateArn() != null) {
152 requestBuilder.certificates(Certificate.builder()
153 .certificateArn(config.getSslCertificateArn())
154 .build());
155 requestBuilder.sslPolicy(config.getSslPolicy());
156 }
157
158 elbClient.createListener(requestBuilder.build());
159 log.info("Created NLB listener for port {} with protocol {}", config.getListenerPort(), config.getProtocol());
160
161 } catch (Exception e) {
162 log.error("Failed to create NLB listener for: {}", loadBalancerArn, e);
163 throw new RuntimeException("NLB listener creation failed", e);
164 }
165 }
166
167 public void enableCrossZoneLoadBalancing(String loadBalancerArn, boolean enabled) {
168 try {
169 ModifyLoadBalancerAttributesRequest request = ModifyLoadBalancerAttributesRequest.builder()
170 .loadBalancerArn(loadBalancerArn)
171 .attributes(LoadBalancerAttribute.builder()
172 .key("load_balancing.cross_zone.enabled")
173 .value(String.valueOf(enabled))
174 .build())
175 .build();
176
177 elbClient.modifyLoadBalancerAttributes(request);
178 log.info("Cross-zone load balancing {} for NLB: {}",
179 enabled ? "enabled" : "disabled", loadBalancerArn);
180
181 } catch (Exception e) {
182 log.error("Failed to modify cross-zone load balancing for NLB: {}", loadBalancerArn, e);
183 throw new RuntimeException("Cross-zone configuration failed", e);
184 }
185 }
186
187 public void configureConnectionIdle(String loadBalancerArn, int idleTimeoutSeconds) {
188 try {
189 ModifyLoadBalancerAttributesRequest request = ModifyLoadBalancerAttributesRequest.builder()
190 .loadBalancerArn(loadBalancerArn)
191 .attributes(LoadBalancerAttribute.builder()
192 .key("idle_timeout.timeout_seconds")
193 .value(String.valueOf(idleTimeoutSeconds))
194 .build())
195 .build();
196
197 elbClient.modifyLoadBalancerAttributes(request);
198 log.info("Configured idle timeout to {} seconds for NLB: {}", idleTimeoutSeconds, loadBalancerArn);
199
200 } catch (Exception e) {
201 log.error("Failed to configure idle timeout for NLB: {}", loadBalancerArn, e);
202 throw new RuntimeException("Idle timeout configuration failed", e);
203 }
204 }
205
206 // NLB Configuration class
207 public static class NLBConfiguration {
208 private String name;
209 private boolean internetFacing = true;
210 private IpAddressType ipAddressType = IpAddressType.IPV4;
211 private List<String> subnetIds;
212 private String vpcId;
213 private String environment = "production";
214 private String applicationName;
215 private String protocol = "TCP";
216 private int listenerPort = 80;
217 private int targetPort = 8080;
218 private TargetTypeEnum targetType = TargetTypeEnum.INSTANCE;
219 private boolean useStaticIps = false;
220 private String healthCheckProtocol = "TCP";
221 private String healthCheckPath = "/";
222 private int healthCheckInterval = 30;
223 private int healthyThreshold = 3;
224 private int unhealthyThreshold = 3;
225 private int deregistrationDelay = 300;
226 private boolean preserveClientIp = false;
227 private boolean proxyProtocolV2 = false;
228 private String sslCertificateArn;
229 private String sslPolicy = "ELBSecurityPolicy-TLS-1-2-2017-01";
230
231 // Constructors, getters, setters
232 public NLBConfiguration() {}
233
234 public NLBConfiguration(String name, List<String> subnetIds, String vpcId) {
235 this.name = name;
236 this.subnetIds = subnetIds;
237 this.vpcId = vpcId;
238 }
239
240 // All getters and setters
241 public String getName() { return name; }
242 public void setName(String name) { this.name = name; }
243 public boolean isInternetFacing() { return internetFacing; }
244 public void setInternetFacing(boolean internetFacing) { this.internetFacing = internetFacing; }
245 public IpAddressType getIpAddressType() { return ipAddressType; }
246 public void setIpAddressType(IpAddressType ipAddressType) { this.ipAddressType = ipAddressType; }
247 public List<String> getSubnetIds() { return subnetIds; }
248 public void setSubnetIds(List<String> subnetIds) { this.subnetIds = subnetIds; }
249 public String getVpcId() { return vpcId; }
250 public void setVpcId(String vpcId) { this.vpcId = vpcId; }
251 public String getEnvironment() { return environment; }
252 public void setEnvironment(String environment) { this.environment = environment; }
253 public String getApplicationName() { return applicationName; }
254 public void setApplicationName(String applicationName) { this.applicationName = applicationName; }
255 public String getProtocol() { return protocol; }
256 public void setProtocol(String protocol) { this.protocol = protocol; }
257 public int getListenerPort() { return listenerPort; }
258 public void setListenerPort(int listenerPort) { this.listenerPort = listenerPort; }
259 public int getTargetPort() { return targetPort; }
260 public void setTargetPort(int targetPort) { this.targetPort = targetPort; }
261 public TargetTypeEnum getTargetType() { return targetType; }
262 public void setTargetType(TargetTypeEnum targetType) { this.targetType = targetType; }
263 public boolean isUseStaticIps() { return useStaticIps; }
264 public void setUseStaticIps(boolean useStaticIps) { this.useStaticIps = useStaticIps; }
265 public String getHealthCheckProtocol() { return healthCheckProtocol; }
266 public void setHealthCheckProtocol(String healthCheckProtocol) { this.healthCheckProtocol = healthCheckProtocol; }
267 public String getHealthCheckPath() { return healthCheckPath; }
268 public void setHealthCheckPath(String healthCheckPath) { this.healthCheckPath = healthCheckPath; }
269 public int getHealthCheckInterval() { return healthCheckInterval; }
270 public void setHealthCheckInterval(int healthCheckInterval) { this.healthCheckInterval = healthCheckInterval; }
271 public int getHealthyThreshold() { return healthyThreshold; }
272 public void setHealthyThreshold(int healthyThreshold) { this.healthyThreshold = healthyThreshold; }
273 public int getUnhealthyThreshold() { return unhealthyThreshold; }
274 public void setUnhealthyThreshold(int unhealthyThreshold) { this.unhealthyThreshold = unhealthyThreshold; }
275 public int getDeregistrationDelay() { return deregistrationDelay; }
276 public void setDeregistrationDelay(int deregistrationDelay) { this.deregistrationDelay = deregistrationDelay; }
277 public boolean isPreserveClientIp() { return preserveClientIp; }
278 public void setPreserveClientIp(boolean preserveClientIp) { this.preserveClientIp = preserveClientIp; }
279 public boolean isProxyProtocolV2() { return proxyProtocolV2; }
280 public void setProxyProtocolV2(boolean proxyProtocolV2) { this.proxyProtocolV2 = proxyProtocolV2; }
281 public String getSslCertificateArn() { return sslCertificateArn; }
282 public void setSslCertificateArn(String sslCertificateArn) { this.sslCertificateArn = sslCertificateArn; }
283 public String getSslPolicy() { return sslPolicy; }
284 public void setSslPolicy(String sslPolicy) { this.sslPolicy = sslPolicy; }
285 }
286}
🎯 NLB Use Cases
✅ When to Use NLB:
- Ultra-low latency applications
- High-performance workloads (gaming, financial trading)
- TCP/UDP protocols (databases, custom protocols)
- Static IP addresses required
- Source IP preservation needed
- Extreme high throughput (millions of requests/second)
- Long-running connections
- PrivateLink integration
❌ When NOT to Use NLB:
- Content-based routing needed
- HTTP/HTTPS-specific features required
- WebSocket applications with advanced routing
- Lambda function targets
- User authentication integration needed
🛡️ Gateway Load Balancer (GWLB)
📋 Overview and Features
Gateway Load Balancer operates at Layer 3 (Network Layer) and is designed for deploying, scaling, and managing third-party network virtual appliances.
✅ Key Features:
- Third-party appliance integration (firewalls, intrusion detection)
- Transparent network gateway
- GENEVE protocol for traffic encapsulation
- Scalable virtual appliance deployment
- Source and destination IP preservation
- Symmetric flow routing
- Health checking for appliances
🛠️ GWLB Implementation
1@Service
2@Slf4j
3public class GatewayLoadBalancerService {
4
5 private final ElasticLoadBalancingV2Client elbClient;
6 private final Ec2Client ec2Client;
7
8 public GatewayLoadBalancerService() {
9 this.elbClient = ElasticLoadBalancingV2Client.builder().build();
10 this.ec2Client = Ec2Client.builder().build();
11 }
12
13 public String createGatewayLoadBalancer(GWLBConfiguration config) {
14 try {
15 // 1. Create Gateway Load Balancer
16 CreateLoadBalancerRequest request = CreateLoadBalancerRequest.builder()
17 .name(config.getName())
18 .type(LoadBalancerTypeEnum.GATEWAY)
19 .subnets(config.getSubnetIds())
20 .tags(
21 Tag.builder().key("Environment").value(config.getEnvironment()).build(),
22 Tag.builder().key("Application").value(config.getApplicationName()).build(),
23 Tag.builder().key("Type").value("GatewayLoadBalancer").build()
24 )
25 .build();
26
27 CreateLoadBalancerResponse response = elbClient.createLoadBalancer(request);
28 String loadBalancerArn = response.loadBalancers().get(0).loadBalancerArn();
29
30 log.info("Created Gateway Load Balancer: {} with ARN: {}", config.getName(), loadBalancerArn);
31
32 // 2. Create target group for virtual appliances
33 String targetGroupArn = createGWLBTargetGroup(config);
34
35 // 3. Create listener
36 createGWLBListener(loadBalancerArn, targetGroupArn, config);
37
38 return loadBalancerArn;
39
40 } catch (Exception e) {
41 log.error("Failed to create Gateway Load Balancer: {}", config.getName(), e);
42 throw new RuntimeException("GWLB creation failed", e);
43 }
44 }
45
46 private String createGWLBTargetGroup(GWLBConfiguration config) {
47 try {
48 CreateTargetGroupRequest request = CreateTargetGroupRequest.builder()
49 .name(config.getName() + "-gwlb-tg")
50 .protocol(ProtocolEnum.GENEVE)
51 .port(6081) // GENEVE default port
52 .vpcId(config.getVpcId())
53 .targetType(config.getTargetType())
54 .healthCheckEnabled(true)
55 .healthCheckProtocol(ProtocolEnum.fromValue(config.getHealthCheckProtocol().toUpperCase()))
56 .healthCheckPort(String.valueOf(config.getHealthCheckPort()))
57 .healthCheckIntervalSeconds(config.getHealthCheckInterval())
58 .healthyThresholdCount(config.getHealthyThreshold())
59 .unhealthyThresholdCount(config.getUnhealthyThreshold())
60 .targetGroupAttributes(
61 TargetGroupAttribute.builder()
62 .key("deregistration_delay.timeout_seconds")
63 .value(String.valueOf(config.getDeregistrationDelay()))
64 .build()
65 )
66 .build();
67
68 CreateTargetGroupResponse response = elbClient.createTargetGroup(request);
69 String targetGroupArn = response.targetGroups().get(0).targetGroupArn();
70
71 log.info("Created GWLB target group: {} with ARN: {}", config.getName() + "-gwlb-tg", targetGroupArn);
72 return targetGroupArn;
73
74 } catch (Exception e) {
75 log.error("Failed to create GWLB target group for: {}", config.getName(), e);
76 throw new RuntimeException("GWLB target group creation failed", e);
77 }
78 }
79
80 private void createGWLBListener(String loadBalancerArn, String targetGroupArn, GWLBConfiguration config) {
81 try {
82 CreateListenerRequest request = CreateListenerRequest.builder()
83 .loadBalancerArn(loadBalancerArn)
84 .defaultActions(Action.builder()
85 .type(ActionTypeEnum.FORWARD)
86 .targetGroupArn(targetGroupArn)
87 .build())
88 .build();
89
90 elbClient.createListener(request);
91 log.info("Created GWLB listener for: {}", loadBalancerArn);
92
93 } catch (Exception e) {
94 log.error("Failed to create GWLB listener for: {}", loadBalancerArn, e);
95 throw new RuntimeException("GWLB listener creation failed", e);
96 }
97 }
98
99 public void registerVirtualAppliances(String targetGroupArn, List<String> instanceIds) {
100 try {
101 List<TargetDescription> targets = instanceIds.stream()
102 .map(id -> TargetDescription.builder()
103 .id(id)
104 .build())
105 .collect(Collectors.toList());
106
107 RegisterTargetsRequest request = RegisterTargetsRequest.builder()
108 .targetGroupArn(targetGroupArn)
109 .targets(targets)
110 .build();
111
112 elbClient.registerTargets(request);
113 log.info("Registered {} virtual appliances to GWLB target group: {}", instanceIds.size(), targetGroupArn);
114
115 } catch (Exception e) {
116 log.error("Failed to register virtual appliances to target group: {}", targetGroupArn, e);
117 throw new RuntimeException("Virtual appliance registration failed", e);
118 }
119 }
120
121 // Create VPC Endpoint for GWLB service
122 public String createGWLBEndpoint(String gwlbArn, String vpcId, String subnetId, String routeTableId) {
123 try {
124 CreateVpcEndpointRequest request = CreateVpcEndpointRequest.builder()
125 .vpcId(vpcId)
126 .vpcEndpointType(VpcEndpointType.GATEWAY_LOAD_BALANCER)
127 .serviceName(extractServiceName(gwlbArn))
128 .subnetIds(subnetId)
129 .build();
130
131 CreateVpcEndpointResponse response = ec2Client.createVpcEndpoint(request);
132 String vpcEndpointId = response.vpcEndpoint().vpcEndpointId();
133
134 log.info("Created GWLB VPC Endpoint: {}", vpcEndpointId);
135
136 // Update route table to route traffic through GWLB endpoint
137 updateRouteTable(routeTableId, vpcEndpointId);
138
139 return vpcEndpointId;
140
141 } catch (Exception e) {
142 log.error("Failed to create GWLB VPC endpoint", e);
143 throw new RuntimeException("GWLB endpoint creation failed", e);
144 }
145 }
146
147 private String extractServiceName(String gwlbArn) {
148 // Extract service name from GWLB ARN for VPC endpoint
149 // Format: com.amazonaws.vpce.<region>.vpce-svc-<service-id>
150 String region = gwlbArn.split(":")[3];
151 String serviceId = gwlbArn.substring(gwlbArn.lastIndexOf("/") + 1);
152 return String.format("com.amazonaws.vpce.%s.vpce-svc-%s", region, serviceId);
153 }
154
155 private void updateRouteTable(String routeTableId, String vpcEndpointId) {
156 try {
157 CreateRouteRequest request = CreateRouteRequest.builder()
158 .routeTableId(routeTableId)
159 .destinationCidrBlock("0.0.0.0/0")
160 .vpcEndpointId(vpcEndpointId)
161 .build();
162
163 ec2Client.createRoute(request);
164 log.info("Updated route table {} to use GWLB endpoint: {}", routeTableId, vpcEndpointId);
165
166 } catch (Exception e) {
167 log.error("Failed to update route table: {}", routeTableId, e);
168 throw new RuntimeException("Route table update failed", e);
169 }
170 }
171
172 // GWLB Configuration class
173 public static class GWLBConfiguration {
174 private String name;
175 private List<String> subnetIds;
176 private String vpcId;
177 private String environment = "production";
178 private String applicationName;
179 private TargetTypeEnum targetType = TargetTypeEnum.INSTANCE;
180 private String healthCheckProtocol = "TCP";
181 private int healthCheckPort = 80;
182 private int healthCheckInterval = 30;
183 private int healthyThreshold = 3;
184 private int unhealthyThreshold = 3;
185 private int deregistrationDelay = 300;
186
187 // Constructors, getters, setters
188 public GWLBConfiguration() {}
189
190 public GWLBConfiguration(String name, List<String> subnetIds, String vpcId) {
191 this.name = name;
192 this.subnetIds = subnetIds;
193 this.vpcId = vpcId;
194 }
195
196 // All getters and setters
197 public String getName() { return name; }
198 public void setName(String name) { this.name = name; }
199 public List<String> getSubnetIds() { return subnetIds; }
200 public void setSubnetIds(List<String> subnetIds) { this.subnetIds = subnetIds; }
201 public String getVpcId() { return vpcId; }
202 public void setVpcId(String vpcId) { this.vpcId = vpcId; }
203 public String getEnvironment() { return environment; }
204 public void setEnvironment(String environment) { this.environment = environment; }
205 public String getApplicationName() { return applicationName; }
206 public void setApplicationName(String applicationName) { this.applicationName = applicationName; }
207 public TargetTypeEnum getTargetType() { return targetType; }
208 public void setTargetType(TargetTypeEnum targetType) { this.targetType = targetType; }
209 public String getHealthCheckProtocol() { return healthCheckProtocol; }
210 public void setHealthCheckProtocol(String healthCheckProtocol) { this.healthCheckProtocol = healthCheckProtocol; }
211 public int getHealthCheckPort() { return healthCheckPort; }
212 public void setHealthCheckPort(int healthCheckPort) { this.healthCheckPort = healthCheckPort; }
213 public int getHealthCheckInterval() { return healthCheckInterval; }
214 public void setHealthCheckInterval(int healthCheckInterval) { this.healthCheckInterval = healthCheckInterval; }
215 public int getHealthyThreshold() { return healthyThreshold; }
216 public void setHealthyThreshold(int healthyThreshold) { this.healthyThreshold = healthyThreshold; }
217 public int getUnhealthyThreshold() { return unhealthyThreshold; }
218 public void setUnhealthyThreshold(int unhealthyThreshold) { this.unhealthyThreshold = unhealthyThreshold; }
219 public int getDeregistrationDelay() { return deregistrationDelay; }
220 public void setDeregistrationDelay(int deregistrationDelay) { this.deregistrationDelay = deregistrationDelay; }
221 }
222}
🎯 GWLB Use Cases
✅ When to Use GWLB:
- Third-party security appliances (firewalls, IDS/IPS)
- Network function virtualization (NFV)
- Deep packet inspection requirements
- Transparent inline processing
- Centralized security inspection
- Compliance requirements for traffic inspection
❌ When NOT to Use GWLB:
- Basic load balancing needs
- Application-layer routing
- Direct application traffic distribution
- Simple high availability setups
📊 Complete Load Balancer Comparison
🔍 Detailed Feature Matrix
Feature | ALB | NLB | GWLB | CLB |
---|---|---|---|---|
OSI Layer | Layer 7 (Application) | Layer 4 (Transport) | Layer 3 (Network) | Layer 4/7 |
Protocols | HTTP, HTTPS, WebSocket | TCP, UDP, TLS | GENEVE | HTTP, HTTPS, TCP, SSL |
Target Types | Instance, IP, Lambda | Instance, IP, ALB | Instance, IP | Instance |
Static IP | ❌ No | ✅ Yes | ❌ No | ❌ No |
Content Routing | ✅ Yes | ❌ No | ❌ No | ❌ Limited |
WebSocket Support | ✅ Yes | ✅ Yes | ❌ No | ❌ No |
HTTP/2 Support | ✅ Yes | ❌ No | ❌ No | ❌ No |
Connection Draining | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
Cross-Zone LB | ✅ Always On | ⚠️ Optional | ❌ No | ⚠️ Optional |
Health Check Types | HTTP, HTTPS | TCP, HTTP, HTTPS | TCP, HTTP, HTTPS | TCP, HTTP, HTTPS |
SSL Termination | ✅ Yes | ✅ Yes (TLS) | ❌ No | ✅ Yes |
Source IP Preservation | ✅ Yes (headers) | ✅ Yes (native) | ✅ Yes | ❌ No |
Integration with WAF | ✅ Yes | ❌ No | ❌ No | ❌ No |
User Authentication | ✅ Yes | ❌ No | ❌ No | ❌ No |
Request Tracing | ✅ Yes | ❌ Limited | ❌ No | ❌ Limited |
Lambda Targets | ✅ Yes | ❌ No | ❌ No | ❌ No |
Container Support | ✅ Excellent | ✅ Good | ✅ Good | ⚠️ Limited |
Pricing Model | Per hour + LCU | Per hour + NLCU | Per hour + GLCU | Per hour + data |
Performance | High | Ultra-High | High | Medium |
Latency | ~100ms | ~1ms | ~10ms | ~100ms |
🎯 Use Case Decision Matrix
graph TD
A[Choose Load Balancer] --> B{What's your primary use case?}
B -->|Web Applications| C[Application Load Balancer]
B -->|High Performance/Gaming| D[Network Load Balancer]
B -->|Security Appliances| E[Gateway Load Balancer]
B -->|Legacy Apps| F[Classic Load Balancer]
C --> G{Advanced Routing Needed?}
G -->|Yes| H[✅ Use ALB<br/>Content-based routing<br/>Microservices<br/>Containers]
G -->|No| I{HTTP/2 or WebSocket?}
I -->|Yes| H
I -->|No| J[Consider NLB for performance]
D --> K{Need Static IPs?}
K -->|Yes| L[✅ Use NLB<br/>Static IP support<br/>Elastic IP integration]
K -->|No| M{Ultra-low latency required?}
M -->|Yes| L
M -->|No| N[Consider ALB for features]
E --> O[✅ Use GWLB<br/>Third-party appliances<br/>Security inspection<br/>NFV deployments]
F --> P[❌ Migrate to ALB/NLB<br/>CLB is deprecated<br/>Limited features]
style H fill:#2ecc71
style L fill:#e74c3c
style O fill:#f39c12
style P fill:#95a5a6
📈 Monitoring and Health Checks
🔍 Load Balancer Monitoring Service
1@Service
2@Slf4j
3public class LoadBalancerMonitoringService {
4
5 private final ElasticLoadBalancingV2Client elbClient;
6 private final CloudWatchClient cloudWatchClient;
7 private final MeterRegistry meterRegistry;
8
9 public LoadBalancerMonitoringService(MeterRegistry meterRegistry) {
10 this.elbClient = ElasticLoadBalancingV2Client.builder().build();
11 this.cloudWatchClient = CloudWatchClient.builder().build();
12 this.meterRegistry = meterRegistry;
13 }
14
15 @Scheduled(fixedRate = 60000) // Every minute
16 public void collectLoadBalancerMetrics() {
17 try {
18 // Get all load balancers
19 DescribeLoadBalancersResponse response = elbClient.describeLoadBalancers();
20
21 for (LoadBalancer lb : response.loadBalancers()) {
22 collectMetricsForLoadBalancer(lb);
23 collectTargetHealthMetrics(lb.loadBalancerArn());
24 }
25
26 } catch (Exception e) {
27 log.error("Failed to collect load balancer metrics", e);
28 }
29 }
30
31 private void collectMetricsForLoadBalancer(LoadBalancer lb) {
32 String lbName = lb.loadBalancerName();
33 LoadBalancerTypeEnum lbType = lb.type();
34
35 try {
36 // Request Count
37 collectCloudWatchMetric("RequestCount", lbName, lbType);
38
39 // Target Response Time
40 collectCloudWatchMetric("TargetResponseTime", lbName, lbType);
41
42 // HTTP Error Codes
43 if (lbType == LoadBalancerTypeEnum.APPLICATION) {
44 collectCloudWatchMetric("HTTPCode_Target_2XX_Count", lbName, lbType);
45 collectCloudWatchMetric("HTTPCode_Target_4XX_Count", lbName, lbType);
46 collectCloudWatchMetric("HTTPCode_Target_5XX_Count", lbName, lbType);
47 collectCloudWatchMetric("HTTPCode_ELB_4XX_Count", lbName, lbType);
48 collectCloudWatchMetric("HTTPCode_ELB_5XX_Count", lbName, lbType);
49 }
50
51 // Active Connection Count (for NLB)
52 if (lbType == LoadBalancerTypeEnum.NETWORK) {
53 collectCloudWatchMetric("ActiveFlowCount", lbName, lbType);
54 collectCloudWatchMetric("NewFlowCount", lbName, lbType);
55 collectCloudWatchMetric("ProcessedBytes", lbName, lbType);
56 }
57
58 } catch (Exception e) {
59 log.error("Failed to collect metrics for load balancer: {}", lbName, e);
60 }
61 }
62
63 private void collectCloudWatchMetric(String metricName, String lbName, LoadBalancerTypeEnum lbType) {
64 try {
65 String namespace = getNamespaceForLBType(lbType);
66
67 GetMetricStatisticsRequest request = GetMetricStatisticsRequest.builder()
68 .namespace(namespace)
69 .metricName(metricName)
70 .dimensions(Dimension.builder()
71 .name("LoadBalancer")
72 .value(lbName)
73 .build())
74 .startTime(Instant.now().minus(Duration.ofMinutes(5)))
75 .endTime(Instant.now())
76 .period(300) // 5 minutes
77 .statistics(Statistic.AVERAGE, Statistic.SUM, Statistic.MAXIMUM)
78 .build();
79
80 GetMetricStatisticsResponse response = cloudWatchClient.getMetricStatistics(request);
81
82 response.datapoints().forEach(datapoint -> {
83 if (datapoint.average() != null) {
84 Gauge.builder("aws.loadbalancer." + metricName.toLowerCase() + ".average")
85 .tag("load_balancer", lbName)
86 .tag("type", lbType.toString())
87 .register(meterRegistry, () -> datapoint.average());
88 }
89
90 if (datapoint.sum() != null) {
91 meterRegistry.counter("aws.loadbalancer." + metricName.toLowerCase() + ".total",
92 "load_balancer", lbName, "type", lbType.toString())
93 .increment(datapoint.sum());
94 }
95 });
96
97 } catch (Exception e) {
98 log.error("Failed to collect CloudWatch metric {} for LB: {}", metricName, lbName, e);
99 }
100 }
101
102 private void collectTargetHealthMetrics(String loadBalancerArn) {
103 try {
104 // Get target groups for this load balancer
105 DescribeTargetGroupsRequest request = DescribeTargetGroupsRequest.builder()
106 .loadBalancerArn(loadBalancerArn)
107 .build();
108
109 DescribeTargetGroupsResponse response = elbClient.describeTargetGroups(request);
110
111 for (TargetGroup tg : response.targetGroups()) {
112 collectTargetGroupHealthMetrics(tg);
113 }
114
115 } catch (Exception e) {
116 log.error("Failed to collect target health metrics for LB: {}", loadBalancerArn, e);
117 }
118 }
119
120 private void collectTargetGroupHealthMetrics(TargetGroup targetGroup) {
121 try {
122 DescribeTargetHealthRequest request = DescribeTargetHealthRequest.builder()
123 .targetGroupArn(targetGroup.targetGroupArn())
124 .build();
125
126 DescribeTargetHealthResponse response = elbClient.describeTargetHealth(request);
127
128 Map<String, Long> healthCounts = response.targetHealthDescriptions().stream()
129 .collect(Collectors.groupingBy(
130 thd -> thd.targetHealth().state().toString(),
131 Collectors.counting()
132 ));
133
134 String tgName = targetGroup.targetGroupName();
135
136 // Record target health metrics
137 healthCounts.forEach((state, count) ->
138 Gauge.builder("aws.loadbalancer.target.health")
139 .tag("target_group", tgName)
140 .tag("state", state)
141 .register(meterRegistry, () -> count.doubleValue())
142 );
143
144 // Calculate health percentage
145 long totalTargets = response.targetHealthDescriptions().size();
146 long healthyTargets = healthCounts.getOrDefault("healthy", 0L);
147 double healthPercentage = totalTargets > 0 ? (double) healthyTargets / totalTargets * 100 : 0;
148
149 Gauge.builder("aws.loadbalancer.target.health_percentage")
150 .tag("target_group", tgName)
151 .register(meterRegistry, () -> healthPercentage);
152
153 } catch (Exception e) {
154 log.error("Failed to collect target group health metrics for: {}", targetGroup.targetGroupName(), e);
155 }
156 }
157
158 private String getNamespaceForLBType(LoadBalancerTypeEnum lbType) {
159 switch (lbType) {
160 case APPLICATION:
161 return "AWS/ApplicationELB";
162 case NETWORK:
163 return "AWS/NetworkELB";
164 case GATEWAY:
165 return "AWS/GatewayELB";
166 default:
167 return "AWS/ELB";
168 }
169 }
170
171 public LoadBalancerHealthSummary getHealthSummary(String loadBalancerArn) {
172 try {
173 // Get load balancer details
174 DescribeLoadBalancersRequest lbRequest = DescribeLoadBalancersRequest.builder()
175 .loadBalancerArns(loadBalancerArn)
176 .build();
177
178 DescribeLoadBalancersResponse lbResponse = elbClient.describeLoadBalancers(lbRequest);
179 LoadBalancer lb = lbResponse.loadBalancers().get(0);
180
181 // Get target groups
182 DescribeTargetGroupsRequest tgRequest = DescribeTargetGroupsRequest.builder()
183 .loadBalancerArn(loadBalancerArn)
184 .build();
185
186 DescribeTargetGroupsResponse tgResponse = elbClient.describeTargetGroups(tgRequest);
187
188 List<TargetGroupHealth> targetGroupHealths = new ArrayList<>();
189
190 for (TargetGroup tg : tgResponse.targetGroups()) {
191 DescribeTargetHealthRequest thRequest = DescribeTargetHealthRequest.builder()
192 .targetGroupArn(tg.targetGroupArn())
193 .build();
194
195 DescribeTargetHealthResponse thResponse = elbClient.describeTargetHealth(thRequest);
196
197 long totalTargets = thResponse.targetHealthDescriptions().size();
198 long healthyTargets = thResponse.targetHealthDescriptions().stream()
199 .mapToLong(thd -> "healthy".equals(thd.targetHealth().state().toString()) ? 1 : 0)
200 .sum();
201
202 targetGroupHealths.add(new TargetGroupHealth(
203 tg.targetGroupName(),
204 totalTargets,
205 healthyTargets,
206 totalTargets > 0 ? (double) healthyTargets / totalTargets * 100 : 0
207 ));
208 }
209
210 return new LoadBalancerHealthSummary(
211 lb.loadBalancerName(),
212 lb.type().toString(),
213 lb.state().code().toString(),
214 targetGroupHealths,
215 Instant.now()
216 );
217
218 } catch (Exception e) {
219 log.error("Failed to get health summary for LB: {}", loadBalancerArn, e);
220 return null;
221 }
222 }
223
224 // Supporting classes for health monitoring
225 public static class LoadBalancerHealthSummary {
226 private final String loadBalancerName;
227 private final String type;
228 private final String state;
229 private final List<TargetGroupHealth> targetGroups;
230 private final Instant timestamp;
231
232 public LoadBalancerHealthSummary(String loadBalancerName, String type, String state,
233 List<TargetGroupHealth> targetGroups, Instant timestamp) {
234 this.loadBalancerName = loadBalancerName;
235 this.type = type;
236 this.state = state;
237 this.targetGroups = targetGroups;
238 this.timestamp = timestamp;
239 }
240
241 // Getters
242 public String getLoadBalancerName() { return loadBalancerName; }
243 public String getType() { return type; }
244 public String getState() { return state; }
245 public List<TargetGroupHealth> getTargetGroups() { return targetGroups; }
246 public Instant getTimestamp() { return timestamp; }
247
248 public boolean isHealthy() {
249 return "active".equals(state) &&
250 targetGroups.stream().allMatch(tg -> tg.getHealthPercentage() > 50);
251 }
252
253 @Override
254 public String toString() {
255 return String.format("LoadBalancerHealth{name='%s', type='%s', state='%s', healthy=%s, targetGroups=%d}",
256 loadBalancerName, type, state, isHealthy(), targetGroups.size());
257 }
258 }
259
260 public static class TargetGroupHealth {
261 private final String targetGroupName;
262 private final long totalTargets;
263 private final long healthyTargets;
264 private final double healthPercentage;
265
266 public TargetGroupHealth(String targetGroupName, long totalTargets, long healthyTargets, double healthPercentage) {
267 this.targetGroupName = targetGroupName;
268 this.totalTargets = totalTargets;
269 this.healthyTargets = healthyTargets;
270 this.healthPercentage = healthPercentage;
271 }
272
273 // Getters
274 public String getTargetGroupName() { return targetGroupName; }
275 public long getTotalTargets() { return totalTargets; }
276 public long getHealthyTargets() { return healthyTargets; }
277 public double getHealthPercentage() { return healthPercentage; }
278
279 @Override
280 public String toString() {
281 return String.format("TargetGroupHealth{name='%s', healthy=%d/%d (%.1f%%)}",
282 targetGroupName, healthyTargets, totalTargets, healthPercentage);
283 }
284 }
285}
🎯 Conclusion
AWS Load Balancers are essential components for building resilient, scalable, and high-performance applications in the cloud. Each type serves specific use cases and offers unique advantages:
🔑 Key Takeaways:
- Application Load Balancer (ALB): Best for modern web applications requiring advanced HTTP routing and features
- Network Load Balancer (NLB): Ideal for ultra-high performance, low latency, and TCP/UDP applications
- Gateway Load Balancer (GWLB): Perfect for third-party security appliances and network function virtualization
- Classic Load Balancer (CLB): Deprecated, migrate to ALB or NLB for better features and performance
📋 Selection Guidelines:
- For Web Applications: Start with ALB for HTTP/HTTPS traffic and advanced routing
- For High Performance: Choose NLB when latency and throughput are critical
- For Security Appliances: Use GWLB for transparent traffic inspection
- For Static IPs: NLB is the only option that supports static IP addresses
- For Containers/Lambda: ALB provides the best integration with modern compute services
🚀 Best Practices:
- Health Checks: Configure appropriate health checks for reliable traffic routing
- Monitoring: Implement comprehensive monitoring with CloudWatch and custom metrics
- Security: Use security groups, WAF integration, and SSL/TLS termination
- Cost Optimization: Choose the right load balancer type to avoid unnecessary costs
- High Availability: Deploy across multiple Availability Zones for fault tolerance
Understanding these differences enables you to architect robust, scalable, and cost-effective solutions that meet your specific application requirements and performance goals.