英文:
AppEngine IO Copy issue results in "API error 10 (file: FILE_NOT_OPENED)"
问题
我的GoLang AppEngine代码正在解压缩一个ZIP文件,然后将每个文件保存为BlobStore内容。我发现保存数据需要超过30秒,然后出现“API错误10(文件:FILE_NOT_OPENED)”。要写入的未压缩文件的大小约为1.5兆字节。以下是从Zip读取器复制到新的BlobStore项的代码:
func storeBlob(c appengine.Context, rc io.Reader, mimeType string) (appengine.BlobKey, error) {
c.Infof("Creating new blob of type: [%v]", mimeType)
var key appengine.BlobKey
w, err := blobstore.Create(c, mimeType)
if err != nil {
return "", err
}
c.Infof("Copying blob data")
_, err = io.Copy(w, rc)
if err != nil {
return "", err
}
c.Infof("Closing Blob")
err = w.Close()
if err != nil {
return "", err
}
c.Infof("Getting Blob Key")
key, err = w.Key()
if err != nil {
return "", err
}
return key, nil
}
生产环境的appengine服务器在30秒后锁定,并在io.Copy调用上报告错误。有没有关于如何排除故障的想法?
英文:
My GoLang AppEngine code is uncompressing a ZIP file and then saving off each file as BlobStore content. I've seen it take over 30 seconds to save the data and then it fails with "API error 10 (file: FILE_NOT_OPENED)." The size of the uncompressed file being written is about 1.5 megabytes. Here is the code that does the copy to a new BlogStore item from the Zip reader:
func storeBlob(c appengine.Context, rc io.Reader, mimeType string) (appengine.BlobKey, error) {
c.Infof("Creating new blob of type: [%v]", mimeType)
var key appengine.BlobKey
w, err := blobstore.Create(c, mimeType)
if err != nil {
return "", err
}
c.Infof("Copying blob data")
_, err = io.Copy(w, rc)
if err != nil {
return "", err
}
c.Infof("Closing Blob")
err = w.Close()
if err != nil {
return "", err
}
c.Infof("Getting Blob Key")
key, err = w.Key()
if err != nil {
return "", err
}
return key, nil
}
The production appengine server locks up for 30 seconds and then reports the error on the io.Copy call. Any thoughts on how to troubleshoot this?
答案1
得分: 2
这个错误是因为你的请求超时了。Create
方法发起了一个协议缓冲区请求,类似于这样:
oreq := &filepb.OpenRequest{
Filename: res.Filename,
ContentType: filepb.FileContentType_RAW.Enum(),
OpenMode: filepb.OpenRequest_APPEND.Enum(),
ExclusiveLock: proto.Bool(true),
}
对应的定义如下:
type OpenRequest struct {
Filename *string `protobuf:"bytes,1,req,name=filename" json:"filename,omitempty"`
ContentType *FileContentType_ContentType `protobuf:"varint,2,req,name=content_type,enum=files.FileContentType_ContentType" json:"content_type,omitempty"`
OpenMode *OpenRequest_OpenMode `protobuf:"varint,3,req,name=open_mode,enum=files.OpenRequest_OpenMode" json:"open_mode,omitempty"`
ExclusiveLock *bool `protobuf:"varint,4,opt,name=exclusive_lock,def=0" json:"exclusive_lock,omitempty"`
BufferedOutput *bool `protobuf:"varint,5,opt,name=buffered_output,def=0" json:"buffered_output,omitempty"`
OpenLeaseTimeSeconds *int32 `protobuf:"varint,6,opt,name=open_lease_time_seconds,def=30" json:"open_lease_time_seconds,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
注意,OpenLeaseTimeSeconds
没有设置。它将默认为30秒:
const Default_OpenRequest_OpenLeaseTimeSeconds int32 = 30
所以可能是在你下面关闭了连接。
你有两个选择:
-
编写自己的
Create
方法,将租约时间设置为大于30秒的值。最多只能设置为60秒,因为超过这个时间,你的请求将被终止,此时你需要使用任务队列。 -
这个API已经被弃用:
警告:在此处用于将文件写入Blobstore的Files API功能已被弃用,并将在将来的某个时间被移除,取而代之的是将文件写入Google Cloud Storage并使用Blobstore来提供服务。有关更多信息,请访问Google Cloud Storage。
所以也许你应该尝试使用Google Storage。
英文:
This error is because your request is timing out. Create
makes a protocol buffer request that looks like this:
oreq := &filepb.OpenRequest{
Filename: res.Filename,
ContentType: filepb.FileContentType_RAW.Enum(),
OpenMode: filepb.OpenRequest_APPEND.Enum(),
ExclusiveLock: proto.Bool(true),
}
The corresponding definition:
type OpenRequest struct {
Filename *string `protobuf:"bytes,1,req,name=filename" json:"filename,omitempty"`
ContentType *FileContentType_ContentType `protobuf:"varint,2,req,name=content_type,enum=files.FileContentType_ContentType" json:"content_type,omitempty"`
OpenMode *OpenRequest_OpenMode `protobuf:"varint,3,req,name=open_mode,enum=files.OpenRequest_OpenMode" json:"open_mode,omitempty"`
ExclusiveLock *bool `protobuf:"varint,4,opt,name=exclusive_lock,def=0" json:"exclusive_lock,omitempty"`
BufferedOutput *bool `protobuf:"varint,5,opt,name=buffered_output,def=0" json:"buffered_output,omitempty"`
OpenLeaseTimeSeconds *int32 `protobuf:"varint,6,opt,name=open_lease_time_seconds,def=30" json:"open_lease_time_seconds,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
Notice OpenLeaseTimeSeconds
is unset. It will default to 30 seconds:
const Default_OpenRequest_OpenLeaseTimeSeconds int32 = 30
So it's probably closing the connection underneath you.
You have two options:
-
Write your own
Create
method which sets the lease time to something greater than 30 seconds. The most you can do is 60 seconds since then your request will be killed, in which case you will need to use a Task Queue. -
The API is deprecated:
> Warning: The Files API feature used here to write files to Blobstore has been deprecated and is going to be removed at some time in the future, in favor of writing files to Google Cloud Storage and using Blobstore to serve them. For more information, please visit Google Cloud Storage.
So maybe you should try google storage instead.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论