вторник, 30 июля 2024 г.

Spring Cloud Gateway

Предположим мы хотим обращаться к нескольким API/нескольким сервисам через одну точку. Для этого мы поднимаем еще один сервис (микросервисная архитектура) и этот сервис будет у нас принимать запросы и перенаправлять их куда надо. Для этого мы создаем приложение Spring Boot и добавляем к нему в зависимости

implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
Далее нам нужно в конфиге прописать маршруты.

spring:
  cloud:
    gateway:
      routes:
        - id: ya
          uri: http://ya.ru
          predicates:
            - Path=/ya/**
          filters:
            - StripPrefix=1
        - id: employees
          uri: http://localhost:8081
          predicates:
            - Path=/employees/**
          filters:
            - StripPrefix=1
Для примера. В результате у нас по адресу localhost:8080/ya будет ya.ru а по адресу localhost:8080/employees будет сервис employees запущенный на 8081 порту (имеется в виду что наш сервис cloud gateway запущен на 8080-м порту). StripPrefix=1 значит убрать первую часть url. Далее все запросы соответствующие предикату перенапрявлются на uri. Мы можем запусть Eureka и разрешать наши сервисы через нее. Для этого нам нужно uri в конфиге маршрутов задавать в таком виде:

	uri: lb://employee-service
Тут указывается название под которым сервис зарегистрирован в Еврике. Так же мы можем посмотреть список зарегестрированных маршрутов через actuator. Для это в конфиг приложения нам надо добавить:

management:
  endpoint:
    gateway:
      enabled=true
  endpoints:
    web:
      exposure:
        include: "*"
И тогда по адресу localhost:8080/actuator/gateway/routes у нас будет информация о маршрутах.

воскресенье, 28 июля 2024 г.

Feign Client и Eureka

Например у нас есть скажем две какие-то сущности в нашей системе, которые хранятся в своих репозитариях и с которыми происходят какие-то процессы. В микросервисной архитектуре мы можем раскидать их два сервиса! Предположим что нам это зачем-то нужно. Например у нас есть два сервиса 1) employee-service который содержит в себе информацию о работниках и 2) organization-service который содержит информацию об организациях. Но у нас в организации есть сотрудники и соответственно второй сервис может получать информацию из первого. Для этого мы можем из второго сервиса вызывать первый например через Spring RestTemplate. Но есть и вариант еще лучше и проще. Это декларативное описание API с помощью Feign.

@FeignClient(name = "employee-service")
public interface EmployeeClient {

	@GetMapping("/organization/{organizationId}")
	List findByOrganization(@PathVariable("organizationId") Long organizationId);
	
}
Вот таким простым образом мы из organization-service можем использовать emplyee-service. Но как organization-service узнает где находится employee-service? Ведь даже если они на одной машине, порты могут быть разные. Или вообще может выбираться рандомный свободный порт. Тут у нас на сцену выходит еще один, третий сервис, ведь у нас же микросервисная архитектура. Это discovery-service, еще одно spring-boot приложение. Создать его проще простого, вот так:

@SpringBootApplication
@EnableEurekaServer
public class DiscoveryApplication {

	public static void main(String[] args) {
		new SpringApplicationBuilder(DiscoveryApplication.class).run(args);
	}

}
. Да для dicsovery-service мы будем использовать Eurekу. Теперь мы можем запусть эвкрику скажем на 8061 порту, потом зайти и глянуть какие же сервисы там зарегистрированы (Instances currently registered with Eureka). Теперь нам нужно чтобы наши сервисы регистрировались в Eureke и тогда они без проблем будут общаться друг с другом даже если будут постоянно перезжать по разным аддресам. Для этого нужно всего лишь добавить евкрика-клиент в зависимости вот так:

implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
. И прописать в конфиги наших сервисов как они будут подключаться к еврике, вот так:

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8061/eureka/
  instance:
    instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}
.

четверг, 25 июля 2024 г.

Spring Cloud Config

Spring Cloud Config. Вот есть у вас преположим spring сервис. Когда вы его запускаете, он запускается по умолчанию на порту 8080, но вы можете это катомизировать с помошью секции server.port в конфиге. С одной стороны хорошо но с другой стороны каждый раз менять там неудобно особенно если сервер этот нужно запускать в разных местах и конфиг для этих мест должен быть разным. Очевидное решение: каждое из этих мест должно хранить настройки само в себе и ваш сервис при старте должен их подхватывать. Для этого например можно поднять еще один сервис в каждом месте который и будет раздавать этот конфиг. Таким образом мы отделяем изменение конфига от изменения основного сервиса/приложения со всеми вытекающими плюсами. Ну и минус в том что теперь у нас еще по одному сервису/приложению дополнительному которое будет просто раздавать конфиг. Для этого в нашем сервисе-клиенте конфиг сервера в конфиге application.yml прописываем что он ожидает наличия конфиг- сервиса:
 spring:  
  application:  
   name: employee-service  
  config:  
   import: "optional:configserver:http://localhost:8088"  
Здесь optional означает что если сервис конфига он не подхватит то это не повод прекращать работу. Далее таким вот нехитрым способом создаем конфиг-сервис:
 @SpringBootApplication  
 @EnableConfigServer  
 public class ConfigApplication {  
      public static void main(String[] args) {  
           new SpringApplicationBuilder(ConfigApplication.class).run(args);  
      }  
 }  
Сами конфиги собственно у нас хранятся в папке resources/config нашего конфиг сервиса. Поскольку у нас приложение называется employee-service у нас конфиг должен называться employee-service.yml. Там мы добавляем точно так же
 server:  
  port: 8290  
например. Теперь сперва стартанем конфиг-сервис, потом наш employee-service и о чудо, порт теперь у нас 8290 на котором сервис стартует.