تُظهر هذه المقالة مثالًا على كيفية رفع بيئة التطوير المحلية باستخدام تطبيق Docker Compose و Consul و Make for the Spring Boot (وليس فقط) ، باستخدام ، على سبيل المثال ، PostgreSQL و Browserless.
الخطة:
- تكوين الخدمات في Docker Compose
- تسجيل الخدمات في القنصل وإضافة المتغيرات إلى مستودع القنصل
- إنشاء ملف Makefile
- تكوين PostgreSQL
- باستخدام FeignClient
- الخلاصة
التطبيق غير مفيد على الإطلاق: باتباع رابط إلى صفحة ، فإنه يعيد رابطًا لأكبر صورة من هذه الصفحة. سيتم استرداد الصورة بواسطة Browserless ، وسيتم حفظ هذه الحالة في PostgreSQL.
رابط للمشروع: https://bitbucket.org/maximka777/consul-docker-spring-cloud/src/master/ .
1. إعداد الخدمات في Docker Compose
أول شيء يجب فعله هو إنشاء ملف تكوين docker-compose.yml
لحاويات docker:
touch docker-compose.yml
يحتوي هذا الملف على إصدار إنشاء عامل الميناء:
version: '3.4'
تكوين الشبكة:
networks: lan:
وتكوين الخدمات اللازمة ، في هذه الحالة القنصل و Browserless و 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
- كلمة مرور لقاعدة بيانات المستخدم بشكل افتراضي postgres
، POSTGRES_DB
- إنشاء قاعدة بيانات تلقائيًا في الحاوية.
لبدء الخدمات تحتاج إلى تشغيل الأمر:
docker-compose up
نحن في انتظار نهاية تحميل صور الحاويات وإطلاق الحاويات. لإيقاف تشغيل الحاويات ، استخدم الأمر docker-compose down
. بعد بدء تشغيل جميع الحاويات ، يمكنك الانتقال إلى العنوان في متصفح localhost:8500
- يجب فتح عميل الويب القنصل (الشكل 1).

الشكل 1
2. تسجيل الخدمات في القنصل وإضافة المتغيرات لتخزين القنصل
يمكنك تسجيل الخدمات في القنصل عن طريق إرسال العديد من الطلبات اللاحقة إلى عنوان localhost:8500/v1/agent/service/register
، على سبيل المثال ، باستخدام curl.
ضع كل مكالمات الضفيرة في سكربت باش.
chmod +x register-services.sh
- لجعل الملف قابلاً للتشغيل.
بعد تنفيذ البرنامج النصي ، ستظهر PostgreSQSL و Browserless في قائمة الخدمات المسجلة في Consule'e (الشكل 2).

الشكل 2
يوضح الشكل أن اختبار PostgreSQL فشل مع وجود خطأ - (لن يؤثر على الجوهر) .
إضافة التكوين إلى تخزين المفتاح / القيمة القنصل. أنشئ متغير test.property
في دليل example.app
:
curl --request PUT --data TEST \ localhost:8500/v1/kv/example.app/test.property
إذا كان هناك العديد من المتغيرات ، فمن الأفضل استخدام نص bash.
3. إنشاء ملف Makefile
لتبسيط إطلاق كل هذا ، اكتب 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
تحذير: يستخدم Makefile
نوعًا خاصًا من المسافات البادئة!
سيبدأ أمر make up
البيئة بأكملها.
4. تكوين PostgreSQL
بعد ذلك ، تم إنشاء مشروع Spring Boot الأساسي (Maven) باستخدام مُهيئ تطبيق Spring Boot https://start.spring.io/ .
تمت إضافة التبعيات التالية إلى 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>
من أسماء الحزم يتضح سبب الحاجة إليها.
دعنا نكتب تكوين مصدر البيانات. في ملف bootstrap.properties
، قم بإفلات التكوينات:
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
في 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: '*'
وفئة التكوين نفسها:
@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")); } }
تأخذ طريقة getPostgresInstance()
مثيل الخدمة الأول مع علامة postgres
المسجلة في القنصل. أسلوب dataSource()
هو فول مصدر البيانات.
بعد ذلك ، نعلن عن مستودع يحتوي على العمليات الأساسية على كيان Image
، الذي يخزن عنوان الصفحة وعنوان الصورة:
@Repository public interface ImageRepository extends JpaRepository<Image, Long> { }
5. باستخدام FeignClient
بعد ذلك ، سنقوم بإسقاط نص JS في الموارد ، والذي سيسحب أكبر صورة من الصفحة.
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' }; };
تحديد واجهة BlowserlessClient:
@FeignClient("browserless")
طريقة الخدمة لطلب صورة وتخزينها في قاعدة البيانات:
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); }
تحكم الوظائف:
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); } }
هنا testProperty
سحب حقل testProperty
من مفتاح / قيمة testProperty
.
6. النهاية
هذا كل شيء!
آمل أن أكون قد تمكنت من إظهار تكوين محتمل للأدوات المعروضة وستكون هذه المقالة مفيدة لشخص ما.
لا توجد العديد من التفسيرات في هذه المقالة ، لأنني أعتقد أنه من السهل في هذه الحالة فهم الرمز.
روابط مفيدة:
1) https://docs.docker.com/compose/overview/ - توثيق Docker Compose
2) https://www.consul.io/intro/index.html - مقدمة عن القنصل
3) http://matt.might.net/articles/intro-to-make/ - مقدمة صنع
4) https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html - وثائق على Feign