Zuul Implementing WeightedResponseTimeRule Error - VIP address for client null is null - spring

I'm encountering this VIP address null white implementing weightedResponseTimeRule for my Zuul gateway.
Did i do it correctly? implementing a config that will implement weightedRule.
I want to route my request to my 2 or more instance.
Error creating bean with name 'ribbonServerList' defined in org.springframework.cloud.netflix.ribbon.eureka.EurekaRibbonClientConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.netflix.loadbalancer.ServerList]: Factory method 'ribbonServerList' threw exception; nested exception is java.lang.NullPointerException: VIP address for client null is null
Currently my Config for Ribbon
#Configuration
public class GatewayRibbonConfiguration {
#Bean
public IClientConfig ribbonClientConfig(){
return new DefaultClientConfigImpl();
}
#Bean
public IPing ribbonPing(IClientConfig config) {
return new PingUrl();
}
#Bean
public IRule ribbonRule(IClientConfig config) {
return new WeightedResponseTimeRule();
}
}
Application
#SpringBootApplication
#EnableDiscoveryClient
#EnableZuulProxy
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
#Bean
public Prefilter prefilter(){
return new Prefilter();
}
}
bootstrap.yml
spring:
application:
name: gateway
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
my properties
server:
port: 8080
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 20000
ribbon:
ReadTimeout: 20000
ConnectTimeout: 20000
zuul:
prefix: /api
ignoredServices: '*'
host:
connect-timeout-millis: 20000
socket-timeout-millis: 20000
routes:
kicks-service:
path: /kicks/**
serviceId: kicks-service
stripPrefix: false
sensitiveHeaders:
kicks-inventory:
path: /inventory/**
serviceId: kicks-inventory
stripPrefix: false
sensitiveHeaders:

Related

Spring Cloud Config - Vault and JDBC backend with JDBC creds in Vault

I am attempting to modify our current Spring Cloud Config server which has only a JDBC backend to include a Vault backend in order make the JDBC connection credentials secret.
VAULT:
Listener 1: tcp (addr: "127.0.0.1:8400", cluster address: "127.0.0.1:8401", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
C:\apps\HashiCorp>vault kv get secret/my-secrets
=============== Data ===============
Key Value
--- -----
spring.datasource.password yadayadayada
spring.datasource.username cobar
bootstrap.yml
server:
port: 8888
spring:
application:
name: config-server
cloud:
config:
allowOverride: true
server:
jdbc:
sql: SELECT prop_key, prop_value from CloudProperties where application=? and profile=? and label=?
order: 2
#https://cloud.spring.io/spring-cloud-config/reference/html/#vault-backend
vault:
scheme: http
host: localhost
port: 8400
defaultKey: my-secrets
order: 1
application.yml
spring:
main:
banner-mode: off
allow-bean-definition-overriding: true
datasource:
url: jdbc:mysql://localhost/bootdb?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false
#username: cobar
#password: yadayadayada
driverClassName: com.mysql.jdbc.Driver
hikari:
connection-timeout: 60000
maximum-pool-size: 5
cloud:
vault:
scheme: http
host: localhost
port: 8400
defaultKey: my-secrets
token: root.RIJQjZ4jRZUS8mskzfCON88K
The spring.datasource username and password are not being retrieved from the vault.
2021-12-01 12:43:39.927 INFO 5992 --- [ restartedMain]: The following profiles are active: jdbc,vault
2021-12-01 12:43:46.123 ERROR 5992 --- [ restartedMain] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Exception during pool initialization.
Login failed for user ''. ClientConnectionId:a32
Move properties from bootstrap to application context.
Call Vault endpoint to obtain secrets and use these to configure Datasource to JDBC backend.
#Slf4j
#SpringBootApplication
#EnableConfigServer
public class ConfigServerApplication {
public static final String VAULT_URL_FRMT = "%s://%s:%s/v1/secret/%s";
#Autowired
private Environment env;
public static void main(String[] args) {
SpringApplication app = new SpringApplication(ConfigServerApplication.class);
app.addListeners(new ApplicationPidFileWriter());
app.addListeners(new WebServerPortFileWriter());
app.run(args);
}
#Order(1)
#Bean("restTemplate")
public RestTemplate restTemplate() {
return new RestTemplate();
}
#Configuration
public class JdbcConfig {
#Autowired
private RestTemplate restTemplate;
#Bean
public DataSource getDataSource() {
Secrets secrets = findSecrets();
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.url(secrets.getData().get("spring.datasource.url"));
dataSourceBuilder.username(secrets.getData().get("spring.datasource.username"));
dataSourceBuilder.password(secrets.getData().get("spring.datasource.password"));
return dataSourceBuilder.build();
}
private Secrets findSecrets() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("X-Vault-Token", env.getProperty("spring.cloud.vault.token"));
HttpEntity request = new HttpEntity(httpHeaders);
String url = String.format(VAULT_URL_FRMT,
env.getProperty("spring.cloud.vault.scheme"),
env.getProperty("spring.cloud.vault.host"),
env.getProperty("spring.cloud.vault.port"),
env.getProperty("spring.cloud.vault.defaultKey")
);
return restTemplate.exchange(url, HttpMethod.GET, request, Secrets.class, 1).getBody();
}
}
}
#Getter
#Setter
public class Secrets implements Serializable {
private String request_id;
private String lease_id;
private boolean renewable;
private Duration lease_duration;
private Map<String, String> data;
}
Now you have a Cloud Config with a JDBC backend you can keep the Database properties secret.

Error while using custom loadbalancer for spring cloud loadbalancer with healthcheck configuration

I am using a static list (SimpleDiscoveryClient) to loadbalance using spring cloud loadbalancer. Using StickySession Loadbalancer rule in https://github.com/fitzoh/spring-cloud-commons/blob/e10997b6141ff560479ef7065c3547f1f59360c8/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/core/StickySessionLoadBalancer.java.
My WebClientConfig class:
#Configuration
#LoadBalancerClient(name = "testservice", configuration = CustomLoadBalancerConfiguration.class)
public class WebClientConfig {
#LoadBalanced
#Bean
WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
Custom LoadBalancer Configuration class:
public class CustomLoadBalancerConfiguration {
#Bean
ReactorLoadBalancer<ServiceInstance> StickySessionLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new StickySessionLoadBalancer(loadBalancerClientFactory
.getLazyProvider(name, ServiceInstanceListSupplier.class),
name);
}
#Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withHealthChecks()
.build(context);
}
}
Posting my yml here :
spring:
application:
name: sample
cloud:
discovery:
client:
health-indicator:
enabled: false
simple:
instances:
testservice:
- uri: http://localhost:8082
- uri: http://localhost:8081
loadbalancer:
configurations: health-check
cache:
enabled: false
health-check:
path:
default: /actuator/health
interval: 10000
gateway:
routes:
- id: testrouting
path: /user/*
uri: lb://testservice
predicates:
- Method=GET,POST
- Path=/user/**
It's all according to the official documentation. But with the customloadbalancer rule (Stickysession Loadbalancer), the healthchecks to servers are not happening to checkif the servers are alive or not. The server list is always empty (all servers are marked as not alive).

Zuul throwing 404 No meesage Available error

I have my below app (microservices) which is successfully registered to Eureka server.I t has below Rest end point
#Controller
#RequestMapping("v1/base/")
public class PersonController {
#PostMapping
#RequestMapping(value="/personid")
public ResponseEntity< ?> getPersonList(){
return ResponseEntity.ok("All person list");
}
The properties file for person-application
eureka:
instance:
appname: person-application
client:
enabled: true
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka/
My zuul server yml file config is is .
server:
port:9000
servlet:
contextPath: /zuulapp
zuul:
routes:
person:
path: /v1/base/**
serviceId: person-application
When i call hit the rest point localhost:9000/zuulapp/person/personid i get the below error.How do i resolve this error
{
"timestamp":"2019-10-08T12:42:09.479+0000",
"status":404,
"error":"Internal Server Error",
"message":"No Message available"
"path" : "/zuulapp/person/personid"
}
Since the registered path in the zuul of the application is "/v1/base/**"
try this one: delete the contextpath properties then replace it with zuul.prefix properties.
server:
port:9000
zuul:
prefix: /zuulapp
routes:
person:
path: /person/**
serviceId: person-application
Now try checking this endpoint:
localhost:9000/zuulapp/person/v1/base/personid
try this in the controller class:
#RestController
#RequestMapping("/v1/base/")
public class PersonController {
#GetMapping(value="/personid")
public ResponseEntity< ?> getPersonList(){
return ResponseEntity.ok("All person list");
}

FeignException ServiceUnavailable: Load balancer does not contain an instance for the service match-result-service

I fail to understand, nor find any explanation about how can I fix the exception in subject.
This is the main code I use:
Eureka Server
application:
...
#SpringBootApplication
#EnableEurekaServer
public class BbSimApplication {
public static void main(String[] args) {
SpringApplication.run(BbSimApplication.class, args);
}
}
application.yml:
server.port : 8088
spring:
application:
name : bbsim-discovery-server
eureka:
server:
evictionIntervalTimerInMs: 3000
response-cache-update-interval-ms: 3000
wait-time-in-ms-when-sync-empty: 0
peer-node-read-timeout-ms : 10000
client:
registerWithEureka: false
fetchRegistry: false
service-url:
defaultZone: http://localhost:${server.port}/eureka
Controller class:
#RestController
public class WebController {
#Autowired private WebService webService;
#GetMapping("/matchresultbyids")
public MatchStats matchResult(#RequestParam Long homeId, #RequestParam Long awayId){
return webService.matchResult(homeId, awayId);
}
}
Manager Service
application:
#SpringBootApplication
#EnableFeignClients
#EnableDiscoveryClient
public class BBSimManagerServiceApplication {
public static void main(String[] args) {
SpringApplication.run(BBSimManagerServiceApplication.class, args);
}
}
application.yaml:
server.port: 9903
spring:
application.name: bbsim-manager-service
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_URI:http://localhost:8088/eureka}
registryFetchIntervalSeconds: 1
# register-with-eureka: true
# fetch-registry: true
instance:
leaseRenewalIntervalInSeconds: 1
Client interface:
#FeignClient("match-result-service")
public interface MatchResultClient {
#GetMapping("/matchresultbyids")
MatchStats getMatchResult();
}
Controller class:
#RestController
public class BbsimManagerController {
#Autowired
MatchResultClient matchStatsClient;
#GetMapping("/matchresultbyids")
public MatchStats matchResult(){
return matchStatsClient.getMatchResult();
}
}
MatchResult Service
application:
#SpringBootApplication
#EnableDiscoveryClient
public class MatchResultServiceApplication {
public static void main(String[] args) {
SpringApplication.run(MatchResultServiceApplication.class, args);
}
}
application.yml:
server.port: 9901
spring:
application:
name: match-result-service
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8088/eureka/
registryFetchIntervalSeconds: 1
instance:
leaseRenewalIntervalInSeconds: 1
Controller:
#RestController
public class WebController {
#Autowired private WebService webService;
#GetMapping("/matchresultbyids")
public MatchStats matchResult(){
return webService.matchResult();
}
}
When I try to execute:
http://localhost:9903/matchresultbyids
I get the exception:
o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is feign.FeignException$ServiceUnavailable: [503] during [GET] to [http://match-result-service/matchresultbyids?homeId=0&awayId=1] [MatchResultClient#getMatchResult()]: [Load balancer does not contain an instance for the service match-result-service]] with root cause
feign.FeignException$ServiceUnavailable: [503] during [GET] to [http://match-result-service/matchresultbyids?homeId=0&awayId=1] [MatchResultClient#getMatchResult()]: [Load balancer does not contain an instance for the service match-result-service]
Can you advise me what is wrong and how to fix it?
Thank you all.
It may be related to OpenFeign bug. You can try to upgrade it to the version >= v3.0.6.
If you use spring-cloud-dependencies the version >= v2020.0.5 should be also ok.

Feign Client cannot communicate with a method inside of eureka server

I have a eureka server configured and inside that eureka server I have written a rest api. Now I have a eureka client service and I am trying to call one of the method of eureka service using feign from client service. But I am getting an error "Load balancer does not have available server for client: eureka-service".
But If I call api from a client service to another client service using feign then it is giving successful result. Just can't call API from eureka service.
eureka-service is application name of my eureka server.
#EnableEurekaServer
#SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
#RestController
#RequestMapping("test")
public class TestController {
#GetMapping
public String test(){
return "test success";
}
}
bootstrap.yml of eureka service
eureka:
client:
registerWithEureka: false
fetchRegistry: false
eureka-server-read-timeout-seconds: 60
eureka-server-connect-timeout-seconds: 60
serviceUrl:
defaultZone: http://localhost:8763/eureka/
dashboard:
enabled: true
spring:
application:
name: eureka-service
And client service is:
#SpringBootApplication
#EnableFeignClients
#EnableDiscoveryClient
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
#FeignClient("eureka-service")
public interface TestFeign {
#GetMapping("test")
String test();
}
bootstrap.yml of client service
eureka:
client:
registerWithEureka: true
fetchRegistry: true
eureka-server-read-timeout-seconds: 60
eureka-server-connect-timeout-seconds: 60
serviceUrl:
defaultZone: http://localhost:8763/eureka/
spring:
application:
name: client-service
feign:
hystrix:
enabled: true
ERROR log : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.netflix.hystrix.exception.HystrixRuntimeException: TestFeign#test() failed and no fallback available.] with root cause
com.netflix.client.ClientException: Load balancer does not have available server for client: eureka-service.
How can we solve this issue. Thanks for help in advance.
You need to scan your interfaces that declare they are FeignClients with the #EnableFeignClients annotation in your main class and add the feign.hystrix.enabled=true property.

Resources