') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - bryanxtong/LearnMicroservicesWithSpringBoot-Kafka: A sample project to demonstrate microservices with spring cloud, including consul, micrometer,zipkin,kafka and spring cloud gateway · GitHub
Skip to content

Repository files navigation

Learn Microservices with Spring Boot 3 - (Spring Cloud and Kafka)

This repository contains the source code of the practical use case described in the book Learn Microservices with Spring Boot 3 (3rd Edition). And I made some changes to logback kafka appender to add headers https://github.com/danielwegener/logback-kafka-appender and add micrometer zipkin trace support.

Features

The figure below shows a high-level overview of the final version of our system.

Logical View - Chapter 8 (Final)

The main concepts included in this project are:

  • Why do we need Centralized Logs and Distributed tracing?
  • Why would I create Docker images for my applications?
  • Building a simple logger application with Spring Boot and Kafka using logback-kafka-appender.
  • Distributed traces with Micrometer and Zipkin.
  • Building Docker images for Spring Boot applications with Cloud Native Buildpacks.
  • Container Platforms, Application Platforms, and Cloud Services.

Running the app

Building the images yourself

First, build the application images with:

multiplication$ ./mvnw spring-boot:build-image
gamification$ ./mvnw spring-boot:build-image
gateway$ ./mvnw spring-boot:build-image
logs$ ./mvnw spring-boot:build-image

or

multiplication$ docker build -t multiplication:0.0.1-SNAPSHOT .
gamification$ docker build -t gamification:0.0.1-SNAPSHOT .
gateway$ docker build -t gateway:0.0.1-SNAPSHOT .
logs$ docker build -t logs:0.0.1-SNAPSHOT .

Then, build the consul importer from the docker/consul folder:

$ consul agent -node=learnmicro -dev
docker/consul$ consul kv export config/ > consul-kv-docker.json
docker/consul$ docker build -t consul-importer:1.0 .

And the UI server (first you have to build it with npm run build):

challenges-frontend$ npm install
challenges-frontend$ npm run build
challenges-frontend$ docker build -t challenges-frontend:1.0 .

Once you have all the images ready, run:

docker$ docker-compose up

See the figure below for a diagram showing the container view.

Container View

Once the backend and the frontend are started, you can navigate to http://localhost:3000 in your browser and start resolving multiplication challenges.

Playing with Docker Compose

After the system is up and running, you can quickly scale up and down instances of both Multiplication and Gamification services. For example, you can run:

docker$ docker-compose up --scale multiplication=2 --scale gamification=2

And you'll get two instances of each of these services with proper Load Balancing and Service Discovery.

About

A sample project to demonstrate microservices with spring cloud, including consul, micrometer,zipkin,kafka and spring cloud gateway

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages