|
@@ -25,7 +25,8 @@ import (
|
|
var (
|
|
var (
|
|
// accountMap 用来缓存OSS帐号信息
|
|
// accountMap 用来缓存OSS帐号信息
|
|
accountMap sync.Map
|
|
accountMap sync.Map
|
|
- DownLoadPool = make(chan bool, g.Config().MustGet(gctx.New(), "downLoadPoolSize").Int())
|
|
|
|
|
|
+ UploadPool = make(chan bool, g.Config().MustGet(gctx.New(), "uploadPoolSize").Int())
|
|
|
|
+ DownloadPool = make(chan bool, g.Config().MustGet(gctx.New(), "downloadPoolSize").Int())
|
|
GetDetailFromEsPool = make(chan bool, g.Config().MustGet(gctx.New(), "getDetailFromEsPoolSize").Int())
|
|
GetDetailFromEsPool = make(chan bool, g.Config().MustGet(gctx.New(), "getDetailFromEsPoolSize").Int())
|
|
GetDetailFromMgoPool = make(chan bool, g.Config().MustGet(gctx.New(), "getDetailFromMgoPoolSize").Int())
|
|
GetDetailFromMgoPool = make(chan bool, g.Config().MustGet(gctx.New(), "getDetailFromMgoPoolSize").Int())
|
|
getDetail = map[string]func(w io.Writer, bucketID, objectName string) error{
|
|
getDetail = map[string]func(w io.Writer, bucketID, objectName string) error{
|
|
@@ -41,7 +42,9 @@ var (
|
|
list := es.VarEs.Get(indexName, indexName, fmt.Sprintf(`{"query":{"bool":{"filter":{"term":{"_id":"%s"}}}},"_source":["detail"]}`, objectName))
|
|
list := es.VarEs.Get(indexName, indexName, fmt.Sprintf(`{"query":{"bool":{"filter":{"term":{"_id":"%s"}}}},"_source":["detail"]}`, objectName))
|
|
if list != nil && len(*list) > 0 {
|
|
if list != nil && len(*list) > 0 {
|
|
detail, _ := (*list)[0]["detail"].(string)
|
|
detail, _ := (*list)[0]["detail"].(string)
|
|
- _, err := io.Copy(w, bytes.NewReader([]byte(detail)))
|
|
|
|
|
|
+ buf := bufferPool.Get().(*[]byte)
|
|
|
|
+ defer bufferPool.Put(buf)
|
|
|
|
+ _, err := io.CopyBuffer(w, bytes.NewReader([]byte(detail)), *buf)
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
return errors.New("not find from es")
|
|
return errors.New("not find from es")
|
|
@@ -54,12 +57,20 @@ var (
|
|
data, _ := config.Mgo.FindById(g.Config().MustGet(gctx.New(), "mongodb.collection").String(), objectName, `{"detail":1}`)
|
|
data, _ := config.Mgo.FindById(g.Config().MustGet(gctx.New(), "mongodb.collection").String(), objectName, `{"detail":1}`)
|
|
if data != nil && len(*data) > 0 {
|
|
if data != nil && len(*data) > 0 {
|
|
detail, _ := (*data)["detail"].(string)
|
|
detail, _ := (*data)["detail"].(string)
|
|
- _, err := io.Copy(w, bytes.NewReader([]byte(detail)))
|
|
|
|
|
|
+ buf := bufferPool.Get().(*[]byte)
|
|
|
|
+ defer bufferPool.Put(buf)
|
|
|
|
+ _, err := io.CopyBuffer(w, bytes.NewReader([]byte(detail)), *buf)
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
return errors.New("not find from mgo")
|
|
return errors.New("not find from mgo")
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
+ bufferPool = sync.Pool{
|
|
|
|
+ New: func() interface{} {
|
|
|
|
+ buf := make([]byte, 512*1024) // 512KB 缓冲区
|
|
|
|
+ return &buf
|
|
|
|
+ },
|
|
|
|
+ }
|
|
)
|
|
)
|
|
|
|
|
|
// GetBucket 根据bucketID获取bucket信息,如果没有则模拟查询数据库(这里只查询一次)
|
|
// GetBucket 根据bucketID获取bucket信息,如果没有则模拟查询数据库(这里只查询一次)
|
|
@@ -71,40 +82,41 @@ func GetBucket(bucketID string) (config.BucketInfo, error) {
|
|
return *v, nil
|
|
return *v, nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- err := fmt.Errorf("bucket id %s not found", bucketID)
|
|
|
|
- log.Println(err)
|
|
|
|
// 模拟数据库查询:实际业务中这里应查询数据库
|
|
// 模拟数据库查询:实际业务中这里应查询数据库
|
|
- return config.BucketInfo{}, err
|
|
|
|
|
|
+ return config.BucketInfo{}, fmt.Errorf("bucket id %s not found", bucketID)
|
|
}
|
|
}
|
|
|
|
|
|
// bucketPool 缓存 bucket 对象,避免重复创建
|
|
// bucketPool 缓存 bucket 对象,避免重复创建
|
|
-//var bucketPool sync.Map // key: bucketID, value: *ossSDK.Bucket
|
|
|
|
|
|
+var bucketPool sync.Map // key: bucketID, value: *ossSDK.Bucket
|
|
|
|
|
|
// GetCachedBucket 对外暴露统一入口,根据 bucketID 获取 *ossSDK.Bucket 对象
|
|
// GetCachedBucket 对外暴露统一入口,根据 bucketID 获取 *ossSDK.Bucket 对象
|
|
func GetCachedBucket(bucketID string) (*ossSDK.Bucket, error) {
|
|
func GetCachedBucket(bucketID string) (*ossSDK.Bucket, error) {
|
|
// 优先从对象池取
|
|
// 优先从对象池取
|
|
- //if cached, ok := bucketPool.Load(bucketID); ok {
|
|
|
|
- // return cached.(*ossSDK.Bucket), nil
|
|
|
|
- //}
|
|
|
|
|
|
+ if cached, ok := bucketPool.Load(bucketID); ok {
|
|
|
|
+ return cached.(*ossSDK.Bucket), nil
|
|
|
|
+ }
|
|
|
|
|
|
// 如果不存在则依次读取 bucketInfo 和 OSS client 信息
|
|
// 如果不存在则依次读取 bucketInfo 和 OSS client 信息
|
|
bucketInfo, err := GetBucket(bucketID)
|
|
bucketInfo, err := GetBucket(bucketID)
|
|
if err != nil {
|
|
if err != nil {
|
|
|
|
+ log.Println(err)
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
|
|
client, err := getOSSClient(bucketInfo.AccountID)
|
|
client, err := getOSSClient(bucketInfo.AccountID)
|
|
if err != nil {
|
|
if err != nil {
|
|
|
|
+ log.Println(err)
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
|
|
bucket, err := client.Bucket(bucketInfo.BucketName)
|
|
bucket, err := client.Bucket(bucketInfo.BucketName)
|
|
if err != nil {
|
|
if err != nil {
|
|
|
|
+ log.Println(err)
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
|
|
// 存入对象池
|
|
// 存入对象池
|
|
- //bucketPool.Store(bucketID, bucket)
|
|
|
|
|
|
+ bucketPool.Store(bucketID, bucket)
|
|
return bucket, nil
|
|
return bucket, nil
|
|
}
|
|
}
|
|
|
|
|
|
@@ -123,6 +135,12 @@ func getOSSClient(accountID string) (*ossSDK.Client, error) {
|
|
|
|
|
|
// UploadAttachment 上传附件;如果gzipEnabled为true,则进行gzip压缩(使用 io.Pipe 实现流式压缩)
|
|
// UploadAttachment 上传附件;如果gzipEnabled为true,则进行gzip压缩(使用 io.Pipe 实现流式压缩)
|
|
func Upload(bucketID, objectName string, data io.Reader, gzipEnabled bool) error {
|
|
func Upload(bucketID, objectName string, data io.Reader, gzipEnabled bool) error {
|
|
|
|
+ atomic.AddInt64(&util.UploadCounter, 1)
|
|
|
|
+ UploadPool <- true
|
|
|
|
+ defer func() {
|
|
|
|
+ <-UploadPool
|
|
|
|
+ atomic.AddInt64(&util.UploadCounter, -1)
|
|
|
|
+ }()
|
|
bucket, err := GetCachedBucket(bucketID)
|
|
bucket, err := GetCachedBucket(bucketID)
|
|
if err != nil {
|
|
if err != nil {
|
|
return err
|
|
return err
|
|
@@ -142,26 +160,29 @@ func Upload(bucketID, objectName string, data io.Reader, gzipEnabled bool) error
|
|
} else {
|
|
} else {
|
|
reader = data
|
|
reader = data
|
|
}
|
|
}
|
|
-
|
|
|
|
// 上传到OSS
|
|
// 上传到OSS
|
|
- return bucket.PutObject(objectName, reader)
|
|
|
|
|
|
+ if err := bucket.PutObject(objectName, reader); err != nil {
|
|
|
|
+ log.Println(bucketID, objectName, "上传出错", err)
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
}
|
|
}
|
|
|
|
|
|
// downloadAttachment 下载,如果检测到数据为gzip压缩,则自动解压后返回
|
|
// downloadAttachment 下载,如果检测到数据为gzip压缩,则自动解压后返回
|
|
func Download(w io.Writer, autoExtract int, bucketID, objectName string) error {
|
|
func Download(w io.Writer, autoExtract int, bucketID, objectName string) error {
|
|
- atomic.AddInt64(&util.DownLoadCounter, 1)
|
|
|
|
- DownLoadPool <- true
|
|
|
|
|
|
+ atomic.AddInt64(&util.DownloadCounter, 1)
|
|
|
|
+ DownloadPool <- true
|
|
defer func() {
|
|
defer func() {
|
|
- <-DownLoadPool
|
|
|
|
- atomic.AddInt64(&util.DownLoadCounter, -1)
|
|
|
|
|
|
+ <-DownloadPool
|
|
|
|
+ atomic.AddInt64(&util.DownloadCounter, -1)
|
|
}()
|
|
}()
|
|
bucket, err := GetCachedBucket(bucketID)
|
|
bucket, err := GetCachedBucket(bucketID)
|
|
if err != nil {
|
|
if err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
-
|
|
|
|
result, err := bucket.DoGetObject(&ossSDK.GetObjectRequest{objectName}, nil)
|
|
result, err := bucket.DoGetObject(&ossSDK.GetObjectRequest{objectName}, nil)
|
|
if err != nil {
|
|
if err != nil {
|
|
|
|
+ log.Println(bucketID, objectName, "下载出错", err)
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
defer result.Response.Body.Close()
|
|
defer result.Response.Body.Close()
|
|
@@ -169,25 +190,31 @@ func Download(w io.Writer, autoExtract int, bucketID, objectName string) error {
|
|
rw.Header().Set("Content-Type", result.Response.Headers.Get("Content-Type")) // 根据文件类型调整此行
|
|
rw.Header().Set("Content-Type", result.Response.Headers.Get("Content-Type")) // 根据文件类型调整此行
|
|
rw.Header().Set("Content-Disposition", "attachment; filename="+objectName)
|
|
rw.Header().Set("Content-Disposition", "attachment; filename="+objectName)
|
|
}
|
|
}
|
|
|
|
+ buf := bufferPool.Get().(*[]byte)
|
|
|
|
+ defer bufferPool.Put(buf)
|
|
if autoExtract == 1 {
|
|
if autoExtract == 1 {
|
|
data, err := ioutil.ReadAll(result.Response.Body)
|
|
data, err := ioutil.ReadAll(result.Response.Body)
|
|
if err != nil {
|
|
if err != nil {
|
|
|
|
+ log.Println(bucketID, objectName, "下载后ioutil.ReadAll出错", err)
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
// 判断是否为gzip压缩格式(判断前两个字节)
|
|
// 判断是否为gzip压缩格式(判断前两个字节)
|
|
if len(data) >= 2 && data[0] == 0x1f && data[1] == 0x8b {
|
|
if len(data) >= 2 && data[0] == 0x1f && data[1] == 0x8b {
|
|
gzipReader, err := gzip.NewReader(bytes.NewReader(data))
|
|
gzipReader, err := gzip.NewReader(bytes.NewReader(data))
|
|
if err != nil {
|
|
if err != nil {
|
|
|
|
+ log.Println(bucketID, objectName, "下载后gzip.NewReader出错", err)
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
defer gzipReader.Close()
|
|
defer gzipReader.Close()
|
|
- if _, err = io.Copy(w, gzipReader); err != nil {
|
|
|
|
|
|
+ if _, err = io.CopyBuffer(w, gzipReader, *buf); err != nil {
|
|
|
|
+ log.Println(bucketID, objectName, "下载解压后io.Copy出错", err)
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- if _, err = io.Copy(w, result.Response.Body); err != nil {
|
|
|
|
|
|
+ if _, err = io.CopyBuffer(w, result.Response.Body, *buf); err != nil {
|
|
|
|
+ log.Println(bucketID, objectName, "下载后io.Copy出错", err)
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -200,8 +227,10 @@ func Delete(bucketID, objectName string) error {
|
|
if err != nil {
|
|
if err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
-
|
|
|
|
- return bucket.DeleteObject(objectName)
|
|
|
|
|
|
+ if err := bucket.DeleteObject(objectName); err != nil {
|
|
|
|
+ log.Println(bucketID, objectName, "删除出错", err)
|
|
|
|
+ }
|
|
|
|
+ return err
|
|
}
|
|
}
|
|
|
|
|
|
// LoadOSSAccounts 加载OSS帐号信息到缓存
|
|
// LoadOSSAccounts 加载OSS帐号信息到缓存
|
|
@@ -212,7 +241,7 @@ func LoadOSSAccounts() {
|
|
for _, acc := range oas {
|
|
for _, acc := range oas {
|
|
accountMap.Store(acc.ID, *acc)
|
|
accountMap.Store(acc.ID, *acc)
|
|
}
|
|
}
|
|
- //bucketPool.Clear()
|
|
|
|
|
|
+ bucketPool.Clear()
|
|
}
|
|
}
|
|
|
|
|
|
// 获取标讯正文,优先从oss中取,再从es中取
|
|
// 获取标讯正文,优先从oss中取,再从es中取
|