|
| 1 | +# Http Connector |
| 2 | + |
| 3 | +## Introduction |
| 4 | +Http Connector is a tool for [flagd](https://github.com/open-feature/flagd) in-process resolver. |
| 5 | + |
| 6 | +This mode performs flag evaluations locally (in-process). |
| 7 | +Flag configurations for evaluation are obtained via Http. |
| 8 | + |
| 9 | +## Http Connector functionality |
| 10 | + |
| 11 | +HttpConnector is responsible for polling data from a specified URL at regular intervals. |
| 12 | +It is leveraging Http cache mechanism with 'ETag' header, then when receiving 304 Not Modified response, |
| 13 | +reducing traffic, reducing rate limits effects and changes updates. Can be enabled via useHttpCache option. |
| 14 | +The implementation is using Java HttpClient. |
| 15 | + |
| 16 | +## Use cases and benefits |
| 17 | +* flagd installation is not required, the Http Connector works independently. |
| 18 | + Minimizing infrastructure and DevOps overhead - no extra containers required. |
| 19 | +* Low latency by fetching data directly in-process. |
| 20 | +* Decreased external network traffic from the HTTP source, even without a standalone flagd container or proxy, |
| 21 | + when using polling cache. |
| 22 | +* Can serve as an additional provider for fallback or internal backup scenarios using a multi-provider setup. |
| 23 | + |
| 24 | +### What happens if the Http source is down during application startup? |
| 25 | + |
| 26 | +Http Connector supports optional resilient fail-safe initialization using a cache. |
| 27 | +If the initial fetch fails due to source unavailability, it can load the initial payload from the cache instead of |
| 28 | +falling back to default values. |
| 29 | +This ensures smoother startup behavior until the source becomes available again. To be effective, the TTL of the |
| 30 | +fallback cache should be longer than the expected duration of the source downtime during initialization. |
| 31 | + |
| 32 | +### Polling cache |
| 33 | +The polling cache is used to store the payload fetched from the URL. |
| 34 | +Used when usePollingCache is configured as true. |
| 35 | +A key advantage of this cache is that it enables a single microservice within a cluster to handle the polling of a |
| 36 | +URL, effectively acting as a flagd/proxy while all other services leverage the shared cache. |
| 37 | +This approach optimizes resource usage by preventing redundant polling across services. |
| 38 | + |
| 39 | +### Sample flows demonstrating the architecture |
| 40 | + |
| 41 | +#### Basic Simple Configuration |
| 42 | + |
| 43 | +This example demonstrates a simple flow using: |
| 44 | +- GitHub as the source for flag payload. |
| 45 | + |
| 46 | +```mermaid |
| 47 | +sequenceDiagram |
| 48 | + participant service |
| 49 | + participant Github |
| 50 | +
|
| 51 | + service->>Github: fetch |
| 52 | + Github->>service: payload |
| 53 | + Note right of service: polling interval passed |
| 54 | + service->>Github: fetch |
| 55 | + Github->>service: payload |
| 56 | +``` |
| 57 | + |
| 58 | +#### A More Scalable Configuration Utilizing Fail-Safe and Polling Caching Mechanisms |
| 59 | + |
| 60 | +This configuration aim to reduce network requests to the source URL, to improve performance and to improve the |
| 61 | +application's resilience to source downtime. |
| 62 | + |
| 63 | +This example demonstrates a micro-services architectural flow using: |
| 64 | +- GitHub as the source for flag payload. |
| 65 | +- Redis serving as both the fail-safe initialization cache and the polling cache. |
| 66 | + |
| 67 | +Example initialization flow during GitHub downtime, |
| 68 | +demonstrates how the application continues to access flag values from the cache even when GitHub is unavailable. |
| 69 | +In this setup, multiple microservices share the same cache, with only one service responsible for polling the source |
| 70 | +URL. |
| 71 | + |
| 72 | +```mermaid |
| 73 | +sequenceDiagram |
| 74 | + box Cluster |
| 75 | + participant micro-service-1 |
| 76 | + participant micro-service-2 |
| 77 | + participant micro-service-3 |
| 78 | + participant Redis |
| 79 | + end |
| 80 | + participant Github |
| 81 | + |
| 82 | + break source downtime |
| 83 | + micro-service-1->>Github: initialize |
| 84 | + Github->>micro-service-1: failure |
| 85 | + end |
| 86 | + micro-service-1->>Redis: fetch |
| 87 | + Redis->>micro-service-1: failsafe payload |
| 88 | + Note right of micro-service-1: polling interval passed |
| 89 | + micro-service-1->>Github: fetch |
| 90 | + Github->>micro-service-1: payload |
| 91 | + micro-service-2->>Redis: fetch |
| 92 | + Redis->>micro-service-2: payload |
| 93 | + micro-service-3->>Redis: fetch |
| 94 | + Redis->>micro-service-3: payload |
| 95 | +
|
| 96 | +``` |
| 97 | + |
| 98 | +## Usage |
| 99 | + |
| 100 | +### Installation |
| 101 | +<!-- x-release-please-start-version --> |
| 102 | +```xml |
| 103 | +<dependency> |
| 104 | + <groupId>dev.openfeature.contrib.tools</groupId> |
| 105 | + <artifactId>flagd-http-connector</artifactId> |
| 106 | + <version>0.0.1</version> |
| 107 | +</dependency> |
| 108 | +``` |
| 109 | +<!-- x-release-please-end-version --> |
| 110 | + |
| 111 | +### Usage example |
| 112 | + |
| 113 | +```java |
| 114 | +HttpConnectorOptions httpConnectorOptions = HttpConnectorOptions.builder() |
| 115 | + .url("http://example.com/flags") |
| 116 | + .build(); |
| 117 | +HttpConnector connector = HttpConnector.builder() |
| 118 | + .httpConnectorOptions(httpConnectorOptions) |
| 119 | + .build(); |
| 120 | + |
| 121 | +FlagdOptions options = |
| 122 | + FlagdOptions.builder() |
| 123 | + .resolverType(Config.Resolver.IN_PROCESS) |
| 124 | + .customConnector(connector) |
| 125 | + .build(); |
| 126 | + |
| 127 | +FlagdProvider flagdProvider = new FlagdProvider(options); |
| 128 | +``` |
| 129 | + |
| 130 | +#### HttpConnector using fail-safe cache and polling cache |
| 131 | + |
| 132 | +```java |
| 133 | +PayloadCache payloadCache = new PayloadCache() { |
| 134 | + |
| 135 | + @Override |
| 136 | + public void put(String key, String payload) { |
| 137 | + // implement put in cache |
| 138 | + } |
| 139 | + |
| 140 | + @Override |
| 141 | + public void put(String key, String payload, int ttlSeconds) { |
| 142 | + // implement put in cache with TTL |
| 143 | + } |
| 144 | + |
| 145 | + @Override |
| 146 | + public String get(String key) { |
| 147 | + // implement get from cache and return |
| 148 | + } |
| 149 | +}; |
| 150 | + |
| 151 | +HttpConnectorOptions httpConnectorOptions = HttpConnectorOptions.builder() |
| 152 | + .url(testUrl) |
| 153 | + .useHttpCache(true) |
| 154 | + .payloadCache(payloadCache) |
| 155 | + .payloadCacheOptions(PayloadCacheOptions.builder().build()) |
| 156 | + .useFailsafeCache(true) |
| 157 | + .pollIntervalSeconds(10) |
| 158 | + .usePollingCache(true) |
| 159 | + .build(); |
| 160 | + |
| 161 | +HttpConnector connector = HttpConnector.builder() |
| 162 | + .httpConnectorOptions(httpConnectorOptions) |
| 163 | + .build(); |
| 164 | +``` |
| 165 | + |
| 166 | +### Configuration |
| 167 | +The Http Connector can be configured using the following properties in the `HttpConnectorOptions` class.: |
| 168 | + |
| 169 | +| Property Name | Type | Description | |
| 170 | +|-------------------------------------------|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |
| 171 | +| url | String | The URL to poll for updates. This is a required field. | |
| 172 | +| pollIntervalSeconds | Integer | The interval in seconds at which the connector will poll the URL for updates. Default is 60 seconds. | |
| 173 | +| connectTimeoutSeconds | Integer | The timeout in seconds for establishing a connection to the URL. Default is 10 seconds. | |
| 174 | +| requestTimeoutSeconds | Integer | The timeout in seconds for the request to complete. Default is 10 seconds. | |
| 175 | +| linkedBlockingQueueCapacity | Integer | The capacity of the linked blocking queue used for processing requests. Default is 100. | |
| 176 | +| scheduledThreadPoolSize | Integer | The size of the scheduled thread pool used for processing requests. Default is 2. | |
| 177 | +| headers | Map<String, String> | A map of headers to be included in the request. Default is an empty map. | |
| 178 | +| httpClientExecutor | ExecutorService | The executor service used for making HTTP requests. Default is a fixed thread pool with 1 thread. | |
| 179 | +| proxyHost | String | The host of the proxy server to use for requests. Default is null. | |
| 180 | +| proxyPort | Integer | The port of the proxy server to use for requests. Default is null. | |
| 181 | +| payloadCacheOptions | PayloadCacheOptions | Options for configuring the payload cache. Default is null. | |
| 182 | +| payloadCache | PayloadCache | The payload cache to use for caching responses. Default is null. | |
| 183 | +| useHttpCache | Boolean | Whether to use HTTP caching for the requests. Default is false. | |
| 184 | +| useFailsafeCache | Boolean | Whether to use a failsafe cache for initialization. Default is false. | |
| 185 | +| usePollingCache | Boolean | Whether to use a polling cache for initialization. Default is false. | |
| 186 | +| PayloadCacheOptions.updateIntervalSeconds | Integer | The interval, in seconds, at which the cache is updated. By default, this is set to 30 minutes. The goal is to avoid overloading fallback cache writes, since the cache serves only as a fallback mechanism. Typically, this value can be tuned to be shorter than the cache's TTL, balancing the need to minimize unnecessary updates while still handling edge cases effectively. | |
0 commit comments