Dieser Artikel zeigt ein Beispiel für das Erhöhen der lokalen Entwicklungsumgebung mit Docker Compose, Consul, Make für die Spring Boot-Anwendung (und nicht nur), z. B. mit PostgreSQL und Browserless.
Plan:
- Konfigurieren von Diensten in Docker Compose
- Registrierung von Diensten in Consul'e und Hinzufügen von Variablen zum Consul'a-Repository
- Makefile erstellen
- PostgreSQL-Konfiguration
- FeignClient verwenden
- Fazit
Die Anwendung ist absolut nutzlos: Wenn Sie einem Link zu einer Seite folgen, wird ein Link zum größten Bild dieser Seite zurückgegeben. Das Bild wird von Browserless abgerufen und in PostgreSQL wird dieser Fall gespeichert.
Link zum Projekt: https://bitbucket.org/maximka777/consul-docker-spring-cloud/src/master/ .
1. Einrichten von Diensten in Docker Compose
Als erstes erstellen Sie eine Konfigurationsdatei docker-compose.yml
für Docker-Container:
touch docker-compose.yml
Diese Datei enthält die Version von Docker-Compose:
version: '3.4'
Netzwerkkonfiguration:
networks: lan:
Und die Konfiguration der notwendigen Dienste, in diesem Fall Consul, Browserless und PostgreSQL:
services: consul: image: consul:1.1.0 hostname: localhost networks: - lan ports: - 8500:8500 postgres: image: postgres:11.0 hostname: localhost networks: - lan ports: - 5432:5432 environment: POSTGRES_PASSWORD: password POSTGRES_DB: example_app browserless: image: browserless/chrome hostname: localhost networks: - lan ports: - 3000:3000
POSTGRES_PASSWORD
- Passwort für die Benutzerdatenbank standardmäßig postgres
, POSTGRES_DB
- automatisch erstellte Datenbank im Container.
Um die Dienste zu starten, müssen Sie den folgenden Befehl ausführen:
docker-compose up
Wir warten auf das Ende des Ladens von Containerbildern und des Startens von Containern. Verwenden Sie den docker-compose down
, um die Ausführung von Containern zu stoppen. Nachdem Sie alle Container gestartet haben, können Sie im localhost:8500
Browser zur Adresse gehen localhost:8500
- Der Consul-Webclient sollte geöffnet werden (Abb. 1).

Abbildung 1
2. Registrierung von Diensten in Consul'e und Hinzufügen von Variablen zum Speicher von Consul'a
Sie können Dienste in Consul registrieren, indem Sie mehrere Post-Requests an die localhost:8500/v1/agent/service/register
Adresse senden localhost:8500/v1/agent/service/register
, z. B. mithilfe von curl.
Fügen Sie alle Curl-Aufrufe in das Bash-Skript ein.
chmod +x register-services.sh
- um die Datei ausführbar zu machen.
Nachdem das Skript ausgeführt wurde, werden PostgreSQSL und Browserless in der Liste der registrierten Dienste in Consule'e angezeigt (Abb. 2).

Abbildung 2
Die Abbildung zeigt, dass die PostgreSQL-Prüfung mit einem Fehler fehlschlägt - (dies hat keinen Einfluss auf das Wesentliche) .
Fügen Sie die Konfiguration dem Schlüssel- / Wertspeicher von Consul hinzu. Erstellen Sie die Variable test.property
im Verzeichnis example.app
:
curl --request PUT --data TEST \ localhost:8500/v1/kv/example.app/test.property
Wenn es viele Variablen gibt, ist es besser, ein Bash-Skript zu verwenden.
3. Erstellen eines Makefiles
Um den Start all dessen zu vereinfachen, schreiben Sie Makefile`:
docker_up: @docker-compose up -d consul_up: @./register-services.sh && \ ./register-variables.sh compile: @cd example.app && mvn package run: @cd example.app && java -jar target/example.app-1.0-SNAPSHOT.jar up: docker_up consul_up compile run down: @docker-compose down
Warnung: Makefile
verwendet eine spezielle Art von Einrückung!
Der Befehl make up
startet die gesamte Umgebung.
4. PostgreSQL-Konfiguration
Als Nächstes wurde mit dem Spring Boot-Anwendungsinitialisierer https://start.spring.io/ ein grundlegendes Spring Boot-Projekt (Maven) generiert.
Die folgenden Abhängigkeiten wurden zu pom.xml
hinzugefügt:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-config</artifactId> <version>2.0.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> <version>2.0.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency>
Aus den Namen der Pakete geht hervor, warum sie benötigt werden.
Schreiben wir die Konfiguration für die DataSource. Löschen Sie in der Datei bootstrap.properties
die Konfigurationen:
spring.cloud.consul.host=localhost spring.cloud.consul.port=8500 spring.cloud.consul.config.enabled=true spring.cloud.consul.config.prefix= spring.cloud.consul.config.defaultContext=example.app spring.cloud.consul.discovery.register=false spring.cloud.service-registry.auto-registration.enabled=false spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect spring.jpa.show-sql=false spring.jpa.hibernate.ddl-auto=create
In application.yml
:
example.app: db: name: 'example_app' feign: client: config: default: connectTimeout: 20000 readTimeout: 20000 loggerLevel: basic management: endpoint: health: show-details: always endpoints: web.exposure: include: '*'
Und die Konfigurationsklasse selbst:
@Configuration public class PersistenceConfiguration { @Value("${example.app.db.name}") private String databaseName; @Autowired private DiscoveryClient discoveryClient; @Bean @Primary public DataSource dataSource() { var postgresInstance = getPostgresInstance(); return DataSourceBuilder .create() .username("postgres") .password("password") .url(format("jdbc:postgresql://%s:%s/%s", postgresInstance.getHost(), postgresInstance.getPort(), databaseName)) .driverClassName("org.postgresql.Driver") .build(); } private ServiceInstance getPostgresInstance() { return discoveryClient.getInstances("postgres") .stream() .findFirst() .orElseThrow(() -> new IllegalStateException("Unable to discover a Postgres instance")); } }
Die Methode getPostgresInstance()
verwendet die erste postgres
mit dem in Consul registrierten postgres
Tag. Die dataSource()
-Methode ist die Bean der DataSource.
Als Nächstes deklarieren wir ein Repository mit grundlegenden Operationen für die Image
Entität, in dem die Seitenadresse und die Image-Adresse gespeichert sind:
@Repository public interface ImageRepository extends JpaRepository<Image, Long> { }
5. FeignClient verwenden
Als Nächstes legen wir ein JS-Skript in den Ressourcen ab, wodurch das größte Bild von der Seite abgerufen wird.
module.exports = async ({page, context}) => { const {url} = context; await page.goto(url); await page.evaluate(_ => { window.scrollBy(0, window.innerHeight); }); const data = await page._client.send('Page.getResourceTree') .then(tree => { return Array.from(tree.frameTree.resources) .filter(resource => resource.type === 'Image' && resource.url && resource.url.indexOf('.svg') == -1) .sort((a, b) => b.contentSize - a.contentSize)[0]; }); return { data, type: 'json' }; };
Definieren Sie die BlowserlessClient-Schnittstelle:
@FeignClient("browserless")
Servicemethode, die ein Bild anfordert und in der Datenbank speichert:
public Image findLargestImage(String url) { var browserlessContext = new BrowserlessContext(url); var largestImageRequest = new LargestImageRequest(getLargestImageScript, browserlessContext); var imageInfo = browserlessClient.findLargestImage(largestImageRequest); var image = new Image(); image.setSourceUrl(url); image.setImageUrl(imageInfo.getUrl()); return imageRepository.save(image); }
Funktionskontrolleur:
public class MainController { private static Logger log = LoggerFactory.getLogger(MainController.class); @Autowired private ImageService imageService; @Value("${test.property}") private String testProperty; @GetMapping("/largest-image") public ResponseEntity<Image> getTitle(@RequestParam("url") String url) { return ResponseEntity.ok(imageService.findLargestImage(url)); } @GetMapping("/property") public ResponseEntity<String> getProperty() { return ResponseEntity.ok(testProperty); } }
Hier wird das Feld testProperty
aus dem Schlüssel- / testProperty
von testProperty
.
6. Das Ende
Das ist alles!
Ich hoffe, ich konnte eine mögliche Konfiguration der vorgestellten Tools zeigen und dieser Artikel wird für jemanden nützlich sein.
In diesem Artikel gibt es nicht viele Erklärungen, da ich glaube, dass es in diesem Fall einfacher ist, den Code zu verstehen.
Nützliche Links:
1) https://docs.docker.com/compose/overview/ - Docker Compose-Dokumentation
2) https://www.consul.io/intro/index.html - Einführung in Consul
3) http://matt.might.net/articles/intro-to-make/ - Einführung zu machen
4) https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html - Dokumentation zu Feign