本文显示了一个示例,该示例说明了如何使用Docker Compose,Consul,Make for the Spring Boot应用程序(不仅限于),例如使用PostgreSQL和Browserless来提升本地开发环境。
计划:
- 在Docker Compose中配置服务
- 在Consul'e中注册服务并将变量添加到Consul'a存储库中
- 创建Makefile
- PostgreSQL配置
- 使用FeignClient
- 结论
该应用程序绝对没有用:在链接到页面之后,它返回到该页面上最大图像的链接。 该图像将由Browserless检索,并且在PostgreSQL中将保存这种情况。
链接到项目: https : //bitbucket.org/maximka777/consul-docker-spring-cloud/src/master/ 。
1.在Docker Compose中设置服务
首先要做的是docker-compose.yml
容器创建docker-compose.yml
配置文件:
touch docker-compose.yml
该文件包含docker-compose的版本:
version: '3.4'
网络配置:
networks: lan:
以及必要服务的配置,在本例中为Consul,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
浏览器中的地址localhost:8500
-Consul Web客户端应打开(图1)。

图1
2.在Consul'e中注册服务并将变量添加到Consul'a的存储中
您可以在Consul中注册服务,方法是将几个后期请求发送到localhost:8500/v1/agent/service/register
地址localhost:8500/v1/agent/service/register
,例如,使用curl。
将所有curl调用放入bash脚本中。
chmod +x register-services.sh
-services.sh-使文件可运行。
执行脚本后,我们的PostgreSQSL和Browserless将出现在Consule'e中已注册服务的列表中(图2)。

图2
该图显示PostgreSQL检查失败并显示错误- (这不会影响本质) 。
将配置添加到领事的键/值存储中。 在example.app
目录中创建变量test.property
:
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应用程序初始化程序https://start.spring.io/生成了一个基本的Spring Boot项目(Maven)。
以下依赖项已添加到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>
从软件包名称中可以很清楚地知道为什么需要它们。
让我们为DataSource编写配置。 在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()
方法采用在Consul中注册了postgres
标签的第一个服务实例。 dataSource()
方法是DataSource的bean。
接下来,我们声明一个在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
的键/值存储区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的文档