【问题标题】:Kubernetes Issue in Spring Boot Microservices java.net.SocketTimeoutException: connect timed outSpring Boot 微服务中的 Kubernetes 问题 java.net.SocketTimeoutException: connect timed out
【发布时间】:2023-02-03 06:47:13
【问题描述】:

我在 Kubernetes 上运行 Spring Boot 微服务时遇到问题。安装 minikube 后,我启动它并打开它的仪表板。

这是打开仪表板的命令。

1 ) minikube start
2 ) minikube dashboard 

接下来,我通过此命令运行所有服务。

kubectl apply -f k8s

等待一定时间后,我遇到了如下所示的问题。

15:22:37.395 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
org.springframework.cloud.config.client.ConfigClientFailFastException: Could not locate PropertySource and the resource is not optional, failing
 at org.springframework.cloud.config.client.ConfigServerConfigDataLoader.doLoad(ConfigServerConfigDataLoader.java:197)
 at org.springframework.cloud.config.client.ConfigServerConfigDataLoader.load(ConfigServerConfigDataLoader.java:102)
 at org.springframework.cloud.config.client.ConfigServerConfigDataLoader.load(ConfigServerConfigDataLoader.java:61)
 at org.springframework.boot.context.config.ConfigDataLoaders.load(ConfigDataLoaders.java:107)
 at org.springframework.boot.context.config.ConfigDataImporter.load(ConfigDataImporter.java:128)
 at org.springframework.boot.context.config.ConfigDataImporter.resolveAndLoad(ConfigDataImporter.java:86)
 at org.springframework.boot.context.config.ConfigDataEnvironmentContributors.withProcessedImports(ConfigDataEnvironmentContributors.java:116)
 at org.springframework.boot.context.config.ConfigDataEnvironment.processWithProfiles(ConfigDataEnvironment.java:311)
 at org.springframework.boot.context.config.ConfigDataEnvironment.processAndApply(ConfigDataEnvironment.java:232)
 at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:102)
 at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:94)
 at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent(EnvironmentPostProcessorApplicationListener.java:102)
 at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEvent(EnvironmentPostProcessorApplicationListener.java:87)
 at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
 at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
 at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
 at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
 at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:85)
 at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:66)
 at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
 at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120)
 at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:114)
 at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:65)
 at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:344)
 at org.springframework.boot.SpringApplication.run(SpringApplication.java:302)
 at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
 at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
 at com.microservice.orderservice.OrderServiceApplication.main(OrderServiceApplication.java:15)
 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.base/java.lang.reflect.Method.invoke(Method.java:566)
 at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
 at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
 at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
 at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65)
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://config-server-svc:9296/ORDER-SERVICE/default": connect timed out; nested exception is java.net.SocketTimeoutException: connect timed out
 at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:785)
 at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:711)
 at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:602)
 at org.springframework.cloud.config.client.ConfigServerConfigDataLoader.getRemoteEnvironment(ConfigServerConfigDataLoader.java:303)
 at org.springframework.cloud.config.client.ConfigServerConfigDataLoader.doLoad(ConfigServerConfigDataLoader.java:118)
 ... 35 common frames omitted
Caused by: java.net.SocketTimeoutException: connect timed out
 at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)
 at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412)
 at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255)
 at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237)
 at java.base/java.net.Socket.connect(Socket.java:609)
 at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:177)
 at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:508)
 at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:603)
 at java.base/sun.net.www.http.HttpClient.<init>(HttpClient.java:276)
 at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:375)
 at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:396)
 at java.base/sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1253)
 at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1187)
 at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1081)
 at java.base/sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:1015)
 at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:76)
 at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
 at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66)
 at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:776)
 ... 39 common frames omitted

这是我的 deployment.yaml 文件,如下所示。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: auth-service-app
spec:
  selector:
    matchLabels:
      app: auth-service-app
  template:
    metadata:
      labels:
        app: auth-service-app
    spec:
      containers:
        - name: auth-service-app
          image: noyandocker/authservice
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 7777
          env:
            - name: CONFIG_SERVER_URL
              valueFrom:
                configMapKeyRef:
                  name: config-cm
                  key: config_url
            - name: EUREKA_SERVER_ADDRESS
              valueFrom:
                configMapKeyRef:
                  name: eureka-cm
                  key: eureka_service_address
            - name: DB_HOST
              valueFrom:
                configMapKeyRef:
                  name: mysql-cm
                  key: hostname

---

apiVersion: v1
kind: Service
metadata:
  name: auth-service-svc
spec:
  selector:
    app: auth-service-app
  ports:
    - port: 80
      targetPort: 7777

这是配置映射 yaml 文件

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-cm
data:
  config_url: "config-server-svc"

---

apiVersion: v1
kind: ConfigMap
metadata:
  name: eureka-cm
data:
  eureka_service_address: "http://eureka-0.eureka:8761/eureka"

---

apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-cm
data:
  hostname: "mysql-0.mysql"

这是 config-server-deployment.yaml 文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: config-server-app
spec:
  selector:
    matchLabels:
      app: config-server-app
  template:
    metadata:
      labels:
        app: config-server-app
    spec:
      containers:
        - name: config-server-app
          image: noyandocker/configserver
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 9296
          readinessProbe:
            httpGet:
              path: /actuator/health
              port: 9296
            initialDelaySeconds: 20
            timeoutSeconds: 10
            periodSeconds: 3
            failureThreshold: 2
          livenessProbe:
            httpGet:
              path: /actuator/health
              port: 9296
            initialDelaySeconds: 30
            timeoutSeconds: 2
            periodSeconds: 8
            failureThreshold: 1
          env:
            - name: EUREKA_SERVER_ADDRESS
              valueFrom:
                configMapKeyRef:
                  name: eureka-cm
                  key: eureka_service_address

---

apiVersion: v1
kind: Service
metadata:
  name: config-server-svc
spec:
  selector:
    app: config-server-app
  ports:
    - port: 80
      targetPort: 9296

我以为所有的服务都会同时启动。 Config Server 是所有其他服务(如 auth 服务)的依赖服务,在 Config Server 服务启动并运行之前,此 Auth 服务不应启动。

已编辑

有人对我说了这个消息。

在 Kubernetes 中,所有服务将同时启动。 Config Server 是所有其他服务的依赖服务。即订单、付款和产品。

Sp 理想情况下,在 COnfig Server 服务启动并运行之前,您的 Order 服务不应启动。我们看到在 Docker 中使用 Depends_on 属性实现了类似的事情。

在 Kubernetes 中,我们可以使用 Probes 来实现它。您需要为 Config Server 的应用程序实施 Lineness 和 Readiness 探测。

您为订单服务添加一个配置,以检查配置服务器是否已启动,然后它将启动。

我仍然无法解决问题。

我怎样才能做到这一点?

这是我的仓库:Link

这是我的码头工人中心:Link

这是 git 后端系统:Link

【问题讨论】:

  • 嘿,我也坚持在 docker 部分。在订单服务中,我应该在运行 docker 时传递什么来代替 DB_SERVER env 变量?我通过每日代码缓冲区为这门课程创建了一个小组。您可以通过以下链接加入: Discord:discord.gg/FVUgRxCw Telegram:t.me/+PP7q6Fq4AeQ0ZTg1

标签: java spring-boot kubernetes devops minikube


【解决方案1】:

在微服务架构中工作时,您不能依赖服务之间的依赖关系。如果由于硬件问题导致单个服务关闭怎么办?所有平台都无法使用?

事实上,每个微服务都必须为不可用的服务做好准备。您可以使用断路器来做到这一点。据我所知,Kubernetes 不支持这种依赖。

不过,我发现了一些可以在这里使用的技巧:https://www.alibabacloud.com/blog/kubernetes-demystified-solving-service-dependencies_594110

在您的情况下,使用启动其他服务时不可用的服务配置服务器,您可以为服务添加一些重试机制。这样,他们将在 5 或 5 次尝试后尝试访问服务配置服务器。看这里,https://cloud.spring.io/spring-cloud-static/spring-cloud-config/2.1.4.RELEASE/multi/multi__spring_cloud_config_client.html#config-client-retry

【讨论】:

  • 我为此添加了健康检查以检查它是否正常运行。我仍然无法解决它。如果您有任何相关信息,是否可以对其进行测试?
  • 我无法修复它。如果您不介意,可以查看 deployment.yaml 文件吗?
  • 现在是什么问题?配置服务是否已启动但为时已晚?
  • 配置服务器启动,但我认为它最近工作了一点。如果你不介意,你可以测试一下吗?我也编辑了我的帖子。
  • 我没有看到包含配置服务器连接的引导程序配置(在 orderservice 中)文件。在这个文件中,你应该添加我在上一段中解释过的“重试”配置。
猜你喜欢
  • 2023-02-01
  • 2014-01-25
  • 2019-02-20
  • 2018-02-02
  • 2020-01-13
  • 2023-02-09
  • 2017-03-22
  • 2021-09-11
  • 2023-02-03
相关资源
最近更新 更多