Designing a gateway from 0 to 1 Architecture construction of a self-developed gateway
Build the project skeleton
The IDE tool I use here is IDEA. From the above, we know that our project has about five modules, Client, Common, Register Center, Config Center and Core. 



Domain Model and DDD
Domain Model is a core concept in Domain-Driven Design (DDD), which is an abstract model used to represent and describe a specific domain. A domain model is a structured, object-oriented programming model for capturing and reflecting concepts, rules, and relationships in the actual business domain.
The advantages of a domain model are improved understanding of the business domain, increased modularity, and enhanced business rules, the disadvantages are the potential for increased complexity and development time, and the role is to realize business requirements and ensure that the software system is consistent with the business.
The role of domain modeling in software development includes:
Abstraction of Business Concepts: Domain modeling helps to abstract the various concepts and entities in the business domain into objects, classes and relationships in a programming language. This helps the development team to better understand the business requirements.
Representation of Business Rules: A domain model can contain business rules that can be represented in the model in the form of methods, attributes or constraints. This helps to ensure that the application follows the business rules.
Definition of Domain Objects: A domain model contains domain objects such as entities, value objects, aggregate roots, etc. that have business semantics and interact with other objects in the model.
Modeling of Business Processes: Domain models can be used to represent business processes, state transitions, and workflows. This helps developers to better understand and model business processes.
Separation of problem domain and solution: Domain modeling helps to separate the problem domain (business domain) from the solution domain (software development domain) so that developers can focus more on solving business problems.
Maintainability and Extensibility: The abstraction and clarity of the domain model makes the code easier to maintain and extend because it reflects the structure and rules of the business domain.
In short, the role of the domain model is to design for a specific business, and for this business, we will find out a lot of features related to this business, and if you change a business scenario, the current domain model may not be appropriate, you have to continue to design a new one. But for the current scenario, even if there are continuous requirements coming in, the domain model can ensure better usability because it is very well adapted to the business scenario in the previous design process.
And the design idea of domain model is probably:
- Find corresponding domain objects
- Create corresponding entities
- Setting up the corresponding link relationship for the entities
Then according to the above process, we know that, for our gateway project, after the service loading configuration is started, the gateway server receives the front-end request, after the request is parsed, the composition of the internal parameters in the internal flow of the gateway, such as serialization after a set of filters filtered, forwarded to the back-end service, the back-end service to process the request, the results of the gateway to return to the client. After the service loading configuration is started, the gateway server receives the front-end request, parses the request, and then composes the internal parameters to flow inside the gateway, for example, after serialization is filtered by a set of filters, it is forwarded to the back-end service, and after the back-end service handles the request, the result is returned to the client by the gateway. So we can get the following domain objects: Context, Request, Response, Config, Processor, Filter, FilterChain, Rule, HTTP request object.
After getting the domain object, we can start to set the corresponding entity object. For example, our Request should have some request time, parameters, id number, etc., Response should have the return value, status code and other information. And a Context context, is a complete request object processing.
So we probably also came up with the connection between the entities, that is: Context contains Request and Response.
Core Context Model Encapsulation
The encapsulation of the core Context model involves the following steps:
- Context context core definition
- BaseContext base context implementation
- Context parameters
- GatewayRequest implementation
- GatewayResponse implementation
- Rule, FilterConfig implementation
- Final GatewayContext implementation
We start by defining an abstract class that defines some core functional actions. After the design is complete the code will look roughly as follows: 
Static configuration loading
After that we need to start writing some classes and methods to load the configuration of our gateway. Here are the configuration class details, which simply provide some information about the configuration class.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class GatewayConfig {
private int port = 8080;
private String applicationName = "blossom-gateway";
private String registryAddress = "localhost:8848";
private String env = "dev";
private int eventLoopGroupBossNum = 1;
private int eventLoopGroupWorkerNum = Runtime.getRuntime().availableProcessors();
private int maxContentLength = 64 * 1024 * 1024;
private boolean oddEvenAsync = false;
}
And the following provides configuration loading methods, respectively, from the configuration file, environment variables, JVM parameters, runtime parameters for loading configuration information.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94package blossom.gateway.core.config;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.util.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
public class ConfigLoader {
public static final String CONFIG_FILE = "gateway.properties";
public static final String ENV_PREFIX = "GATEWAY_";
public static final String JVM_PREFIX = "gateway.";
private static final ConfigLoader INSTANCE = new ConfigLoader();
private GatewayConfig config;
private ConfigLoader() {
}
public static ConfigLoader getInstance() {
return INSTANCE;
}
public static GatewayConfig getConfig() {
return INSTANCE.config;
}
public GatewayConfig load(String[] args) {
config = new GatewayConfig();
loadFromConfigFile();
loadFromEnv();
loadFromJvm();
loadFromRuntimeArgs(args);
return config;
}
private void loadFromRuntimeArgs(String[] args) {
if (ArrayUtils.isNotEmpty(args)) {
Properties properties = new Properties();
for (String arg : args) {
if (arg.startsWith("--") && arg.contains("=")) {
properties.put(arg.substring(2, arg.indexOf("=")), arg.substring(arg.indexOf("=") + 1));
}
}
BeanUtil.copyProperties(properties, config);
}
}
private void loadFromJvm() {
Properties properties = System.getProperties();
BeanUtil.copyProperties(properties, config);
}
private void loadFromEnv() {
Map env = System.getenv();
Properties properties = new Properties();
properties.putAll(env);
BeanUtil.copyProperties(properties, config);
}
private void loadFromConfigFile() {
InputStream stream = ConfigLoader.class.getClassLoader().getResourceAsStream(CONFIG_FILE);
if (Objects.nonNull(stream)) {
Properties properties = new Properties();
try {
properties.load(stream);
BeanUtil.copyProperties(properties, config);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
stream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
Component Lifecycle
The lifecycle piece is as simple as defining an interface that provides methods for initialization, startup, and shutdown.1
2
3
4
5
6
7
8
9public interface LifeCycle {
void init();
void start();
void shutdown();
}