【问题标题】:未安装提供程序“gs”
【发布时间】:2021-05-14 13:44:59
【问题描述】:

我在这里找到了两篇类似的帖子,但一篇没有得到答复,另一篇是关于 android 的。我有一个 Spring Boot 项目,我想在我的应用程序中访问 GCP 存储文件。

在本地一切正常,我可以访问我的存储桶并在我的存储中读取和存储文件。但是当我将它上传到 gcp kubernetes 时,我得到了以下异常:

"java.nio.file.FileSystemNotFoundException: Provider "gs" not 安装在 java.nio.file.Paths.get(Paths.java:147) ~[na:1.8.0_212] 在 xx.xx.StorageService.saveFile(StorageService.java:64) ~[classes!/:0.3.20-SNAPSHOT]

我出现的代码行如下:

public void saveFile(MultipartFile multipartFile, String path) {
    String completePath = filesBasePath + path;
    
    Path filePath = Paths.get(URI.create(completePath)); // <- exception appears here
    Files.createDirectories(filePath);
    multipartFile.transferTo(filePath);
        
}

}

completePath 可能会导致类似“gs://my-storage/path/to/file/image.jpg”

我有以下依赖项:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-gcp-starter-storage</artifactId>
    <version>1.2.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-nio</artifactId>
    <version>0.122.5</version>
</dependency>

有人知道在哪里看吗? 除了基础设施之外,唯一真正的区别是我没有明确不在 kubernetes 上使用身份验证,因为根据文档,它不是必需的

从 Google Cloud Platform 使用 Google Cloud 库时 Compute Engine、Kubernetes Engine 或 App Engine 等环境, 无需额外的身份验证步骤。

【问题讨论】:

  • “本地一切正常”是指在容器内或本地机器上运行 Spring Boot 应用程序?
  • 本地在我的机器上的eclipse

标签: java kubernetes google-cloud-storage nio spring-cloud-gcp


【解决方案1】:

看起来这里传统的 Spring Boot 打包并没有以所需的方式打包依赖项。通常你会看到类似的东西:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>2.4.5</version>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

但是,要访问“gs”提供程序,它需要位于“lib/”文件夹中。您可以通过复制依赖项然后创建 JAR 来手动打包它(这是基于springboot-helloworld 示例:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <executions>
      <execution>
          <id>copy-dependencies</id>
          <phase>prepare-package</phase>
          <goals>
              <goal>copy-dependencies</goal>
          </goals>
          <configuration>
              <outputDirectory>
                  ${project.build.directory}/lib
              </outputDirectory>
          </configuration>
      </execution>
  </executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
    <archive>
        <manifest>
            <addClasspath>true</addClasspath>
            <classpathPrefix>lib/</classpathPrefix>
            <mainClass>
              com.example.appengine.springboot.SpringbootApplication
            </mainClass>
        </manifest>
    </archive>
</configuration>
</plugin>

原为posted on GitHub

【讨论】:

    【解决方案2】:

    gs:// 语法不是通用的;某些 Google 工具和服务(例如 gsutil)支持它,但许多 URL 库并不知道它。

    您可以更改为使用其中一种 GCS API 的 HTTP 语法,例如,

    https://my-storage.storage.googlapis.com/path/to/file/image.jpg
    

    请注意,上面的 HTTP URL 将需要身份验证,因此您可能希望使用像 google-cloud-java 这样支持发出经过身份验证的 GCS 请求的库。

    【讨论】:

    • 是的,我使用 spring lib 进行 gcp 存储。我后来改用google-cloud-storage,问题仍然存在。我不知道为什么它在本地工作而不是在云本身内工作。我还认为它可能与java版本有关,因为在本地我使用jdk 11并将其限制为8,而在k8s上我使用alpine jdk 8(这种组合之前产生了一些奇怪的行为)但是在将docker镜像升级到jdk 11之后什么都没有也变了。
    • google-cloud-storage 也不支持该语法。除了您明确知道的情况外,您应该假设什么都不做。这不是一种广泛采用的语法。
    • 是的,我明白了。 gs 是一种仅适用于 google 的特殊格式,但我认为它是在使用其中一个依赖项时提供的。如果我没有完全弄错的话,官方 java-storage-nio github (github.com/googleapis/java-storage-nio) 上的用法是这样描述的。除此之外,我仍然不清楚我的本地运行时和我的谷歌云运行时之间的区别在哪里。在本地它工作得很好,在 k8s 上它会抛出提到的异常
    • @tagtraeumer 与“在本地它工作得很好”,你的意思是你尝试在本地执行 jar 应用程序还是仅仅从 Eclipse 执行?也许你为你的应用创建的 jar 包遗漏了一些东西
    【解决方案3】:

    按照Averi Kitsch's answer 并使用相同的springboot-helloworld 示例,我能够在更新pom.xml 后使其在本地工作。但是,就像它为您所做的一样,它仅在我在本地运行它时才有效,而当我将它部署在 Google Cloud 上时它会失败。问题是我使用的 Dockerfile 忽略了 /target/lib 目录中的所有 jar 文件,我需要将该目录复制到映像中。请注意,我使用的是 Google Cloud Run,但我相信这应该适用于大多数使用 Dockerfile 的部署。

    这就是我最终得到的结果:

    Dockerfile

    FROM maven:3.8-jdk-11 as builder
    
    WORKDIR /app
    COPY pom.xml .
    COPY src ./src
    
    RUN mvn package -DskipTests
    
    FROM adoptopenjdk/openjdk11:alpine-jre
    
    COPY --from=builder /app/target/springboot-helloworld-*.jar /springboot-helloworld.jar
    
    # IMPORTANT! - Copy the library jars to the production image!
    COPY --from=builder /app/target/lib /lib
    
    CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/springboot-helloworld.jar"]
    

    pom.xml

    <?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>
      <groupId>com.example.appengine</groupId>
      <artifactId>springboot-helloworld</artifactId>
      <version>0.0.1-SNAPSHOT</version>
    
      <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.4</version>
        <relativePath/>
      </parent>
    
      <properties>
        <maven.compiler.target>11</maven.compiler.target>
        <maven.compiler.source>11</maven.compiler.source>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
          <groupId>com.google.cloud</groupId>
          <artifactId>google-cloud-nio</artifactId>
          <version>0.123.8</version>
        </dependency>
      </dependencies>
    
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
              <execution>
                <id>copy-dependencies</id>
                <phase>prepare-package</phase>
                <goals>
                  <goal>copy-dependencies</goal>
                </goals>
                <configuration>
                  <outputDirectory>
                    ${project.build.directory}/lib
                  </outputDirectory>
                </configuration>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
              <archive>
                <manifest>
                  <addClasspath>true</addClasspath>
                  <classpathPrefix>lib/</classpathPrefix>
                  <mainClass>
                    com.example.appengine.springboot.SpringbootApplication
                  </mainClass>
                </manifest>
              </archive>
            </configuration>
          </plugin>
        </plugins>
      </build>
    
    </project>
    

    【讨论】:

      猜你喜欢
      • 2013-10-19
      • 1970-01-01
      • 1970-01-01
      • 2022-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多