Spring Boot访问GCP Storage获取AccessToken超时问题排查
Spring Boot应用本地运行时可通过代理正常访问GCP Storage,但部署到服务器后抛出错误:Error getting access token for service account: connect timed out。
代理配置代码如下:
@Bean public Storage storage() throws IOException { GoogleCredentials credentials = GoogleCredentials.fromStream( new ByteArrayInputStream(java.util.Base64.getDecoder().decode(keys))); NetHttpTransport.Builder builder = new NetHttpTransport.Builder(); builder.setProxy(new Proxy(Proxy.Type.HTTP,new InetSocketAddress(host,port))); NetHttpTransport httpTransport = builder.build(); HttpTransportFactory hf = new HttpTransportFactory() { @Override public HttpTransport create() { return httpTransport; } }; Storage storage = StorageOptions.newBuilder() .setTransportOptions(HttpTransportOptions.newBuilder().setHttpTransportFactory(hf).build()) .setCredentials(credentials) .build().getService(); return storage; }
使用Base64加密的JSON密钥文件,调试时重复打印以下请求,最终触发socket超时:
POST https://oauth2.googleapis.com/token Accept-Encoding: gzip User-Agent: Google-HTTP-Java-Client/1.27.0 (gzip) Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Content-Length: 811 curl -v --compressed -X POST -H 'Accept-Encoding: gzip' -H 'User-Agent: Google-HTTP-Java-Client/1.27.0 (gzip)' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -d '@-' -- 'https://oauth2.googleapis.com/token' << $$$
疑问:代理配置是否遗漏了什么?
代理认证信息缺失:代码仅配置了代理地址和端口,若服务器代理需要用户名密码认证,会导致连接超时。本地可能无需代理认证或已自动配置,服务器端则未设置。需在
NetHttpTransport.Builder中添加代理认证逻辑:builder.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port))) .setProxyAuthenticator(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(proxyUsername, proxyPassword.toCharArray()); } });Credentials获取Token未走代理:当前仅给Storage客户端配置了代理,但GoogleCredentials请求
oauth2.googleapis.com/token获取Token时,可能未使用该代理。需确保Credentials的请求也走代理:credentials = credentials.createScoped(StorageScopes.all()); // 为Credentials配置相同的代理传输 HttpTransport transport = NetHttpTransport.newBuilder() .setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port))) // 若需要认证则添加ProxyAuthenticator .build(); Storage storage = StorageOptions.newBuilder() .setTransportOptions(HttpTransportOptions.newBuilder().setHttpTransportFactory(() -> transport).build()) .setCredentials(credentials) .build().getService();服务器网络与代理权限限制:检查服务器防火墙是否允许应用访问代理端口;确认代理是否放行
oauth2.googleapis.com和GCP Storage相关域名的流量;本地与服务器的代理网络环境可能存在差异,需核对服务器代理的可用状态。超时时间配置缺失:服务器网络环境可能较慢,默认超时时间不足以完成请求,需显式设置连接和读取超时:
builder.setConnectTimeout(15000, TimeUnit.MILLISECONDS) .setReadTimeout(15000, TimeUnit.MILLISECONDS);系统环境变量未配置:本地可能通过
HTTP_PROXY、HTTPS_PROXY环境变量配置了代理,服务器端未设置。可在服务器部署时添加这两个环境变量,或在代码中显式传递代理参数。
内容的提问来源于stack exchange,提问作者finalVar

