将 Spring 云负载平衡与 KeycloakRestTemplate 集成
Integrate Spring Cloud load balancing with KeycloakRestTemplate
我有一个 microservice landscape 配置了 Spring 云发现,所以我可以只使用它们的 ID 访问其他服务实例:
public class MyClass {
@Autowired
@LoadBalanced
private RestTemplate restTemplate;
public String doOtherStuff() {
String results = restTemplate.getForObject("http://stores/stores", String.class);
return results;
}
}
现在我想访问一个需要OAuth2授权的服务。我使用 Keycloak 服务器来提供它,并且 Keycloak 已经提供了一个具有特定 KeycloakRestTemplate. Anyway, how to enhance it with load balancing?
的适配器
我们需要创建一个特定的 KeycloakRestTemplate,它将使用 LoadBalancerInterceptor:
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@LoadBalanced
public KeycloakRestTemplate keycloakRestTemplate(
KeycloakClientRequestFactory keycloakClientRequestFactory,
LoadBalancerInterceptor interceptor) {
KeycloakRestTemplate result = new KeycloakRestTemplate(
keycloakClientRequestFactory);
// Add the interceptor for load balancing
result.getInterceptors().add(interceptor);
return result;
}
//More configurations for keycloak
}
所以有机会获得 Authorized / LoadBalanced 模板:
@Autowired
@LoadBalanced
protected KeycloakRestTemplate restTemplate;
另请参阅:
- Add Ribbon load balancing to a vanilla RestTemplate
你的解决方案不是很好,因为
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@LoadBalanced
public KeycloakRestTemplate keycloakRestTemplate(
KeycloakClientRequestFactory keycloakClientRequestFactory,
LoadBalancerInterceptor interceptor) {
KeycloakRestTemplate result = new KeycloakRestTemplate(
keycloakClientRequestFactory);
// Add the interceptor for load balancing
result.getInterceptors().add(interceptor);
return result;
}
没有用,因为你遇到了异常
The dependencies of some of the beans in the application context form a cycle:
...
┌─────┐
| keycloakRestTemplate defined in class path resource [...]
↑ ↓
| ribbonInterceptor defined in class path resource [org/springframework/cloud/client/loadbalancer/LoadBalancerAutoConfiguration$LoadBalancerInterceptorConfig.class]
↑ ↓
| org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration (field private java.util.List org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.restTemplates)
└─────┘
你要做什么?
@Bean
@LoadBalanced
public KeycloakRestTemplate keycloakRestTemplate(
KeycloakClientRequestFactory keycloakClientRequestFactory) {
return new KeycloakRestTemplate(keycloakClientRequestFactory);
}
没有 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 那么你会得到单例,你可以像这样使用它
@Autowired
protected KeycloakRestTemplate restTemplate;
或者你可以像原型
一样定义restTemplate
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@LoadBalanced
public KeycloakRestTemplate keycloakRestTemplate(
KeycloakClientRequestFactory keycloakClientRequestFactory) {
return new KeycloakRestTemplate(keycloakClientRequestFactory);
}
然后像这样使用
@Autowired
@LoadBalanced
protected KeycloakRestTemplate restTemplate;
编辑:
由于循环问题,Xtreme Biker 的解决方案不适用于 SpringBoot 2 和 Keycloak 6,我的第一个建议不是 threads/sesions 保存,第二个建议不起作用,因为将在 运行 之前创建 @ LoadBalanced 和基于原型创建的 restTemplate 是没有设置拦截器的:|
我有一个 microservice landscape 配置了 Spring 云发现,所以我可以只使用它们的 ID 访问其他服务实例:
public class MyClass {
@Autowired
@LoadBalanced
private RestTemplate restTemplate;
public String doOtherStuff() {
String results = restTemplate.getForObject("http://stores/stores", String.class);
return results;
}
}
现在我想访问一个需要OAuth2授权的服务。我使用 Keycloak 服务器来提供它,并且 Keycloak 已经提供了一个具有特定 KeycloakRestTemplate. Anyway, how to enhance it with load balancing?
的适配器我们需要创建一个特定的 KeycloakRestTemplate,它将使用 LoadBalancerInterceptor:
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@LoadBalanced
public KeycloakRestTemplate keycloakRestTemplate(
KeycloakClientRequestFactory keycloakClientRequestFactory,
LoadBalancerInterceptor interceptor) {
KeycloakRestTemplate result = new KeycloakRestTemplate(
keycloakClientRequestFactory);
// Add the interceptor for load balancing
result.getInterceptors().add(interceptor);
return result;
}
//More configurations for keycloak
}
所以有机会获得 Authorized / LoadBalanced 模板:
@Autowired
@LoadBalanced
protected KeycloakRestTemplate restTemplate;
另请参阅:
- Add Ribbon load balancing to a vanilla RestTemplate
你的解决方案不是很好,因为
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@LoadBalanced
public KeycloakRestTemplate keycloakRestTemplate(
KeycloakClientRequestFactory keycloakClientRequestFactory,
LoadBalancerInterceptor interceptor) {
KeycloakRestTemplate result = new KeycloakRestTemplate(
keycloakClientRequestFactory);
// Add the interceptor for load balancing
result.getInterceptors().add(interceptor);
return result;
}
没有用,因为你遇到了异常
The dependencies of some of the beans in the application context form a cycle:
...
┌─────┐
| keycloakRestTemplate defined in class path resource [...]
↑ ↓
| ribbonInterceptor defined in class path resource [org/springframework/cloud/client/loadbalancer/LoadBalancerAutoConfiguration$LoadBalancerInterceptorConfig.class]
↑ ↓
| org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration (field private java.util.List org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.restTemplates)
└─────┘
你要做什么?
@Bean
@LoadBalanced
public KeycloakRestTemplate keycloakRestTemplate(
KeycloakClientRequestFactory keycloakClientRequestFactory) {
return new KeycloakRestTemplate(keycloakClientRequestFactory);
}
没有 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 那么你会得到单例,你可以像这样使用它
@Autowired
protected KeycloakRestTemplate restTemplate;
或者你可以像原型
一样定义restTemplate@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@LoadBalanced
public KeycloakRestTemplate keycloakRestTemplate(
KeycloakClientRequestFactory keycloakClientRequestFactory) {
return new KeycloakRestTemplate(keycloakClientRequestFactory);
}
然后像这样使用
@Autowired
@LoadBalanced
protected KeycloakRestTemplate restTemplate;
编辑: 由于循环问题,Xtreme Biker 的解决方案不适用于 SpringBoot 2 和 Keycloak 6,我的第一个建议不是 threads/sesions 保存,第二个建议不起作用,因为将在 运行 之前创建 @ LoadBalanced 和基于原型创建的 restTemplate 是没有设置拦截器的:|