I’m getting a NotFoundException: 503 SERVICE_UNAVAILABLE
exception in the gateway-server logs. I’m running microservices in docker containers. I have an auth-service
microservice which handles authentication and Jwt. I can connect directly to the auth-service using Postman and register, validate and receive tokens via the auth-service’s AuthController. However, using the gateway causes the 503 error. Since the problem is with the gateway, I will highlight pertinent gateway code:
SecurityConfig
package com.microservices.gatewayserver.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
//Configures security settings for the gateway server. Authentication uses JWT tokens
// for the pathMatchers and disables CSRF protection.
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http.authorizeExchange(exchanges -> exchanges
.pathMatchers("/login-service/**").authenticated()
.pathMatchers("/employee-service/**").authenticated()
.pathMatchers("/registration-service/**").authenticated()
.pathMatchers("/auth-service/**").permitAll())
//.pathMatchers("/actuator/**").permitAll())
.oauth2ResourceServer()
.jwt();
http.csrf().disable();
return http.build();
}
}
GatewayServerApplication
package com.microservices.gatewayserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.web.bind.annotation.RestController;
@RestController
@SpringBootApplication
@EnableDiscoveryClient
@LoadBalancerClient(name= "auth-service")
public class GatewayServerApplication {
public static final Logger LOGGER = LoggerFactory
.getLogger(GatewayServerApplication.class);
public static void main(String[] args) {
SpringApplication.run(GatewayServerApplication.class, args);
}
application.yml
server:
port: 8097
spring:
application:
name: gateway-service
output:
ansi:
enabled: always
cloud:
config:
enabled: false
gateway:
discovery:
locator:
enabled: true
routes:
- id: auth-service
uri: lb://auth-service
predicates:
- Path=/auth-service/**
filters:
- RewritePath=/auth-service/(?<path>.*), /${path}
- id: employee-service
uri: lb://employee-service
predicates:
- Path=/employee/**
filters:
- RewritePath=/employee/(?<path>.*), /${path}
- id: login-service
uri: lb://login-service
predicates:
- Path=/login/**
filters:
- RewritePath=/login/(?<path>.*), /${path}
- id: registration-service
uri: lb://registration-service
predicates:
- Path=/registration/**
filters:
- RewritePath=/registration/(?<path>.*), /${path}
- id: openapi
uri: http://localhost:${server.port}
predicates:
- Path=/v3/api-docs/**
filters:
- RewritePath=/v3/api-docs/(?<path>.*), /${path}/v3/api-docs
main:
web-application-type: reactive
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: http://localhost:7080/realms/master/protocol/openid-connect/certs
eureka:
client:
serviceUrl:
defaultZone: http://discovery-service-container:8761/eureka/
springdoc:
swagger-ui:
urls:
- name: auth
url: /v3/api-docs/auth
- name: employee
url: /v3/api-docs/employee
- name: login
url: /v3/api-docs/login
- name: registration
url: /v3/api-docs/registration
logging:
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%X{traceId:-},%X{spanId:-}] ${LOG_LEVEL_PATTERN:-%5p} %m%n"
level:
springframework:
boot:
autoconfigure: DEBUG
web: DEBUG
root: DEBUG
POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<artifactId>gateway-server</artifactId>
<version>3.0.6-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version>
<spring-cloud.version>2022.0.2</spring-cloud.version>
<sonar.moduleKey>${project.artifactId}</sonar.moduleKey>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</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-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bom</artifactId>
<version>${micrometer-tracing.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
Stacktrace
2023-05-25 05:45:20 [,] -DEBUG Trying to match using PathMatcherServerWebExchangeMatcher{pattern='/auth-service/**', method=null}
2023-05-25T05:45:20.457679873Z 2023-05-25 05:45:20 [,] -DEBUG Checking match of request : '/auth-service/register'; against '/auth-service/**'
2023-05-25T05:45:20.457699175Z 2023-05-25 05:45:20 [,] -DEBUG matched
2023-05-25T05:45:20.457742344Z 2023-05-25 05:45:20 [,] -DEBUG Checking authorization on '/auth-service/register' using org.springframework.security.config.web.server.ServerHttpSecurity$AuthorizeExchangeSpec$Access$$Lambda$648/0x00000008010ce248@1b9bc02
2023-05-25T05:45:20.458327743Z 2023-05-25 05:45:20 [,] -DEBUG Authorization successful
2023-05-25T05:45:20.459204178Z 2023-05-25 05:45:20 [,] -DEBUG Route matched: auth-service
2023-05-25T05:45:20.459229258Z 2023-05-25 05:45:20 [,] -DEBUG Mapping [Exchange: POST http://localhost:8097/auth-service/register] to Route{id='auth-service', uri=lb://auth-service, order=0, predicate=Paths: [/auth-service/**], match trailing slash: true, gatewayFilters=[[[RewritePath /auth-service/(?<path>.*) = '/${path}'], order = 1]], metadata={}}
2023-05-25T05:45:20.459233539Z 2023-05-25 05:45:20 [,] -DEBUG [afe63e91-2] Mapped to org.springframework.cloud.gateway.handler.FilteringWebHandler@363dab18
2023-05-25T05:45:20.459345964Z 2023-05-25 05:45:20 [,] -DEBUG Sorted gatewayFilterFactories: [[GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter@6a74d228}, order = -2147483648], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@720653c2}, order = -2147482648], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@36bc415e}, order = -1], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardPathFilter@3e134896}, order = 0], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.GatewayMetricsFilter@2e3a5237}, order = 0], [[RewritePath /auth-service/(?<path>.*) = '/${path}'], order = 1], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@349d0836}, order = 10000], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter@301d8120}, order = 10150], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.LoadBalancerServiceInstanceCookieFilter@6d367020}, order = 10151], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@72ba28ee}, order = 2147483646], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyRoutingFilter@72458efc}, order = 2147483647], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardRoutingFilter@6a714237}, order = 2147483647]]
2023-05-25T05:45:20.460796164Z 2023-05-25 05:45:20 [,] - WARN No servers available for service: auth-service
2023-05-25T05:45:20.461939954Z 2023-05-25 05:45:20 [,] -DEBUG [afe63e91-2] Resolved [NotFoundException: 503 SERVICE_UNAVAILABLE "Unable to find instance for auth-service"] for HTTP POST /auth-service/register
2023-05-25T05:45:20.462477063Z 2023-05-25 05:45:20 [,] -DEBUG [afe63e91-2] Encoding [{timestamp=Thu May 25 05:45:20 GMT 2023, path=/auth-service/register, status=503, error=Service Unav (truncated)...]
2023-05-25T05:45:20.467139970Z 2023-05-25 05:45:20 [,] -DEBUG [afe63e91-2, L:/172.27.0.9:8097 - R:/172.27.0.1:58344] Decreasing pending responses, now 0
2023-05-25T05:45:20.468226365Z 2023-05-25 05:45:20 [,] -DEBUG [afe63e91-2] Completed 503 SERVICE_UNAVAILABLE
2023-05-25T05:45:20.468294940Z 2023-05-25 05:45:20 [,] -DEBUG [afe63e91-2, L:/172.27.0.9:8097 - R:/172.27.0.1:58344] Last HTTP response frame
2
Answers
you need to use a service discovery like netflix eureka to register your applications like auth service in this service and gateway can find auth service by name ->
I think maybe somehow if you define DNS in your docker and setting the auth service name to the auth service ip and port no need to using discovery service
The log traces you’ve shared suggest that your application is attempting to connect to a service labeled ‘auth-service’, but it can’t find any instances of that service. This scenario is typically seen in microservices architectures, where services discover each other using tools like Netflix’s Eureka or Kubernetes service discovery.
Looking at the message "No servers available for service: auth-service", it seems that the service discovery component (likely Eureka, based on your POM file) isn’t able to locate any registered ‘auth-service’ instances.
Here’s a list of potential issues that you might want to investigate:
Confirm whether the ‘auth-service’ is currently operational. If it’s not, you’ll need to get it running.
If the ‘auth-service’ is indeed running, ensure that it’s properly registered with the service discovery component (possibly Eureka). To verify this, you can check the Eureka dashboard or inspect the logs from ‘auth-service’.
Make sure that ‘auth-service’ and the gateway are on the same network. If they aren’t, network issues might prevent service discovery from functioning correctly.
Review the ‘auth-service’ configuration. It should be set up with the correct Eureka server address, and its instance name should be ‘auth-service’.
Sometimes, the issue can be a matter of timing. One service might start and try to discover other services before they’ve had a chance to register with the service discovery tool. In such a case, implementing a retry mechanism or ensuring services start in the right order might help.
If you’re still experiencing issues after checking these potential problems, please share more information or context about your setup so that I can provide more targeted assistance.