Muscle and Fitness Server
Muscle and Fitness Server a Spring Cloud microservice based, DDD structured, back-end server for managing data of muscle and fitness.
Features
Here is the highlights of Muscle and Fitness Server:
-
Each microservice is organized by Domain Driven Design (DDD) structure.
-
Based on Java - and Kotlin - , built by Gradle multi-module management . Inherited from the most modern and newest Spring frameworks:
org.springframework.boot:spring-boot-starter-parent
-org.springframework.cloud:spring-cloud-dependencies
- -
Spring Cloud Feature:
- Consul - Service registration and discovery.
- Spring Cloud Gateway - API Gateway on top of Spring WebFlux. Provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.
- Spring Cloud OpenFeign - Declarative REST Client: Feign creates a dynamic implementation of an interface decorated with JAX-RS or Spring MVC annotations. Enhanced connection by Okhttp 3.
- Spring Boot Admin - Admin UI for administration of spring boot applications.
- Zipkin - a distributed tracing system. It helps gather timing data needed to troubleshoot latency problems in service architectures.
-
Customized Spring Cloud Starter for traditional Spring MVC and Reactive Spring WebFlux microservice. Encapsulated a bunch of libraries and dependencies. Developer can import those dependencies by demand.
- For Spring MVC, spring-cloud-starter
- For Spring WebFlux, reactive-spring-cloud-starter
-
Advocate 𝛌 Java Functional Programming, provide developers with powerful and useful functions to make Java more sweeter.
-
Secured API. RBAC by API gateway and Auth Center. JWT authentication, and RBAC authorization.
-
MySQL Replication for High Availability. ShardingSphere as database access middleware to boost the database capacity better.
-
Multi data source managed by ShardingSphere, including main, replica and Quartz 3 data sources.
-
Dynamic SQL read-write isolation and table sharding provided by ShardingSphere.
-
MyBatis-Plus is the integrated ORM library.
-
ĺ…‰ HikariCP is the database connection pool.
-
TODO: Dynamically enhance connection pool size by CPU count (logical processor count). Read more at How to Find the Optimal Database Connection Pool Size, Sizing the Connection Pool.
-
-
Redis 6.x support. Master-slave replication for high availability. Redis cluster.
-
Docker, Rancher Kubernetes support. Google JIB for building production-ready Docker container images.
-
OSS service, based on Minio and SFTP integration. Asynchronous Progressive Download resources. Chunked resource upload. The media player will play back that content using sequential byte-range requests. Refers to a request for partial content (HTTP 206). This type of request is typically used to retrieve a large asset in smaller segments. This technique is employed by HTTP Progressive Download to avoid long buffering times.
-
STOMP over WebSocket (SockJS), real time messaging, based on RabbitMQ STOMP message broker.
-
Messaging with RabbitMQ, also supports delayed message, provided by RabbitMQ Delayed Message Plugin
-
Quartz support. Distributed job scheduling, based on JDBC. Dynamic Quartz job configuration, served by served by database configuration table
quartz_job_configuration
. Reduce lots of Quartz job and trigger boilerplate codes. -
Multi-environment support.
-
Knife4j API visualization. Enhanced Swagger API documentation.
-
Async log output. Log file compressed by standard GNU zip (gzip) compression algorithm. ELK log aggregation.
-
PMD code quality check for each every CI (during Maven verify phase), with Alibaba-p3c rulesets. -
JaCoCo for JUnit code coverage.
-
JVM log configuration for JVM garbage collection.
-
AOP based request log, configurable for turning on or off.
-
Customized method argument validation.
-
Docker container log persistence, Size and time based rolling policy. Daily rollover (at midnight 12 am) with automatic GZIP compression of the archived files.
-
Customized startup banner.
Architecture
Usage
-
Clone or download this project.
$ git clone https://github.com/johnnymillergh/muscle-and-fitness-server.git
-
Build with newest IntelliJ IDEA.
-
Click the green triangle to Run.
Useful Commands
Gradle
-
Compilation:
$ gradle classes testClasses
-
Execute unit tests, see also Difference Between Gradle Test and Check:
$ gradle test
-
Build artifacts:
$ gradle clean build
-
Build and push Docker images:
$ gradle clean build jib
Maven (deprecated)
-
Compile:
$ mvn clean validate compile --batch-mode --show-version --quiet -f pom.xml
-
Package:
$ mvn clean package -Djunit.jupiter.execution.parallel.enabled=true --batch-mode --show-version --quiet -f pom.xml
-
Set Version:
$ mvn versions:set -DgenerateBackupPoms=false -f pom.xml
-
Build Docker Images:
$ mvn clean verify --batch-mode --show-version --quiet -f pom.xml
Conventional Changelog CLI
-
Install global dependencies (optional if installed):
$ npm install -g conventional-changelog-cli
-
This will not overwrite any previous changelogs. The above generates a changelog based on commits since the last semver tag that matches the pattern of “Feature”, “Fix”, “Performance Improvement” or “Breaking Changes”.
$ conventional-changelog -p angular -i CHANGELOG.md -s
-
If this is your first time using this tool and you want to generate all previous changelogs, you could do:
$ conventional-changelog -p angular -i CHANGELOG.md -s -r 0
𝛌 Example
-
Require the expression to be true, otherwise throws an exception (if provided).
import com.jmsoftware.maf.springcloudstarter.function.* requireTrue(1 != 1) { anotherBoolean: Boolean? -> log.info("aBoolean = $anotherBoolean") } .orElseThrow { IllegalArgumentException("aBoolean is expected to be true") }
import static com.jmsoftware.maf.springcloudstarter.function.BooleanCheck.requireTrue; requireTrue(1 != 1, anotherBoolean -> log.info("aBoolean = {}", anotherBoolean)) .orElseThrow(() -> new IllegalArgumentException("aBoolean is expected to be true"));
-
Make Function have cache ability.
val cacheMap = mutableMapOf("key1" to "1", "key2" to "2") val stringProcess = Function { input: String -> log.info("No cache return value found. input: $input Re-calculating…") StrUtil.subSuf(input, 3) } val result1 = cacheFunction(stringProcess, "key1", cacheMap) val result2 = cacheFunction(stringProcess, "key2", cacheMap) val result3 = cacheFunction(stringProcess, "key3", cacheMap) assertEquals("1", result1) assertEquals("2", result2) assertEquals("3", result3) assertEquals(3, cacheMap.size)
val cacheMap = Maps.<String, String>newHashMap(); cacheMap.put("key1", "1"); cacheMap.put("key2", "2"); final Function<String, String> stringProcess = input -> { log.info("No cache return value found. input: {} Re-calculating…", input); return StrUtil.subSuf(input, 3); }; val result1 = cacheFunction(stringProcess, "key1", cacheMap); val result2 = cacheFunction(stringProcess, "key2", cacheMap); val result3 = cacheFunction(stringProcess, "key3", cacheMap); assertEquals("1", result1); assertEquals("2", result2); assertEquals("3", result3); assertEquals(3, cacheMap.size);
CI (Continuous Integration)
- GitHub Actions is for building and publishing Docker images, also checking dependency updates and tests.
Travis CI is for publishing Docker Hub images of SNAPSHOT and RELEASE.
Maintainers
Contributing
Feel free to dive in! Open an issue.
Contributors
This project exists thanks to all the people who contribute.
- Johnny Miller [@johnnymillergh]
- …
Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]
License
Apache License © Johnny Miller
2020 - Present