原本碎碎念系列是发布在QQ空间的,但是由于这次可能篇幅比较长,而且最近和谐的也是越来越厉害了,不适合写长篇大论,因此这次就发布到博客里吧。反正基本上内容也就是折腾一些乱七八糟的东西。
成功解决谷歌云Proxy无效的疑惑
最近不怎么写技术笔记了,是因为在做实际的个人项目,一个自动检测、备份B站收藏夹视频的工具,缓存、备份,然后上传到谷歌云。
这几天一直在被谷歌云的Api所困扰,由于国家防火墙的存在,要想薅谷歌云的无限容量网盘的羊毛,毫无疑问要使用代理,于是想像迅雷之类的下载软件那样,做成可配置的代理,虽然有一堆可以代理全局的软件,但是我懒得在Linux上部署这些玩意(对,重点还是懒)。但不知道为什么,明明在代码里面设置了Proxy,依旧什么都没发生,连接不通
Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress("127.0.0.1",1080));
final NetHttpTransport net = new NetHttpTransport.Builder()
.setProxy(proxy)
.trustCertificates(GoogleUtils.getCertificateTrustStore())
.build();
Drive service = new Drive.Builder(net, JSON_FACTORY,GoogleCredential.fromStream(in))
....
翻遍了整个Stack Overflow依旧没有找到原因,甚至有一个答案和我的代码一模一样,但是我的就是没有生效,这就很奇怪。
最后我怀疑是版本问题,于是上Maven找了最新的开发工具包,发现在最新的代码里面,GoogleCredential被标注过时了,注释里提示使用最新的验证包
* @since 1.7
* @author Yaniv Inbar
* @deprecated Please use <a href="https://github.com/googleapis/google-auth-library-java">
* google-auth-library</a> for handling Application Default Credentials and other non-OAuth2
* based authentication.
*/
实际上这个包我之前找到过,但是也仅仅发现它可以用来获取AccessToken,好像并不能和Drive的代码混着用,因为Drive的参数指明了需要一个实现了HttpRequestInitializer的接口的对象,而新包里面返回的是一个GoogleCredentials。
我只好继续从源代码着手看问题出在哪儿,在追踪代码的过程中发现,构造NetHttpTransport的方法总是会被执行两遍,而第二遍的时候Proxy就会莫名其妙的变成Null,一开始我以为是在某个地方,NetHttpTransport被替换了,但后来发现第二次执行是在GoogleCredential.fromStream(in)中,在这个方法里面使用了一个单例的HttpTransport
public static HttpTransport getDefaultTransport() {
return TransportInstanceHolder.INSTANCE;
}
private static class TransportInstanceHolder {
static final HttpTransport INSTANCE = new NetHttpTransport();
}
这里也验证了我之前学习JVM的时候学到过的,【类的加载只会在类的第一次主动使用时触发】JVM学习(一) 类加载
所以我们之前一直以来做过的努力,并非全部白费.jpg
而这里这个Transport是默认构造器,并没有传入Proxy!
因此答案就很明显了,超时的连接没有使用我们设置的Proxy,是因为这个连接是由GoogleCredential发起的,以非OAuth2方式请求授权接口,用于获取AccessToken,这是整个流程的第一步,由于没有使用代理,就华丽丽的的超时了==。
解决方案也很明了了,经查看GoogleCredential有另一个重载方法:
public static GoogleCredential fromStream(InputStream credentialStream, HttpTransport transport,
JsonFactory jsonFactory) throws IOException
这里支持传入我们自定义的HttpTransport,用于构建自定义的RequestFactory。
不过既然都引入了新版本,这个类也被标注为不推荐了,那就研究一下新版本怎么和Api整合吧。
最后在google-auth-library的github描述里面找到了这么一段话:
Using Credentials with google-http-client
Credentials provided by google-auth-library can be used with Google's HTTP-based clients. We provide a HttpCredentialsAdapter which can be used as an HttpRequestInitializer.
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.services.bigquery.Bigquery;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credentials);
Bigquery bq = new Bigquery.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer)
.setApplicationName(APPLICATION_NAME)
.build();
嗯,完美解决,锵锵。
主力系统换为Ubuntu Desktop
自从我推完《海猫鸣泣之时》,我发现自己好像也并没有太大的游戏需求,因此台式机完全就变成工作机了,而Windows虽然功能齐全,但是对于经常把项目往服务器上丢的人来说,有一个本地的Linux环境是很有必要的。当时在电脑上安装了我个人比较熟悉的CentOS,把环境什么的都搭建齐全了。
然而当时QQ并没有发布新Linux版,结果在某次切换回Windows使用QQ的时候,和别人打电话的途中,无意间把Linux的系统盘给格式化了。。因为磁盘格式的原因,那个系统盘在windows下只显示个盘符,看不到容量信息,我还以为是我U盘坏掉了。。。有的时候是会无意间做出一些迷惑行为==
好不容易搭起来的环境全部木大,我也没心思再整一次了,启动项都懒得删,就这样在那里挂了大半年。
后来十月份的时候听闻QQ更新了Linux版,而且可以正常使用,当时一听就很令人振奋,因为对于我来说桌面版Linux真的就只差一个QQ,这下我拿Linux当主力系统的热情又上来了。加上最近在jenkins的使用过程中,发现有必要学一学shell脚本,于是就决定把Linux装回来。
至于为什么这次选择了Ubuntu,而不是我更熟悉的红帽系,一方面是某只夜鹰经常在群里叽叽喳喳Ubuntu(大雾),另一方面是Ubuntu在桌面版上确实下的功夫更多。
实际上安装过程和使用过程都确实比CentOS要省心许多,安装包体积更小,而且安装速度相当快,过程也人性化。
系统安装完后,当然是安装开发三件套:谷歌浏览器,Git,Idea。在这个过程中遇到了一点小问题,最新版的Chromium浏览器(Ubuntu商店里只有这个开源版的)上访问BiliBili直播的时候,H5播放器在拉流的时候在日志里疯狂输出403,但看其他视频又没问题。想着翻墙去下个谷歌浏览器,结果electron-ssr又代理失败,最后发现是系统自带Python版本过高的问题,需要安装老的Python2.7才行。挂上代理后下载谷歌浏览器,访问直播终于正常了。
最后去P站下载一张好康的壁纸,完美。透明的Dock是真的漂亮QAQ
PS:马上就要放假了,这个春节有一堆事情等着我回去处理。啊,好紧张,心脏都快跳出来了