我正在尝试描述用go编写的http处理程序。在每个http请求中从S3下载图像,调整大小/裁剪它并将其写入响应。
我已经关注了这个link并尝试使用简单方法和硬方法来描述我的代码。现在,当我使用代码中提到的以下行时。
defer profile.Start(profile.CPUProfile).Stop()
它不会在/tmp/profie[some number]/cpu.pprof
文件
func main() {
defer profile.Start(profile.CPUProfile).Stop()
if err := http.ListenAndServe(":8081", http.HandlerFunc(serveHTTP)); err != nil {
logFatal("Error when starting or running http server: %v", err)
}
}
func serveHTTP(w http.ResponseWriter, r *http.Request) {
keyName := r.URL.Path[1:]
s3Client := s3.New(session.New(), &aws.Config{Region: aws.String(region)})
params := &s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(keyName),
}
mw := imagick.NewMagickWand()
defer mw.Destroy()
...
}
此外,当我使用defer profile.Start(profile.CPUProfile).Stop()
内的serveHTTP
行时:
func serveHTTP(w http.ResponseWriter, r *http.Request) {
defer profile.Start(profile.CPUProfile).Stop()
......
}
它会在/tmp/profile[some number]
文件夹中创建多个文件。所以,第一个问题是为什么它不是在文件中写入,其次不应该是serveHTTP method
内的位置,因为服务器只会启动一次。因此,main()
将在每次请求被调用serveHTTP
时被调用。
第1部分
. 124: s3Client := s3.New(session.New(), &aws.Config{Region: aws.String(region)})
. . 125: params := &s3.GetObjectInput{
. . 126: Bucket: aws.String(masterBucketName),
. . 127: Key: aws.String(keyName),
. 32.01kB 128: }
. . 129:
. . 130: mw := imagick.NewMagickWand()
. . 131: defer mw.Destroy()
. . 132:
. . 133: out, err := s3Client.GetObject(params)
. . 134:
. . 135: if strings.EqualFold(keyName[strings.LastIndex(keyName,".")+1:len(keyName)], "gif") {
. . 136:
. 40.11kB 137: blobGiff, err := ioutil.ReadAll(out.Body)
. . 138: w.Header().Set("Content-Type", "image/gif")
. . 139: w.Header().Set("Cache-Control", "max-age: 604800, public")
. . 140: w.Header().Set("Last-Modified", time.Now().Format(http.TimeFormat))
. . 141: w.Header().Set("Expires", time.Now().AddDate(1, 0, 0).Format(http.TimeFormat))
. . 142:
第2部分:
else {
. . 167: img, err := ioutil.ReadAll(out.Body)
. . 168: if err != nil {
. . 169:
. . 170: w.WriteHeader(http.StatusNotFound)
. 1.56MB 171: return
. . 172: }
另外,在上面两部分中,第128,137和171行有内存泄漏,对吗?另外,我找不到关闭/销毁s3Client
和blobGiff
(byte [])的任何选项。
答案 0 :(得分:4)
要在http服务器运行时对其进行配置,您可以使用net/http/pprof
包。
添加
procedure TForm1.cxGrid1DBTableView1EditKeyPress(Sender:
TcxCustomGridTableView; AItem: TcxCustomGridTableItem; AEdit:
TcxCustomEdit; var Key: Char);
var
AField : TField;
strValue : String;
V : Variant;
i,
InsertPoint,
EC : Integer;
function CharIsOK(Ch : Char) : Boolean;
begin
Result := CharInSet(Ch, ['0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', '-', '+']);
// Or Result := Ch in ['0', ... for Delphi prior to D2009
end;
begin
if AItem = cxGrid1DBTableView1Value then begin
// The following manually cleans up input into a TIntegerField column
// whose Properties is set to TextEdit
// First, pick up the text in the inplace editor
V := AEdit.EditingValue;
if not VarIsNull(V) then
strValue := AEdit.EditingValue
else
strValue := '';
if strValue <> '' then begin
// Next, check that the Key is a valid one for an Integer field.
if CharIsOk(Key) then begin
// The fact that the Key is a valid character for an Integer field
// does not in itself guarantee that the entire editing string, including the Key
// which is about to be added to in, is a valid string representation of an integer,
// e.g. it might be '--', '+1-5', etc
// So, we add the Key to the existing editing string and see if it converts to an integer
// Of course, there is the wrinkle that the caret may not be at the end of the editing text
// so we need to find out where the caret is. First we need
// to check that AEdit is a TcxtextEdit so that we can access
// its SelStart property
Assert(AEdit is TcxTextEdit);
InsertPoint := TcxTextEdit(AEdit).SelStart;
Insert(Key, strValue, InsertPoint + 1);
Val(strValue, i, EC);
// if EC is non-zero, the conversion failed, so we suppress the Key
if EC <> 0 then
Key := Chr(0);
end
else
// the Key might be a backspace, so permit that
if Ord(Key) <> VK_Back then
Key := Chr(0);
end
end;
end;
导入并在浏览器中打开import _ "net/http/pprof"
。
答案 1 :(得分:2)
首先使用import "net/http/pprof"
NOT import _“net / http / pprof 。后来人们无法识别以下路线中的pprof
。
我使用的是默认的serveMux / multiplexer。但后来我创建了自己的,因为人们认为它具有性能含义。
myMux := http.NewServeMux()
然后添加了请求的路由
myMux.HandleFunc("/", serveHTTP)
另外,我还添加了使http://localhost:8081/debug/pprof/
工作的路线
myMux.HandleFunc("/debug/pprof/", pprof.Index)
myMux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
myMux.HandleFunc("/debug/pprof/profile", pprof.Profile)
myMux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
所以,最终的代码是:
导入“net / http / pprof
func main() {
myMux := http.NewServeMux()
myMux.HandleFunc("/", serveHTTP)
myMux.HandleFunc("/debug/pprof/", pprof.Index)
myMux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
myMux.HandleFunc("/debug/pprof/profile", pprof.Profile)
myMux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
if err := http.ListenAndServe(":8081", myMux); err != nil {
logFatal("Error when starting or running http server: %v", err)
}
}