{"id":48249189,"url":"https://github.com/jjeanjacques10/rate-limit-hero-orders","last_synced_at":"2026-04-04T20:45:39.684Z","repository":{"id":338112709,"uuid":"1136637062","full_name":"jjeanjacques10/rate-limit-hero-orders","owner":"jjeanjacques10","description":"Aplicação que controla as solicitações de ajuda para super-heróis, utilizando AWS SQS para gerenciamento de filas e implementando diferentes estratégias de limitação de taxa (rate limiting) para o consumo das mensagens.","archived":false,"fork":false,"pushed_at":"2026-01-25T04:27:14.000Z","size":144,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-13T06:31:18.116Z","etag":null,"topics":["aws","rate-limiting","spring-boot","sqs"],"latest_commit_sha":null,"homepage":"https://jjeanjacques10.medium.com/resolvendo-problemas-de-rate-limiter-com-token-bucket-e-sem%C3%A1foros-f521dd1166ef","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jjeanjacques10.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-18T03:46:27.000Z","updated_at":"2026-02-09T03:12:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jjeanjacques10/rate-limit-hero-orders","commit_stats":null,"previous_names":["jjeanjacques10/rate-limit-hero-orders"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/jjeanjacques10/rate-limit-hero-orders","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjeanjacques10%2Frate-limit-hero-orders","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjeanjacques10%2Frate-limit-hero-orders/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjeanjacques10%2Frate-limit-hero-orders/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjeanjacques10%2Frate-limit-hero-orders/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jjeanjacques10","download_url":"https://codeload.github.com/jjeanjacques10/rate-limit-hero-orders/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjeanjacques10%2Frate-limit-hero-orders/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31413284,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T20:09:54.854Z","status":"ssl_error","status_checked_at":"2026-04-04T20:09:44.350Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","rate-limiting","spring-boot","sqs"],"created_at":"2026-04-04T20:45:39.010Z","updated_at":"2026-04-04T20:45:39.676Z","avatar_url":"https://github.com/jjeanjacques10.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🦸 My Hero Academia - Solicitações de Super-Heróis\n\nEste repositório contém o código e os recursos do projeto \"My Hero Academia - Solicitações de Super-Heróis\".\n\nUma aplicação que controla as solicitações de ajuda para super-heróis, utilizando AWS SQS para gerenciamento de filas e\nimplementando diferentes estratégias de limitação de taxa (rate limiting) para o consumo das mensagens.\n\n## Recursos\n\n- Integração com fila SQS para processamento de solicitações\n- Limitação de taxa de consumo com exemplos de consumo local e distribuído\n- Configurações flexíveis via profiles Spring\n\n## Tecnologias Utilizadas\n\n- 🍃 Spring Boot 3\n- ☕ Java 21\n- 📬 AWS SQS\n- 🔴 Redis\n- 🐳 Docker\n\n## Profiles\n\n- **spring.profiles.active:** Define o profile ativo para configurar o comportamento do consumidor SQS.\n\nex: `-Dspring.profiles.active=local-control` ou `-Dspring.profiles.active=distributed-semaphores` ou\n`-Dspring.profiles.active=distributed-token-bucket` ou `distributed-token-bucket4j`\n\n| Profile                    | Description                                                                                                                         |\n|----------------------------|-------------------------------------------------------------------------------------------------------------------------------------|\n| local-control              | Define as configurações para usar um controle local do consumo no SQS. Não recomendado para arquiteturas distribuídas.              |\n| distributed-semaphores     | Define as configurações para usar semáforos distribuídos no controle do consumo no SQS. Recomendado para arquiteturas distribuídas. |\n| distributed-token-bucket   | Define as configurações para usar token bucket distribuído no controle de taxa de consumo no SQS. Recomendado para rate limiting.   |\n| distributed-token-bucket4j | Define as configurações para usar token bucket com Bucket4j e Redis. Solução enterprise-ready para rate limiting distribuído.       |\n\n---\n\n## Configurações do Profile local-control\n\n\u003cdetails\u003e\n\u003csummary\u003eVeja as configurações do profile \u003cb\u003elocal-control\u003c/b\u003e\u003c/summary\u003e\n\n## Objetivo\n\nLimitar o processamento de mensagens SQS a **3 mensagens por vez** por consumidor, garantindo um controle mais rígido\nsobre o fluxo de mensagens a nível container.\n\n## Configurações Implementadas\n\n### 1. OrderConsumerLocalControl.kt\n\n```kotlin\n@SqsListener(\n    value = [\"event-hero-orders-queue\"],\n    maxConcurrentMessages = \"3\",\n    maxMessagesPerPoll = \"3\"\n)\nfun consumeMessage(message: Message\u003cHeroOrderRequest\u003e, acknowledgement: Acknowledgement) {\n    try {\n        orderService.processOrder(message.payload)\n        acknowledgement.acknowledge() // ACK manual apenas após sucesso\n    } catch (e: Exception) {\n        // Mensagem volta para a fila automaticamente\n    }\n}\n```\n\n**Parâmetros:**\n\n- `maxConcurrentMessages = \"3\"`: Número máximo de mensagens processadas simultaneamente\n- `maxMessagesPerPoll = \"3\"`: Número máximo de mensagens buscadas por polling\n- **Acknowledgement Manual**: Apenas mensagens processadas com sucesso são removidas da fila\n\n### 2. application-local-control.yml\n\n```yaml\nspring:\n  cloud:\n    aws:\n      sqs:\n        listener:\n          max-concurrent-messages: 3\n          max-messages-per-poll: 3\n          poll-timeout: 10\n          acknowledgement-mode: manual\n```\n\n**Configuração de acknowledgement manual** para controle preciso sobre quando as mensagens são removidas da fila SQS.\n\n### Vantagens\n\n✅ **Controle Preciso**: Mensagem só é removida da fila após processamento bem-sucedido  \n✅ **Retry Automático**: Falhas fazem a mensagem voltar para a fila automaticamente  \n✅ **Sem Perda de Dados**: Garante que nenhuma mensagem seja perdida em caso de erro\n\n\u003c/details\u003e\n\n## Configurações do Profile distributed-semaphores\n\n\u003cdetails\u003e\n\u003csummary\u003eVeja as configurações do profile \u003cb\u003edistributed-semaphores\u003c/b\u003e\u003c/summary\u003e\n\n## Objetivo\n\nLimitar o processamento de mensagens SQS a **10 mensagens por vez** independente do número de containers, utilizando\nsemáforos distribuídos para coordenar o consumo entre múltiplas instâncias.\n\n## Configurações Implementadas\n\n### 1. RedisDistributedSemaphore.kt\n\nServiço que gerencia o semáforo distribuído usando Redis:\n\n**Características:**\n\n- **MAX_PERMITS = 10**: Máximo de 10 mensagens processadas simultaneamente em todo o cluster\n- **Sorted Set do Redis**: Armazena os permits ativos com timestamp\n- **TTL de 60 segundos**: Cleanup automático de permits órfãos\n- **Race Condition Protection**: Verifica se o limite não foi excedido após adquirir\n\n### 2. OrderConsumerDistributedSemaphores.kt\n\nConsumer que utiliza o semáforo distribuído para controlar o processamento:\n\n```kotlin\n@SqsListener(value = [\"event-hero-orders-queue\"])\nfun consumeMessage(message: Message\u003cHeroOrderRequest\u003e, acknowledgement: Acknowledgement) {\n    var permitId: String? = null\n\n    try {\n        permitId = distributedSemaphore.tryAcquire()\n\n        if (permitId == null) {\n            // Sem permit disponível - mensagem volta para a fila\n            return\n        }\n\n        orderService.processOrder(message.payload)\n        acknowledgement.acknowledge() // ACK manual apenas após sucesso\n\n    } catch (e: Exception) {\n        // Erro no processamento - mensagem volta para a fila\n    } finally {\n        permitId?.let { distributedSemaphore.release(it) }\n    }\n}\n```\n\n**Comportamento:**\n\n- Tenta adquirir um permit antes de processar\n- Se não conseguir permit, **NÃO faz ACK** → mensagem volta para a fila\n- Se conseguir processar com sucesso, **faz ACK manual** → mensagem é removida da fila\n- Em caso de erro no processamento, **NÃO faz ACK** → mensagem volta para a fila\n- Sempre libera o permit no bloco finally\n\n### 3. application-distributed-semaphores.yml\n\n```yaml\nspring:\n  cloud:\n    aws:\n      sqs:\n        listener:\n          max-concurrent-messages: 20\n          max-messages-per-poll: 10\n          poll-timeout: 10\n          acknowledgement-mode: manual\n```\n\n**Parâmetros:**\n\n- `max-concurrent-messages = 20`: Permite até 20 threads de processamento por container\n- `max-messages-per-poll = 10`: Busca até 10 mensagens por polling\n- `acknowledgement-mode = manual`: Controle manual de quando fazer ACK das mensagens\n- O semáforo do Redis garante que apenas 10 mensagens sejam processadas em todo o cluster\n\n### 4. Redis Configuration\n\nRedis configurado com autenticação via password no docker-compose.yml e application.yml\n\n### Como Funciona\n\n1. **Container A** busca 10 mensagens da fila SQS\n2. Tenta processar todas, mas consegue apenas 6 permits do semáforo\n3. 4 mensagens falham e voltam para a fila (retry)\n4. **Container B** busca 10 mensagens\n5. Consegue apenas 4 permits (completando os 10 do cluster)\n6. 6 mensagens falham e voltam para a fila\n7. Quando Container A ou B terminam o processamento, liberam permits\n8. Novas mensagens podem então ser processadas\n\n### Vantagens\n\n✅ **Controle Global**: Limite de 10 mensagens independente do número de containers  \n✅ **Escalabilidade**: Adicione quantos containers quiser sem perder o controle  \n✅ **Fault Tolerance**: TTL automático limpa permits de containers que falharam  \n✅ **Retry Automático**: Mensagens sem permit ou com erro voltam para a fila automaticamente  \n✅ **Sem Perda de Dados**: ACK manual garante que apenas mensagens processadas com sucesso sejam removidas\n\n\u003c/details\u003e\n\n## Configurações do Profile distributed-token-bucket\n\n\u003cdetails\u003e\n\u003csummary\u003eVeja as configurações do profile \u003cb\u003edistributed-token-bucket\u003c/b\u003e\u003c/summary\u003e\n\n## Objetivo\n\nImplementar **rate limiting** usando o algoritmo **Token Bucket** distribuído com Redis, permitindo controlar a taxa de\nprocessamento de mensagens com suporte a **burst traffic** enquanto mantém uma taxa média estável.\n\n## Configurações Implementadas\n\n### 1. RedisDistributedTokenBucket.kt\n\nServiço que implementa o algoritmo Token Bucket distribuído usando Redis:\n\n**Características:**\n\n- **MAX_TOKENS = 10**: Capacidade máxima do bucket (permite burst de até 10 mensagens)\n- **REFILL_RATE = 2**: Taxa de reabastecimento (2 tokens por segundo)\n- **Auto Refill**: Tokens são automaticamente adicionados baseado no tempo decorrido\n- **Atomic Operations**: Usa operações atômicas do Redis para evitar race conditions\n- **TTL de 300 segundos**: Cleanup automático das chaves do Redis\n\n**Funcionamento:**\n\n```kotlin\nfun tryConsume(tokensNeeded: Int = 1): Boolean {\n    refillTokens() // Reabastece tokens baseado no tempo\n\n    val currentTokens = getCurrentTokens()\n    if (currentTokens \u003e= tokensNeeded) {\n        // Consome o token atomicamente\n        redisTemplate.opsForValue().decrement(TOKEN_BUCKET_KEY, tokensNeeded.toLong())\n        return true\n    }\n    return false\n}\n```\n\n### 2. OrderConsumerDistributedTokenBucket.kt\n\nConsumer que utiliza o token bucket para controlar o rate limiting:\n\n```kotlin\n@SqsListener(\n    value = [\"event-hero-orders-queue\"],\n    maxConcurrentMessages = \"3\",\n    maxMessagesPerPoll = \"3\",\n    acknowledgementMode = \"MANUAL\"\n)\nfun consumeMessage(message: Message\u003cHeroOrderRequest\u003e, acknowledgement: Acknowledgement) {\n    try {\n        if (!tokenBucket.tryConsume()) {\n            // Sem token disponível - mensagem volta para a fila\n            log.warn(\"No token available - message will return to queue\")\n            return\n        }\n\n        orderService.processOrder(message.payload)\n        acknowledgement.acknowledge() // ACK manual apenas após sucesso\n\n    } catch (e: Exception) {\n        // Erro no processamento - mensagem volta para a fila\n        log.error(\"Processing error - message will return to queue\", e)\n    }\n}\n```\n\n**Comportamento:**\n\n- Tenta consumir um token antes de processar\n- Se não houver token disponível, **NÃO faz ACK** → mensagem volta para a fila\n- Se conseguir processar com sucesso, **faz ACK manual** → mensagem é removida da fila\n- Em caso de erro no processamento, **NÃO faz ACK** → mensagem volta para a fila\n- Tokens são reabastecidos automaticamente a cada segundo (2 tokens/s)\n\n### 3. application-distributed-token-bucket.yml\n\n```yaml\nspring:\n  cloud:\n    aws:\n      sqs:\n        listener:\n          max-concurrent-messages: 5\n          max-messages-per-poll: 5\n          poll-timeout: 10\n```\n\n**Parâmetros:**\n\n- `max-concurrent-messages = 5`: Permite até 5 threads de processamento por container\n- `max-messages-per-poll = 5`: Busca até 5 mensagens por polling\n- `acknowledgement-mode = manual`: Controle manual de quando fazer ACK das mensagens\n- Token bucket garante taxa máxima de 2 mensagens/segundo com burst de até 10\n\n### Como Funciona - Exemplo de Cenário\n\n**Cenário 1: Tráfego em Burst**\n\n1. Sistema está ocioso - bucket tem 10 tokens cheios\n2. Chegam 10 mensagens de uma vez\n3. Todas as 10 são processadas imediatamente (burst permitido)\n4. Bucket fica vazio (0 tokens)\n5. Próximas mensagens precisam esperar o refill\n\n**Cenário 2: Taxa Sustentada**\n\n1. Bucket está vazio (0 tokens)\n2. A cada 0.5 segundos, 1 novo token é adicionado (2 tokens/segundo)\n3. Mensagens são processadas a uma taxa máxima de 2/segundo\n4. Sistema mantém throughput estável e controlado\n\n**Cenário 3: Múltiplos Containers**\n\n1. Container A e B compartilham o mesmo bucket no Redis\n2. Container A consome 5 tokens\n3. Container B pode consumir no máximo os 5 tokens restantes\n4. Ambos competem pelos tokens de forma distribuída\n5. Taxa global é mantida independente do número de containers\n\n### Vantagens do Token Bucket\n\n✅ **Rate Limiting Eficiente**: Controla a taxa de processamento de forma precisa  \n✅ **Suporte a Burst**: Permite picos de tráfego até o limite do bucket  \n✅ **Distribuído**: Funciona corretamente com múltiplos containers  \n✅ **Smooth Traffic**: Evita sobrecarga do sistema com throughput controlado  \n✅ **Auto Recovery**: Tokens são reabastecidos automaticamente ao longo do tempo  \n✅ **Retry Automático**: Mensagens sem token voltam para a fila automaticamente  \n✅ **Sem Perda de Dados**: ACK manual garante que apenas mensagens processadas com sucesso sejam removidas\n\n\u003c/details\u003e\n\n## Configurações do Profile distributed-token-bucket4j\n\n\u003cdetails\u003e\n\u003csummary\u003eVeja as configurações do profile \u003cb\u003edistributed-token-bucket4j\u003c/b\u003e\u003c/summary\u003e\n\n## Objetivo\n\nImplementar **rate limiting** usando a biblioteca **Bucket4j** com backend Redis, uma solução enterprise-ready e\notimizada para controlar a taxa de processamento de mensagens com suporte a **burst traffic** e alta performance.\n\n## Configurações Implementadas\n\n### 1. RedisDistributedTokenBucket4j.kt\n\nServiço que utiliza a biblioteca Bucket4j com Redis para implementar token bucket distribuído:\n\n**Características:**\n\n- **MAX_TOKENS = 10**: Capacidade máxima do bucket (permite burst de até 10 mensagens)\n- **REFILL_RATE = 2 tokens/segundo**: Taxa de reabastecimento automática\n- **Greedy Refill**: Tokens são reabastecidos de forma otimizada\n- **Lettuce Redis Client**: Cliente Redis de alta performance\n- **ProxyManager**: Gerenciamento distribuído de buckets com CAS (Compare-And-Set)\n- **Atomic Operations**: Operações atômicas garantidas pela biblioteca\n\n**Código:**\n\n```kotlin\n@Service\nclass RedisDistributedTokenBucket4j(\n    @Value(\"\\${spring.data.redis.host:localhost}\") private val redisHost: String,\n    @Value(\"\\${spring.data.redis.port:6379}\") private val redisPort: Int\n) {\n    private lateinit var bucket: Bucket\n\n    @PostConstruct\n    fun init() {\n        // Cria o cliente Redis Lettuce\n        redisClient = RedisClient.create(\"redis://$redisHost:$redisPort\")\n        connection = redisClient.connect(RedisCodec.of(StringCodec.UTF8, ByteArrayCodec.INSTANCE))\n\n        // Cria o ProxyManager do Bucket4j para Redis\n        proxyManager = LettuceBasedProxyManager.builderFor(connection).build()\n\n        // Configura o bucket com capacidade e taxa de refill\n        val bucketConfiguration = BucketConfiguration.builder()\n            .addLimit { limit -\u003e\n                limit.capacity(MAX_TOKENS)\n                    .refillGreedy(REFILL_TOKENS, Duration.ofSeconds(REFILL_PERIOD_SECONDS))\n            }\n            .build()\n\n        // Obtém ou cria o bucket distribuído\n        bucket = proxyManager.builder().build(BUCKET_KEY) { bucketConfiguration }\n    }\n\n    fun tryConsume(tokensNeeded: Long = 1): Boolean {\n        return bucket.tryConsume(tokensNeeded)\n    }\n}\n```\n\n### 2. OrderConsumerDistributedTokenBucket4j.kt\n\nConsumer que utiliza Bucket4j para controlar o rate limiting:\n\n```kotlin\n@Profile(\"distributed-token-bucket4j\")\n@Component\nclass OrderConsumerDistributedTokenBucket4j(\n    val orderService: OrderService,\n    val tokenBucket: RedisDistributedTokenBucket4j\n) {\n    @SqsListener(\n        value = [\"event-hero-orders-queue\"],\n        acknowledgementMode = \"MANUAL\"\n    )\n    fun consumeMessage(message: Message\u003cHeroOrderRequest\u003e, acknowledgement: Acknowledgement) {\n        try {\n            if (!tokenBucket.tryConsume()) {\n                // Sem token disponível - mensagem volta para a fila\n                return\n            }\n\n            orderService.processOrder(message.payload)\n            acknowledgement.acknowledge() // ACK manual apenas após sucesso\n\n        } catch (e: Exception) {\n            // Erro no processamento - mensagem volta para a fila\n        }\n    }\n}\n```\n\n### 3. application-distributed-token-bucket4j.yml\n\n```yaml\nspring:\n  cloud:\n    aws:\n      sqs:\n        listener:\n          max-concurrent-messages: 5\n          max-messages-per-poll: 5\n          poll-timeout: 10\n  data:\n    redis:\n      host: localhost\n      port: 6379\n\n# Bucket4j Token Bucket Configuration\n# Max Tokens: 10\n# Refill Rate: 2 tokens per second\n# This configuration uses Bucket4j with Redis for distributed rate limiting\n```\n\n### 4. Dependências Maven (pom.xml)\n\n```xml\n\u003c!-- Bucket4j for Token Bucket Rate Limiting --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.bucket4j\u003c/groupId\u003e\n    \u003cartifactId\u003ebucket4j-core\u003c/artifactId\u003e\n    \u003cversion\u003e8.10.1\u003c/version\u003e\n\u003c/dependency\u003e\n\u003cdependency\u003e\n\u003cgroupId\u003ecom.bucket4j\u003c/groupId\u003e\n\u003cartifactId\u003ebucket4j-redis\u003c/artifactId\u003e\n\u003cversion\u003e8.10.1\u003c/version\u003e\n\u003c/dependency\u003e\n\u003cdependency\u003e\n\u003cgroupId\u003eio.lettuce\u003c/groupId\u003e\n\u003cartifactId\u003elettuce-core\u003c/artifactId\u003e\n\u003c/dependency\u003e\n```\n\n### Como Funciona - Exemplo de Cenário\n\n**Cenário 1: Tráfego em Burst com Bucket4j**\n\n1. Sistema está ocioso - bucket tem 10 tokens cheios\n2. Chegam 15 mensagens de uma vez\n3. As primeiras 10 são processadas imediatamente (burst permitido)\n4. Bucket fica vazio (0 tokens)\n5. As 5 mensagens restantes voltam para a fila\n6. A cada 0.5 segundos, 1 novo token é adicionado (2 tokens/segundo)\n7. Mensagens na fila são reprocessadas conforme tokens ficam disponíveis\n\n**Cenário 2: Taxa Sustentada**\n\n1. Bucket está vazio (0 tokens)\n2. Bucket4j adiciona automaticamente 2 tokens por segundo\n3. Mensagens são processadas a uma taxa máxima de 2/segundo\n4. Sistema mantém throughput estável e controlado\n\n**Cenário 3: Múltiplos Containers com Alta Concorrência**\n\n1. 3 containers (A, B, C) compartilham o mesmo bucket no Redis\n2. Container A tenta consumir 4 tokens\n3. Container B tenta consumir 3 tokens ao mesmo tempo\n4. Container C tenta consumir 5 tokens simultaneamente\n5. Bucket4j garante atomicidade - apenas 10 tokens são consumidos no total\n6. Containers que não conseguiram tokens fazem suas mensagens voltarem para a fila\n7. Operações CAS (Compare-And-Set) do Redis evitam race conditions\n\n### Vantagens do Bucket4j\n\n✅ **Enterprise-Ready**: Biblioteca madura e amplamente testada em produção  \n✅ **Alta Performance**: Otimizações internas para operações distribuídas  \n✅ **Thread-Safe**: Operações atômicas garantidas mesmo em alta concorrência  \n✅ **Rate Limiting Preciso**: Algoritmo otimizado de token bucket  \n✅ **Suporte a Burst**: Permite picos de tráfego até o limite do bucket  \n✅ **Distribuído**: ProxyManager gerencia buckets compartilhados entre instâncias  \n✅ **Sem Race Conditions**: CAS (Compare-And-Set) previne condições de corrida  \n✅ **Monitoring Ready**: Métricas e estatísticas disponíveis via API  \n✅ **Flexível**: Suporta múltiplos limites e configurações avançadas  \n✅ **Retry Automático**: Mensagens sem token voltam para a fila automaticamente  \n✅ **Sem Perda de Dados**: ACK manual garante que apenas mensagens processadas com sucesso sejam removidas\n\n### Comparação: Token Bucket Manual vs Bucket4j\n\n| Aspecto                | Token Bucket Manual               | Bucket4j                           |\n|------------------------|-----------------------------------|------------------------------------|\n| **Implementação**      | Código customizado                | Biblioteca enterprise-ready        |\n| **Atomicidade**        | Operações Redis manuais           | CAS (Compare-And-Set) garantido    |\n| **Performance**        | Boa (depende da implementação)    | Otimizada para alta concorrência   |\n| **Race Conditions**    | Requer cuidado na implementação   | Automaticamente prevenido          |\n| **Complexidade**       | Média a alta                      | Baixa (API simples)                |\n| **Manutenibilidade**   | Requer manutenção do código       | Atualizado pela comunidade         |\n| **Recursos Avançados** | Limitados ao que você implementar | Múltiplos limites, bandwidth, etc. |\n| **Testes em Produção** | Depende dos seus testes           | Testado por milhares de empresas   |\n\n\u003c/details\u003e\n\n---\n\n### Diferença entre Semaphore vs Token Bucket vs Bucket4j\n\n| Aspecto                   | Distributed Semaphore                    | Token Bucket Manual                      | Token Bucket Bucket4j                   |\n|---------------------------|------------------------------------------|------------------------------------------|-----------------------------------------|\n| **Objetivo**              | Limitar concorrência                     | Limitar taxa (rate limiting)             | Limitar taxa (rate limiting)            |\n| **Controle**              | Número de processamentos simultâneos     | Taxa de processamento ao longo do tempo  | Taxa de processamento ao longo do tempo |\n| **Burst**                 | Limitado ao número de permits            | Suporta burst até o tamanho do bucket    | Suporta burst até o tamanho do bucket   |\n| **Refill**                | Não há refill automático                 | Refill automático baseado no tempo       | Refill automático otimizado             |\n| **Implementação**         | Código customizado                       | Código customizado                       | Biblioteca enterprise                   |\n| **Atomicidade**           | Sorted Set                               | Operações Redis manuais                  | CAS (Compare-And-Set)                   |\n| **Performance**           | Boa                                      | Boa                                      | Otimizada                               |\n| **Uso Ideal**             | Limitar carga em recursos compartilhados | Controlar throughput e evitar sobrecarga | Rate limiting em produção enterprise    |\n| **Risco de Concorrência** | Médio (depende da implementação)         | Médio (depende da implementação)         | Baixo (prevenido pela biblioteca)       |\n\n## Como Executar o Projeto\n\n1. Criar o ambiente local com [Docker Compose](local-environment/docker-compose.yml):\n\n``` bash\ncd local-environment\ndocker-compose up -d --build\n```\n\n2. Executar a aplicação Spring Boot com o profile desejado:\n\n``` bash\n./mvnw spring-boot:run -Dspring-boot.run.profiles=distributed-token-bucket\n``` \n\n3. Enviar mensagens para a fila SQS e observar o comportamento do consumidor conforme o profile\n   selecionado ([send-batch-message.sh](local-environment/localstack/test/send-batch-message.sh))\n\n``` bash\nsh local-environment/localstack/test/send-batch-message.sh\n```\n\n---\n\n## Licença\n\nEste projeto está licenciado sob a Licença MIT. Veja o arquivo [LICENSE](LICENSE) para mais detalhes.\n\n## Autor\n\nDesenvolvido por [Jean Jacques Barros](https://github.com/jjeanjacques10)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjjeanjacques10%2Frate-limit-hero-orders","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjjeanjacques10%2Frate-limit-hero-orders","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjjeanjacques10%2Frate-limit-hero-orders/lists"}