Concerns Overview
Plugins or Middleware Handlers that address all the cross-cutting concerns
Read More »
Audit Log
A built-in audit handler writes logs into audit.log file, which is set up in the logback appender. The end user can add more customized audit handlers if needed. For example, some customers write audit info into a relational database, while others write it into a Kafka topic.
In the audit module, there is AuditHandler which is generic and configurable with the audit.yml config file.
There is another audit provided by the light-4j framework called DumpHandler in the dump module.
Read More »
Body Handler
Introduction Body parser is a middleware handler designed for light-rest-4j only. It will parse the body to a list or map according to the content-type in the HTTP header for POST, PUT and PATCH HTTP methods. The content-type that can be parsed includes “application/json”, “text/plain”, “multipart/form-data’’ and “application/x-www-form-urlencoded”. The “application/json” type is parsed into a list or map depending on the first character of the body. The “text/plain” will be parsed into a String object.
Read More »
Client
Introduction The service-to-service communication can be done through a request/response style or messaging/event style in a microservices architecture. An efficient HTTP client is crucial in a request/response style as the number of interactions between services is high, and extra latency can kill the entire application performance, causing the failure of a microservices application.
In the early days of light-4j, we had a client module based on Apache HttpClient and Apache HttpAsyncClient, which supported HTTP 1.
Read More »
Cluster
This module caches all the service instances that are needed by the current service and calling underline registry(Direct, Consul and ZooKeeper) to discover the service if necessary (the first time a service is called, the registry notifies something has been changed regarding the subscription to services on Consul or ZooKeeper).
Interface In this module, we have an interface called Cluster.java
public interface Cluster { /** * give a service name and return a url with http or https url * the result is has been gone through the load balance with request key * * requestKey is used to control the behavior of load balance except * round robin and local first which this value is null.
Read More »
Config
Config is a configuration module that supports externalized config in the official standalone deployment or docker container. It is encouraged that every module should have its own configuration file and that these files be served by light-config-server which aggregates/merges config files from a different level of organization in GitHub or other git servers.
Introduction Externalized configuration from the application package is very important. It allows us to deploy the same package to the DEV/SIT/UAT/PROD environment with different configuration packages without reopening the delivery package.
Read More »
Consul Client
Consul is a service registry implementation that uses HashiCorp Consul as a registry and discovery server. It implements both registry and discovery in the same module for Consul communication. The server module is responsible for registering itself during startup and deregistering during shut down.
In some cases, if the server crashes, there is no chance for the server to invoke the deregister endpoint on the Consul agent. A health check must be configured to ensure that the Consul service catalog reflects the current status of the service instances.
Read More »
Correlation Id
CorrelationId handler is part of the traceability of microservices architecture along with the traceabilityId handler that is used to index centralized logs collected from all containerized services or the original client.
This is a middleware handler that checks if X-Correlation-Id exists in the request header. If it doesn’t exist it will generate a UUID and put it into the request header. During API to API calls, this header will be passed to the next API by the Client module.
Read More »
CORS
If your API server serves a SPA (single page application) built on top of Angular or React, there is no issue when the SPA accesses APIs on the same server. However, some of the single page applications are served by another server on another domain. In this case, the API server has to handle the pre-flight options request in order to allow browser clients to access the APIs directly. Also, it has to handle the subsequent requests with the Origin header to match it with the cors.
Read More »
Error Status
Introduction When deploying large-scale microservices in an organization, monitoring and alerting are very important for the operation team. The traditional way to monitor monolithic application logs to find potential error status is not feasible anymore. When all service logs are aggregated to the ELK or Splunk, we have a big melting pot of logging statements from different services. To dig useful information from it and identify problematic service instances is not an easy job.
Read More »
Exception Handler
This is a middleware handler that should be put in the beginning of the request/response chain. It wraps the entire chain so that any unhandled exceptions will finally reach here and to be handled gracefully. It is encouraged to handle exceptions in business handlers because the context is clear and the exchange will be terminated at the right place.
This handler is plugged in by default from light-codegen and it should be enabled on production as the last defence line.
Read More »
Handler
An interface for middleware handlers. All middleware handlers must implement this interface so that the handler can be plugged into the request/response chain during server startup with SPI (Service Provider Interface). The entire light-4j framework is a core server that provides a plugin structure for hooking up all sorts of plugins to handle different cross-cutting concerns.
The middleware handlers are designed based on the chain of responsibility pattern.
MiddlewareHandler /** * A interface for middleware handlers.
Read More »
Header Handler
When a request passes through a list of middleware handlers, chances are you want to update the request header or update the response header as part of the cross-cutting concerns. The HeaderHandler is designed for this. The very first use case is for light-proxy to update the Authorization header from Bearer token to Basic Authorization when connecting to downstream services. This allows light-proxy to verify the OAuth 2.0 JWT access token on the proxy and then change the same header to Basic so that the downstream services can be called from light-proxy.
Read More »
Health Check
This is a server health check handler that outputs OK or a JSON object to indicate the server is alive. Normally, it will be used by F5/light-gateway/http-sidecar to check if the server is healthy before routing requests to it. The global registry will also use the same handler to ensure all instances are healthy for consumers to discover. Another way to check server health is to ping the IP and port, and it is the standard way to check server status for F5 or any reverse proxy servers.
Read More »
Load Balance
The light-4j platform encourages client-side discovery in order to avoid proxies in front of multiple instances of services. This can reduce the network hop and subsequently reduce the latency of service calls.
Client-side discovery needs a client-side load balancer to pick up one and only one available service instance from a list of available services for a particular downstream request during runtime.
Currently, Round-Robin and LocalFirst have been implemented and ConsistentHashing is in progress.
Read More »
Logger Config
Logger-config is a module in the Light-4j framework that will be used to get the loggers and their current logging levels. It can also change the logging level for given loggers at runtime (Example: Change logging level to DEBUG for “com.networknt” logger for troubleshooting purposes). The user can also create a brand new logger with a level for debugging issues for a specific package or class on the target server.
Read More »
Mask
In the entire life cycle of the exchange, there might be a lot of logging statements written to log files or other persistence storage. These logs will be used to assist production issue identifying and resolving, and a broad group of people might have access to these logs. For confidentiality, sensitive info needs to be masked before logging, for example, credit card numbers, sin numbers, etc.
StarupHookProvider The mask module depends on JsonPath which is a third party library that gives us access to the JSON strings easily.
Read More »
Metrics
Introduction The metrics handler collects the API runtime information and reports it to Influxdb or Broadcom APM periodically (5 minutes to 15 minutes based on the volume of the API).
For general info about the metrics, please visit here.
The InfluxDB MetricsHandler is the first implementation and the default metrics handler in the light-4j frameworks.
Configuration Here is an example of configuration in values.yml
# metrics.yml metrics.enabled: true metrics.serverHost: localhost metrics.
Read More »
Rate Limit
Although our framework can potentially handle millions of requests per second, some public-facing APIs might be a good idea to enable this handler to limit the concurrent requests to a certain level to avoid DDoS attacks.
When the http-sidecar, light-router or light-proxy is used inside a corporate network for a slow backend API, this handler can be used to throttle the requests to protect the backend API from being overwhelmed.
Read More »
Registry Discovery
This module contains all the interfaces needed in registry and discovery. It also implements a direct registry, which you can hard-code services into the service.yml or direct-registry.yml to simulate Consul or Portal Registry during development. Although this is for local development, many users are still using it during production when they have allocated services to the exact IP and port on virtual machines.
Currently, Consul and portal-registry are supported for external service registry and discovery.
Read More »
Request and Response Dump
This is a handler that dumps the entire request and response into a log file. It should only be used in development mode for debugging purposes as it is very slow.
Introduction This handler can log HTTP request/response info based on configuration.
This is a generic dump handler that may be useful for troubleshooting in a developing/testing environment.
The dump request/response log file should be configured in logback.xml.
The dumping request/response info format can be default format or json format depending on the configuration.
Read More »
Sanitizer
Introduction This is a middleware handler that addresses cross-site scripting concerns. It encodes the header and body according to the configuration. As body encoding depends on BodyHandler middleware, it has to be plugged into the request/response chain after the body handler if the sanitizer.bodyEnabled is true in the values.yml
If you use the http-sidecar or light-gateway, the sanitizer handler will only work with the headers. The body sanitization won’t work as the request body won’t be intercepted but transferred to the backend API directly.
Read More »
Security
API security is paramount, and today most APIs don’t have security built-in at all but rely on third-party API gateways to handle the security at the network level. It assumes that it is safe within the organization or utilizes some firewall setup to ensure that only the Gateway server can access the service host.
Once we move to the cloud, everything is dynamic, and firewalls won’t work anymore as services can be down on one VM but start in another VM immediately through container orchestration tools.
Read More »
Server
This module is responsible for managing the life cycle of the embedded Undertow core HTTP server. It starts the server and initializes all middleware handlers/plugins along with a route handler provider when the handler chain is defined in the service.yml or OrchestrationHandler when the handler chains are defined in the handler.yml. It gracefully stops the server and allows the resources to be released and all in-flight requests to be processed before the server instance is deregistered on the service registry even someone clicks CTRL+C on the terminal.
Read More »
Server Info
Introduction Almost every module in light-4j has a configuration file externalized with default in the module itself or the API implementation config folder. A special handler injected in your hander.yml gives an overview of the server runtime, system properties, specification, and configurations for each enabled module. Once this handler endpoint is called, it will output all the server info in a JSON format.
Configuration info.yml
# Server info endpoint that can output environment and component along with configuration # Indicate if the server info is enable or not.
Read More »
Service
Why we reinvent the wheel While building a lightweight microservices platform, we need an IoC service to bind implementations to interfaces. Given light-4j has server startup and shutdown hooks, we usually only need to inject with a constructor injection during the server startup.
We have evaluated several IoC containers and found them to be too heavy for my use cases. Also, most of them are still using XML as configuration or annotations which eliminate the benefit of configurable IoC.
Read More »
Switcher
This module implement a switcher service interface and a local implementation. Switch is useful at system runtime to turn on or off some logic or service given certain conditions. For example, the light-4j server won’t stop handling requests but just switching off during server shutdown process. The service registry will be notified but in coming requests are still processed until all clients receives notification from service registry.
Read More »
Traceability
For microservices architecture, a request sent from a client may pass through several services to the backend repository/Book of Record, and then a response is returned in the reverse path. If there is an error in the call tree, we need to identify where the problem is during runtime. Also, for some mission-critical applications, the entire call tree must be in the audit log to meet regulatory compliance requirements, for example, banking applications.
Read More »
Utility
This module contains some useful classes that are shared by multiple modules within the light-* frameworks.
Constants Contains all the constants shared by all modules.
ModuleRegistry When the plugin modules are loaded, it will register itself to this module along with configuration. When /server/info is called, the endpoint will return all plugged in modules and their configurations.
Util Some useful utility method like uuid generator etc.
CollectionUtil Utility for collection
Read More »
Zookeeper
A Zookeeper registry implementation uses Zookeeper as a registry and discovery server. It implements both registry and discovery in the same module for Zookeeper communication. If the API/server is delivered as a docker image, another product called registrator will be used to register it with Zookeeper server. Otherwise, the server module will be responsible to register itself during startup.
Interface Here is the interface of ZooKeeper client.
public interface ZooKeeperClient { void subscribeStateChanges(IZkStateListener listener); java.
Read More »