Use @LoadBalanced
This commit is contained in:
@ -9,6 +9,7 @@
|
||||
<version>3.5.5</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<groupId>com.backend.vue.bff.service</groupId>
|
||||
<artifactId>anyame-vue-bff</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
@ -37,22 +38,6 @@
|
||||
<logstash-logback-encoder.version>8.1</logstash-logback-encoder.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-cache</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
|
||||
@ -61,7 +46,6 @@
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.retrofit2</groupId>
|
||||
<artifactId>converter-jackson</artifactId>
|
||||
@ -87,7 +71,6 @@
|
||||
<artifactId>logstash-logback-encoder</artifactId>
|
||||
<version>${logstash-logback-encoder.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
||||
@ -33,6 +33,7 @@ public class GlobalExceptionHandler {
|
||||
"API_CALL_FAILED",
|
||||
"Failed to communicate with external service: " + e.getMessage(),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||
logger.error("API call failed", e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
|
||||
}
|
||||
|
||||
|
||||
@ -1,66 +1,34 @@
|
||||
package com.backend.vue.bff.service.config;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
import com.backend.search.kodik.ApiClient;
|
||||
import com.backend.search.kodik.JSON;
|
||||
import com.backend.search.kodik.api.SearchControllerApi;
|
||||
import com.backend.vue.bff.service.factory.AbstractApiFactory;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import retrofit2.Retrofit.Builder;
|
||||
|
||||
@Configuration
|
||||
@EnableDiscoveryClient
|
||||
public class SearchApiClientConfiguration {
|
||||
|
||||
private final DiscoveryClient discoveryClient;
|
||||
|
||||
public SearchApiClientConfiguration(DiscoveryClient discoveryClient) {
|
||||
this.discoveryClient = discoveryClient;
|
||||
@LoadBalanced
|
||||
@Bean
|
||||
public RestClient.Builder restClientBuilder() {
|
||||
return RestClient.builder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Lazy
|
||||
public FactoryBean<ApiClient> apiClientFactory() {
|
||||
return new ApiClientFactoryBean(discoveryClient);
|
||||
public ApiClient apiClient() {
|
||||
return new ApiClient(restClientBuilder().build());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Lazy
|
||||
public SearchControllerApi searchApi(ApiClient apiClient) {
|
||||
return apiClient.createService(SearchControllerApi.class);
|
||||
}
|
||||
|
||||
private static class ApiClientFactoryBean extends AbstractApiFactory<ApiClient> {
|
||||
public ApiClientFactoryBean(DiscoveryClient discoveryClient) {
|
||||
super(discoveryClient, "ANYAME-KODIK-SEARCH-BACKEND");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return ApiClient.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectMapper createObjectMapper() {
|
||||
JSON json = new JSON();
|
||||
return json.getMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiClient createApiClient() {
|
||||
return new ApiClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateAdapterBuilder(ApiClient instance, Builder adapterBuilder) {
|
||||
instance.setAdapterBuilder(adapterBuilder);
|
||||
}
|
||||
apiClient = apiClient.setBasePath("http://ANYAME-KODIK-SEARCH-BACKEND");
|
||||
return new SearchControllerApi(apiClient);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,8 +4,8 @@ import java.io.IOException;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.backend.vue.bff.service.service.KodikService;
|
||||
|
||||
@RestController
|
||||
|
||||
@ -1,68 +0,0 @@
|
||||
package com.backend.vue.bff.service.factory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
|
||||
import com.backend.vue.bff.service.exception.ServiceUnavailableException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.jackson.JacksonConverterFactory;
|
||||
import retrofit2.converter.scalars.ScalarsConverterFactory;
|
||||
|
||||
public abstract class AbstractApiFactory<T> implements FactoryBean<T> {
|
||||
private final DiscoveryClient discoveryClient;
|
||||
private final String serviceId;
|
||||
|
||||
public AbstractApiFactory(DiscoveryClient discoveryClient, String serviceId) {
|
||||
this.discoveryClient = discoveryClient;
|
||||
this.serviceId = serviceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getObject() throws Exception {
|
||||
T client = createApiClient();
|
||||
|
||||
String baseUrl = resolveServiceUrl(serviceId);
|
||||
|
||||
Retrofit.Builder adapterBuilder = new Retrofit.Builder()
|
||||
.baseUrl(baseUrl)
|
||||
.addConverterFactory(ScalarsConverterFactory.create())
|
||||
.addConverterFactory(JacksonConverterFactory.create(createObjectMapper()));
|
||||
|
||||
updateAdapterBuilder(client, adapterBuilder);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private String resolveServiceUrl(String serviceName) {
|
||||
List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
|
||||
|
||||
if (instances.isEmpty()) {
|
||||
throw new ServiceUnavailableException();
|
||||
}
|
||||
|
||||
ServiceInstance instance = instances.get(0);
|
||||
String baseUrl = instance.getUri().toString();
|
||||
|
||||
if (!baseUrl.endsWith("/")) {
|
||||
baseUrl = baseUrl + "/";
|
||||
}
|
||||
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
public abstract ObjectMapper createObjectMapper();
|
||||
|
||||
public abstract T createApiClient();
|
||||
|
||||
protected abstract void updateAdapterBuilder(T instance, Retrofit.Builder adapterBuilder);
|
||||
}
|
||||
@ -20,6 +20,6 @@ public class KodikService {
|
||||
|
||||
@Cacheable("kodikSearch")
|
||||
public KodikResponse search(String title) throws BeansException, IOException {
|
||||
return controllerApiFactory.getObject().search(title).execute().body();
|
||||
return controllerApiFactory.getObject().search(title);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user