Solon Cloud is a series of interface standards and configuration specifications. Solon Cloud provides a simple and convenient programming mode for common distributed system modes to help developers build elastic, reliable and coordinated applications. Solon Cloud is built on Solon, which makes it easy for developers to start and quickly apply it to production. Solon Cloud is mainly composed of three parts: interface definition and configuration specification, various plug-ins implementing relevant interface definitions, and general client.
Solon Cloud is very easy to connect with the self-developed framework. As long as the relevant interface definitions are implemented, a plug-in configured according to the specification is a Solomon cloud plug-in.
Solon Cloud project source code:
https://gitee.com/noear/solon
Solon Cloud sample source code:
https://gitee.com/noear/solon_cloud_demo
Feature 1: slim figure
The smallest Solon Cloud development unit is only 4m (including okhttp, mysql, redis, memcached, HikariCP and other clients or drivers)
Feature 2: faster
Native HelloWorld test, Qps up to 120000. For reference: helloworld_wrk_test
Feature 3: Code freedom
All abilities can be annotated or handwritten. On demand, free.
proposal
Enable your own single application to be deployed in multiple instances. It's a good start for distribution... Then switch to configuration services, then add event driven, split on demand... Take your time.
1, Solon Cloud suite content
(1) Interface definition and configuration specification list
The interface definition and configuration specification can provide a unified mode for the adaptation and use of different frameworks
Function name | Solon Cloud | Interface definition | Configuration specification (details omitted) |
Service registration and discovery | Solon Cloud Discovery | CloudDiscoveryService | solon.cloud.@@.discovery |
Inter service call mode | RPC or REST API or Event | - | - |
Service gateway | Solon Gateway | - | - |
Circuit breaker | Solon Cloud Breaker | CloudBreakerService | solon.cloud.@@.breaker |
Distributed configuration | Solon Cloud Config | CloudConfigService | solon.cloud.@@.config |
Service tracking | Solon Cloud Tracing | CloudTraceService | solon.cloud.@@.trace |
Event bus | Solon Cloud Event | CloudEventService | solon.cloud.@@.event |
Distributed task | Solon Cloud Job | CloudJobService | solon.cloud.@@.job |
Distributed ID | Solon Cloud Id | CloudIdService | solon.cloud.@@.id |
Distributed file | Solon Cloud File | CloudFileService | solon.cloud.@@.file |
Distributed list | Solon Cloud List | CloudListService | solon.cloud.@@.list |
Distributed lock | Solon Cloud Lock | CloudLockService | solon.cloud.@@.lock |
Distributed log | Solon Cloud Logging | CloudLogService | solon.cloud.@@.log |
(2) List of existing adapters
plug-in unit | explain |
External frame adaptation: | explain |
org.noear:consul-solon-plugin | Consumer adapter plug-in (supporting Solon cloud configuration service, registration and discovery service) |
org.noear:nacos-solon-plugin | nacos adapter plug-in (supporting Solon cloud configuration service, registration and discovery service) |
org.noear:zookeeper-solon-plugin | zookeeper adapter plug-in (supports Solon cloud configuration service, registration and discovery service) |
org.noear:water-solon-plugin | water adapter plug-in (supports Solon cloud configuration service, registration and discovery service, event bus service, log service, tracking service and lock service) |
org.noear:rabbitmq-solon-plugin | rabbitmq adapter plug-in (supporting Solon cloud event bus service) |
org.noear:rocketmq-solon-plugin | rocketmq adapter plug-in (supporting Solon cloud event bus service) |
org.noear:mqtt-solon-plugin | mqtt adapter plug-in (supporting Solon cloud event bus service) |
org.noear:kafka-solon-plugin | kafka adapter plug-in (supporting Solon cloud event bus service) |
org.noear:guava-solon-plugin | guava adapter plug-in (supporting Solon cloud disconnection service) |
org.noear:sentinel-solon-plugin | sentinel adapter plug-in (supporting Solon cloud disconnection service) |
org.noear:semaphore-solon-plugin | semaphore adapter plug-in (supporting Solon cloud disconnection service) |
org.noear:aliyun-oss-solon-plugin | Aliyun OSS adapter plug-in (supporting solo cloud distributed file service) |
org.noear:aws-s3-solon-plugin | aws-s3 adapter plug-in (supporting Solon cloud distributed file service) |
org.noear:snowflake-id-solon-plugin | snowflake algorithm adaptation plug-in (supporting solo cloud distributed ID service) |
(3) General client
The general client provides a unified user interface for all different frameworks and a free manual control mechanism.
//Get the configuration manually (no matter which configuration framework is behind it) Config val1 = CloudClient.config().pull(Solon.cfg().appGroup(), "demo.ds"); //Generate ID manually long val2 = CloudClient.id().generate(); //Manually publish events (no matter which message queue is behind it) CloudClient.event().publish(new Event("demo.user.login","1")); //Wait
2, Quick overview
(1)hello world
A common rest api that outputs hello world
public class DemoApp { public static void main(String[] args) { Solon.start(DemoApp.class, args, app->{ app.get("/", c -> c.output("Hello world!")); }); } }
(2) Using configuration services
Import the required distributed configuration through local configuration
solon.cloud.water: server: water config: load: "test.properties" #A configuration is loaded by default
Alternatively, use the @ CloudConfig annotation to generate beans
@Configuration public class Config { @Bean public DataSource ds(@CloudConfig("demo.ds") HikariDataSource ds){ return ds; } }
(3) Implementing RPC calls using registration and discovery services
Server
// // 1. All components with remoting = true are rpc services; // 2. Provide resource description in the form of uri to support both rest api and rpc modes // @Mapping("/rpc/") @Component(remoting = true) public class HelloServiceImpl implements HelloService{ @Override public String hello(String name) { return null; } }
client
@Controller public class HelloController { //Inject Rpc service agent (automatically obtain service cluster through discovery service) @NamiClient(name = "hellorpc", path = "/rpc/") HelloService helloService; public String hello(String name){ return helloService.hello(name); } }
(4) Use the Slf4j log interface to forward to the distributed logger
Solon Cloud Log emphasizes semantic tags (or solidified meta information). Through semantic tags, the logs are fixed indexed to achieve faster query results.
@Slf4j public class LogController { @Mapping("/") public String hello(String name){ //Solidify meta information into tag0... Tag4; Facilitate log indexing TagsMDC.tag0("user_"+name); //Equivalent to MDC.put("tag0", "user_"+name); log.info("There are users coming"); return name; } }
Note: you can also use logback For log service, you only need to eliminate it solon.logging.impl The framework can
(5) Business level expansion using distributed events
Two features of Solon Cloud Event:
- Self guard mode, i.e. continuous delayed retransmission after failure to ensure final success. This feature supports SAGA distributed transaction model.
- Multi channel mode, that is, different message queues coexist. This feature can be arranged differently according to business. For example, RabbitMQ is used for business messages and Mqtt is used for IoT messages.
For example, publish events
public class EventController { public void onUserRegistered(long user_id) { //After the user registration is completed, an event is published // CloudClient.event().publish( new Event("user.registered", String.format("{\"user_id\":%d}", user_id))); } }
Subscription and consumption events
@CloudEvent("user.registered") public class EventListen implements CloudEventHandler { @Override public boolean handler(Event event) throws Throwable { //After the user registration is completed, send a gold coin // return true; } }
(6) Use distributed list for IP restriction
public class ListController { public void hello(Context ctx){ String ip = IpUtils.getIP(ctx); if(CloudClient.list().inListOfIp("safelist", ip) == false){ return; } //Business processing } }
(7) Current limiting control with fuse
Add configuration (this configuration can be dynamically updated through configuration service)
solon.cloud.local: breaker: main: 100 #qps = 100
Add buried points through annotations
//The name of the buried point in the annotation here must correspond to the name of the configured circuit breaker one by one @CloudBreaker("main") public class BreakerController { @Mapping("/breaker") public void breaker(){ } }
(8) Get and propagate TraceId using tracking service
Pass to slf4j MDC through MDC
String traceId = CloudClient.trace().getTraceId(); MDC.put(CloudClient.trace().HEADER_TRACE_ID_NAME(), traceId);
Passed to the post Http node through the Http Header
HttpUtils.url("http://x.x.x.x") .headerAdd(CloudClient.trace().HEADER_TRACE_ID_NAME(), traceId).get();
Etc... (Solon Cloud Log supports CloudClient.trace() interface by default)
(9) Use distributed IDS to generate ordered non duplicate IDs
long log_id = CloudClient.id().generate();
(10) Use distributed locks to control traffic or resources
if(CloudClient.lock().lock("user_"+user_id, 3)){ //Try to lock a user for 3 seconds; Repeated submission without full line within 3 seconds }else{ //Requests are too frequent }
(11) Using distributed file services
//Use distributed files to store user extension information CloudClient.file().putText("solon/user_"+user_id, "{name:noear}")
(12) Use gateway to provide different outputs for the same set of interfaces
//Gateway 1 @Mapping("/api/rest/**") @Component public class ApiGateway extends Gateway { @Override protected void register() { //Set default render before(c -> c.attrSet("@render", "@json")); //Add service add("user", UserServiceImpl.class, true); } } //Gateway 2 @Mapping("/api/rpc/**") @Component public class RpcGateway extends Gateway { @Override protected void register() { //Set default render before(c -> c.attrSet("@render", "@type_json")); //Add a service (function without mapping; remoting = true is required to load it) add("user", UserServiceImpl.class, true); } }
3, Attachment: complete configuration
application.yml
solon.app: group: demo #Configure the default group used by the service name: helloapp #Application name used by discovery service solon.cloud.water: server: water #water service address config: load: "test.properties" #A configuration is loaded by default discovery: enable: true #When set to false, solo.cloud.local.discovery will take effect (generally used for local debugging) solon.cloud.local: discovery: service: hellorpc: - "http://localhost:7112 "# local service configuration breaker: main: 100
pom.xml (the following configuration size is only 4.7m)
<parent> <groupId>org.noear</groupId> <artifactId>solon-parent</artifactId> <version>1.3.32</version> </parent> <dependencies> <!-- RPC frame --> <dependency> <groupId>org.noear</groupId> <artifactId>solon-rpc</artifactId> </dependency> <!-- Configuration service, registration and discovery service, log service, lock service, list service and tracking service... (contain okhttp,redis,memcaced,HikariCP etc....) --> <dependency> <groupId>org.noear</groupId> <artifactId>water-solon-plugin</artifactId> </dependency> <!-- Breaking service --> <dependency> <groupId>org.noear</groupId> <artifactId>sentinel-solon-plugin</artifactId> </dependency> <!-- File service --> <dependency> <groupId>org.noear</groupId> <artifactId>aliyun-oss-solon-plugin</artifactId> </dependency> <!-- ID service --> <dependency> <groupId>org.noear</groupId> <artifactId>snowflake-id-solon-plugin</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency> </dependencies> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <compilerArgument>-parameters</compilerArgument> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <configuration> <finalName>${project.artifactId}</finalName> <appendAssemblyId>false</appendAssemblyId> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>demo.DemoApp</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>