рдпрд╣ рдЖрд▓реЗрдЦ рдбреЙрдХрдЯрд░ рдХрдореНрдкреЛрдЬрд╝, рдХреЙрдиреНрд╕рд▓, рдореЗрдХ рдлреЙрд░ рдж рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди (рдФрд░ рди рдХреЗрд╡рд▓), рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдХреНрдпреВрдПрд▓ рдФрд░ рдмреНрд░рд╛рдЙрдЬрд╝рд░рд▓реЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реНрдерд╛рдиреАрдп рд╡рд┐рдХрд╛рд╕ рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЛ рдХреИрд╕реЗ рдмрдврд╝рд╛рдПрдВ, рдЗрд╕рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдЦрд╛рддрд╛ рд╣реИред
рдпреЛрдЬрдирд╛:
- рдбреЙрдХрд░ рдХрдореНрдкреЛрдЬрд╝ рдореЗрдВ рд╕реЗрд╡рд╛рдПрдБ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛
- рдХрд╛рдВрд╕реБрд▓реА рдореЗрдВ рд╕реЗрд╡рд╛рдУрдВ рдХрд╛ рдкрдВрдЬреАрдХрд░рдг рдФрд░ рд╡рд╛рдгрд┐рдЬреНрдп рджреВрддрд╛рд╡рд╛рд╕ рдореЗрдВ рдЪрд░ рдЬреЛрдбрд╝рдирд╛
- Makefile рдмрдирд╛рдПрдБ
- PostgreSQL рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди
- FeignClient рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛
- рдирд┐рд╖реНрдХрд░реНрд╖
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрд┐рд▓реНрдХреБрд▓ рдмреЗрдХрд╛рд░ рд╣реИ: рдХрд┐рд╕реА рдкреЗрдЬ рдХреЗ рд▓рд┐рдВрдХ рдХреЗ рдмрд╛рдж, рдпрд╣ рдЗрд╕ рдкреЗрдЬ рд╕реЗ рд╕рдмрд╕реЗ рдмрдбрд╝реА рдЫрд╡рд┐ рдХрд╛ рд▓рд┐рдВрдХ рджреЗрддрд╛ рд╣реИред рдЫрд╡рд┐ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд░рд╣рд┐рдд рджреНрд╡рд╛рд░рд╛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХреА рдЬрд╛рдПрдЧреА, рдФрд░ PostgreSQL рдореЗрдВ рдпрд╣ рдорд╛рдорд▓рд╛ рд╕рд╣реЗрдЬрд╛ рдЬрд╛рдПрдЧрд╛ред
рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рд▓рд┐рдВрдХ: https://bitbucket.org/maximka777/consul-docker-spring-cloud/src/master/ ред
1. рдбреЙрдХрд░ рдХрдореНрдкреЛрдЬрд╝ рдореЗрдВ рд╕реЗрд╡рд╛рдУрдВ рдХреА рд╕реНрдерд╛рдкрдирд╛
рдкрд╣рд▓реА рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ docker-compose.yml
рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ docker-compose.yml
рдХрдВрдЯреЗрдирд░реЛрдВ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдирд╛ рд╣реИ:
touch docker-compose.yml
рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдбреЙрдХ-рдХрдВрдкреЛрдЬрд╝ рдХрд╛ рд╕рдВрд╕реНрдХрд░рдг рд╣реИ:
version: '3.4'
рдиреЗрдЯрд╡рд░реНрдХ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди:
networks: lan:
рдФрд░ рдЖрд╡рд╢реНрдпрдХ рд╕реЗрд╡рд╛рдУрдВ рдХрд╛ рд╡рд┐рдиреНрдпрд╛рд╕, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдХреЙрдиреНрд╕рд▓, рдмреНрд░рд╛рдЙрдЬрд░рд▓реЗрд╕ рдФрд░ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдХреНрдпреВрдПрд▓:
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_DB
- рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдХрдВрдЯреЗрдирд░ рдореЗрдВ рдбреЗрдЯрд╛рдмреЗрд╕ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдХрдорд╛рдВрдб рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдЬрд┐рди рд╕реЗрд╡рд╛рдУрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЙрдиреНрд╣реЗрдВ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП:
docker-compose up
рд╣рдо рдХрдВрдЯреЗрдирд░ рдЫрд╡рд┐рдпреЛрдВ рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдФрд░ рдХрдВрдЯреЗрдирд░ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдХрдВрдЯреЗрдирд░ рдХреЛ рдЪрд▓рд╛рдиреЗ рд╕реЗ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП, docker-compose down
рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рд╕рднреА рдХрдВрдЯреЗрдирд░реЛрдВ рдХреЛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк localhost:8500
рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдкрддреЗ рдкрд░ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ localhost:8500
- рдХреЙрдиреНрд╕рд▓ рд╡реЗрдм рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдЦреЛрд▓рдирд╛ рдЪрд╛рд╣рд┐рдП (рдЫрд╡рд┐ 1)ред

рдЪрд┐рддреНрд░ 1
2. рдХрдВрд╕реБрд▓ рдореЗрдВ рд╕реЗрд╡рд╛рдУрдВ рдХрд╛ рдкрдВрдЬреАрдХрд░рдг рдФрд░ рд╡рд╛рдгрд┐рдЬреНрдп рджреВрддрд╛рд╡рд╛рд╕ рдХреЗ рднрдВрдбрд╛рд░рдг рдХреЗ рд▓рд┐рдП рдЪрд░ рдЬреЛрдбрд╝рдирд╛
рдЖрдк localhost:8500/v1/agent/service/register
рдкрддреЗ рдкрд░ рдХрдИ рдкреЛрд╕реНрдЯ-рдЕрдиреБрд░реЛрдз рднреЗрдЬрдХрд░ рдХреМрдВрд╕реБрд▓ рдореЗрдВ рд╕реЗрд╡рд╛рдПрдВ рдкрдВрдЬреАрдХреГрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ localhost:8500/v1/agent/service/register
, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХрд░реНрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗред
рд╕рднреА рдХрд░реНрд▓ рдХреЙрд▓ рдХреЛ рдмреИрд╢ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рд░рдЦреЗрдВред
chmod +x register-services.sh
- рдлрд╝рд╛рдЗрд▓ рдХреЛ рдЪрд▓рд╛рдиреЗ рдпреЛрдЧреНрдп рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдПред
рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдорд╛рд░рд╛ PostgreSQSL рдФрд░ Browserless, Conusele .e (рдЫрд╡рд┐ 2) рдореЗрдВ рдкрдВрдЬреАрдХреГрдд рд╕реЗрд╡рд╛рдУрдВ рдХреА рд╕реВрдЪреА рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ред

рдЪрд┐рддреНрд░ 2
рдЖрдВрдХрдбрд╝рд╛ рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдХрд┐ PostgreSQL рдЪреЗрдХ рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ - (рдпрд╣ рд╕рд╛рд░ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдирд╣реАрдВ рдХрд░реЗрдЧрд╛) ред
рдХреЙрдиреНрд╕рд▓ рдХреА рдХреБрдВрдЬреА / рдореВрд▓реНрдп рднрдВрдбрд╛рд░рдг рдХреЗ рд▓рд┐рдП рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдЬреЛрдбрд╝реЗрдВред рд╡реЗрд░рд┐рдПрдмрд▓ test.property
рдмрдирд╛рдПрдБред
curl --request PUT --data TEST \ localhost:8500/v1/kv/example.app/test.property
рдпрджрд┐ рдХрдИ рдЪрд░ рд╣реИрдВ, рддреЛ рдмреИрд╢ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИред
3. рдореЗрдХрдлрд┐рд▓ рдмрдирд╛рдирд╛
рдЗрд╕ рд╕рдм рдХреЗ рдкреНрд░рдХреНрд╖реЗрдкрдг рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, 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 рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди
рдЕрдЧрд▓рд╛, рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝рд░ 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>
рд╕рдВрдХреБрд▓ рдХреЗ рдирд╛рдореЛрдВ рд╕реЗ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдЙрдирдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИред
рдЪрд▓рд┐рдП 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 рдХреА рд╕реЗрдо рд╣реИред
рдЕрдЧрд▓рд╛, рд╣рдо Image
рдЗрдХрд╛рдИ рдкрд░ рдореВрд▓ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд╕рд╛рде рдПрдХ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдкреЗрдЬ рдПрдбреНрд░реЗрд╕ рдФрд░ рдЗрдореЗрдЬ рдПрдбреНрд░реЗрд╕ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рддрд╛ рд╣реИ:
@Repository public interface ImageRepository extends JpaRepository<Image, Long> { }
5. FeignClient рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛
рдЕрдЧрд▓рд╛, рд╣рдо рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдореЗрдВ рдПрдХ рдЬреЗрдПрд╕ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЫреЛрдбрд╝ рджреЗрдВрдЧреЗ, рдЬреЛ рдкреЗрдЬ рд╕реЗ рд╕рдмрд╕реЗ рдмрдбрд╝реА рдЫрд╡рд┐ рдХреЛ рдЦреАрдВрдЪ рд▓реЗрдЧрд╛ред
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' }; };
BlserlessClient рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ:
@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
рдХреА рдХреА / рд╡реИрд▓реНрдпреВ рд╕реНрдЯреЛрд░ рд╕реЗ рдЦреАрдВрдЪрд╛ рдЧрдпрд╛ рд╣реИред
6. рдЕрдВрдд
рд╡рд╣ рд╕рдм рд╣реИ!
рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдореИрдВ рдкреНрд░рд╕реНрддреБрдд рдЯреВрд▓ рдХрд╛ рдПрдХ рд╕рдВрднрд╛рд╡рд┐рдд рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рджрд┐рдЦрд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛ рдФрд░ рдпрд╣ рд▓реЗрдЦ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдХрдИ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдирд╣реАрдВ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдХреЛрдб рдХреЛ рд╕рдордЭрдирд╛ рдЖрд╕рд╛рди рд╣реИред
рдЙрдкрдпреЛрдЧреА рд▓рд┐рдВрдХ:
1) https://docs.docker.com/compose/overview/ - рдбреЙрдХрдЯрд░ рд░рдЪрдирд╛ рдкреНрд░рд▓реЗрдЦрди
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 рдкрд░ рдкреНрд░рд▓реЗрдЦрди