Artikel ini menunjukkan contoh cara meningkatkan lingkungan pengembangan lokal menggunakan Docker Compose, Consul, Make for the Spring Boot (dan tidak hanya), menggunakan, misalnya, PostgreSQL dan Browserless.
Rencana:
- Mengkonfigurasi Layanan di Docker Compose
- Pendaftaran layanan di Consul'e dan menambahkan variabel ke repositori Consul'a
- Buat Makefile
- Konfigurasi postgreSQL
- Menggunakan FeignClient
- Kesimpulan
Aplikasi ini sama sekali tidak berguna: mengikuti tautan ke halaman, ia mengembalikan tautan ke gambar terbesar dari halaman ini. Gambar akan diambil oleh Browserless, dan dalam PostgreSQL kasus ini akan disimpan.
Tautan ke proyek: https://bitbucket.org/maximka777/consul-docker-spring-cloud/src/master/ .
1. Menyiapkan layanan di Docker Compose
Hal pertama yang harus dilakukan adalah membuat file konfigurasi docker-compose.yml
untuk kontainer buruh pelabuhan:
touch docker-compose.yml
File ini berisi versi komposisi buruh pelabuhan:
version: '3.4'
Konfigurasi jaringan:
networks: lan:
Dan konfigurasi layanan yang diperlukan, dalam hal ini Consul, Browserless, dan 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
- kata sandi ke basis data pengguna secara default postgres
, POSTGRES_DB
- secara otomatis membuat basis data dalam wadah.
Untuk memulai layanan, Anda perlu menjalankan perintah:
docker-compose up
Kami sedang menunggu akhir memuat gambar wadah dan meluncurkan wadah. Untuk menghentikan kontainer berjalan, gunakan perintah docker-compose down
. Setelah memulai semua kontainer, Anda dapat pergi ke alamat di browser localhost:8500
- klien web Konsul harus terbuka (Gbr. 1).

Gambar 1
2. Pendaftaran layanan di Konsul'e dan menambahkan variabel ke penyimpanan Konsul'a
Anda dapat mendaftarkan layanan di Konsul dengan mengirimkan beberapa permintaan pasca ke alamat localhost:8500/v1/agent/service/register
, misalnya, menggunakan curl.
Masukkan semua panggilan curl ke skrip bash.
chmod +x register-services.sh
- untuk membuat file dapat dijalankan.
Setelah script dieksekusi, PostgreSQSL dan Browserless kami akan muncul dalam daftar layanan terdaftar di Consule'e (Gbr. 2).

Gambar 2
Angka tersebut menunjukkan bahwa pemeriksaan PostgreSQL gagal dengan kesalahan - (itu tidak akan mempengaruhi esensi) .
Tambahkan konfigurasi ke penyimpanan kunci / nilai Konsul. Buat variabel test.property
di direktori example.app
:
curl --request PUT --data TEST \ localhost:8500/v1/kv/example.app/test.property
Jika ada banyak variabel, lebih baik menggunakan skrip bash.
3. Membuat Makefile
Untuk mempermudah peluncuran semua ini, tulis 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
Peringatan: Makefile
menggunakan jenis lekukan khusus!
Perintah make up
akan memulai seluruh lingkungan.
4. Konfigurasi postgreSQL
Selanjutnya, proyek Spring Boot dasar (Maven) dibuat menggunakan penginisialisasi aplikasi Spring Boot https://start.spring.io/ .
Ketergantungan berikut telah ditambahkan ke pom.xml
:
<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>
Dari nama-nama paket jelas mengapa mereka diperlukan.
Mari kita menulis konfigurasi untuk DataSource. Di file bootstrap.properties
, letakkan konfigurasi:
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
Dalam 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: '*'
Dan kelas konfigurasi itu sendiri:
@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")); } }
Metode getPostgresInstance()
mengambil instance layanan pertama dengan tag postgres
terdaftar di Konsul. Metode dataSource()
adalah kacang dari DataSource.
Selanjutnya, kami mendeklarasikan repositori dengan operasi dasar pada entitas Image
, yang menyimpan alamat halaman dan alamat gambar:
@Repository public interface ImageRepository extends JpaRepository<Image, Long> { }
5. Menggunakan FeignClient
Selanjutnya, kita akan memasukkan skrip JS ke sumber, yang akan mengeluarkan gambar terbesar dari halaman.
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' }; };
Tentukan antarmuka BlowserlessClient:
@FeignClient("browserless")
Metode layanan meminta gambar dan menyimpan dalam database:
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); }
Pengontrol fungsionalitas:
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); } }
Di sini bidang testProperty
ditarik dari penyimpanan kunci / nilai testProperty
.
6. Akhir
Itu saja!
Saya harap saya dapat menunjukkan kemungkinan konfigurasi alat yang disajikan dan artikel ini akan bermanfaat bagi seseorang.
Tidak banyak penjelasan dalam artikel ini, karena saya percaya dalam hal ini lebih mudah untuk memahami kode.
Tautan yang bermanfaat:
1) https://docs.docker.com/compose/overview/ - Dokumentasi Penulis Docker
2) https://www.consul.io/intro/index.html - pengantar Konsul
3) http://matt.might.net/articles/intro-to-make/ - pengantar untuk dibuat
4) https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html - dokumentasi tentang Feign