近期在開發一個搶口罩的系統,類似於電商常見的秒殺系統。當時選型的的時候准備在netcore和golang之間選擇一個作為系統的開發語言,網上的說法各異,有的說iris快,有的說.netcore快。於是決定自己做下測試。
iris在go的web開發框架中是非常流行的,它自己的介紹是最快的go語言web框架,這個肯定有一家之言的成分,但是說它是最快的go框架之一肯定沒有問題。使用的iris的版本是12.1.8
aspnetcore 就是微軟在.netcore中開發的標准框架,不需要用到其他第三方框架。這里使用的.netcore版本是3.0
iris的代碼為:
// package main // import "github.com/gin-gonic/gin" // func main() { // r := gin.Default() // r.GET("/ping", func(c *gin.Context) { // c.JSON(200, gin.H{ // "message": "pong", // }) // }) // r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080") // } package main import ( "github.com/kataras/iris" "github.com/kataras/iris/context" //"strings" "math/rand" ) const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 " func randomString(n int) string { b := make([]byte, n) for i := range b { b[i] = letterBytes[rand.Intn(len(letterBytes))] } return string(b) } func main() { app := iris.New() //txt := strings.Repeat("g", 10000) app.Get("/api/values/{id}", func(ctx context.Context) { txt := randomString(1024) ctx.WriteString(txt) }) app.Run(iris.Addr(":5000")) }
aspnetcore的代碼為:(吐槽一下,微軟整的代碼太多,讓人有點添堵)
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseKestrel(options => { options.Listen(IPAddress.Any, 5080); //HTTP port }); webBuilder.UseStartup<Startup>(); }).ConfigureLogging(a => a.SetMinimumLevel(LogLevel.None)); }
public class Startup { // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { } const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "; static string RandomString(int length) { var random = new Random(DateTime.Now.Millisecond); var bytes = new Char[length]; for (var i = 0; i < length; i++) { bytes[i] = chars[random.Next(chars.Length)]; } return new string(bytes); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGet("/", async context => { var txt = RandomString(1024); await context.Response.WriteAsync(txt); // await context.Response.WriteAsync("Hello World!"); }); }); } }
windows下的測試:
iris: 通過 go build 進行編譯,然后運行。啟用 bombardier測試。結果如下
bombardier.exe -c 50 -n 300000 http://localhost:5000/api/values/id
Bombarding http://localhost:5000/api/values/id with 300000 request(s) using 50 connection(s)
300000 / 300000 [=================================================================================] 100.00% 8798/s 34s
Done!
Statistics Avg Stdev Max
Reqs/sec 8860.00 1065.69 38087.60
Latency 5.65ms 187.86us 31.91ms
HTTP codes:
1xx - 0, 2xx - 300000, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 10.27MB/s
aspnetcore: dotnet publish -c Release 編譯。結果如下
Bombarding http://localhost:5080 with 300000 request(s) using 50 connection(s)
300000 / 300000 [=================================================================================] 100.00% 34749/s 8s
Done!
Statistics Avg Stdev Max
Reqs/sec 35283.26 6100.68 45069.66
Latency 1.41ms 8.08ms 1.06s
HTTP codes:
1xx - 0, 2xx - 300000, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 40.35MB/s
結果讓人大跌眼鏡。.netcore比iris 的qps快了4倍以上。(注意上面代碼,我移除了.netcore的日志)
因為是windows平台的結果,我懷疑go語言在windows沒有優化,所以后來加入了linux amd64的測試
iris: 發布成linux單文件 SET GOOS=linux SET GOARCH=amd64 go build. 拷貝到debian 10(vmware在本地搭建的虛擬機)上執行。(這個誇一下,go編譯的結果非常小巧,方便攜帶)
Bombarding http://192.168.236.131:5000/api/values/id with 300000 request(s) using 50 connection(s)
300000 / 300000 [=================================================================================] 100.00% 8176/s 36s
Done!
Statistics Avg Stdev Max
Reqs/sec 8179.10 677.17 11293.41
Latency 6.11ms 757.13us 51.84ms
HTTP codes:
1xx - 0, 2xx - 300000, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 9.55MB/s
結果和windows下面差不多,可能是應該在vm中跑,性能有稍微的損失。
aspnetcore: 發布成linux單文件 dotnet publish -r linux-x64 -c Release /p:PublishSingleFile=true .(這里說一下,這個文件有95M,有點大,不過還能接收),執行結果如下
Bombarding http://192.168.236.131:5080 with 300000 request(s) using 50 connection(s)
300000 / 300000 [================================================================================] 100.00% 17002/s 17s
Done!
Statistics Avg Stdev Max
Reqs/sec 17078.01 1997.18 20679.28
Latency 2.93ms 267.95us 31.91ms
HTTP codes:
1xx - 0, 2xx - 300000, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 19.62MB/s
結果比在windows下面大幅下滑,不過還是比iris高了2倍多。
結論:
- 微軟在.netcore上的性能優化不留余地,尤其是在windows平台上,可能也是為了顯示windows平台還是有優勢的:)
- .netcore, go ,java 總體性能上是一個數量級的,相互之間不可能差距太多。但是在當前的測試中,.netcore略微領先於其他的兩門語言
- go語言有一些其他優勢,比如內存占用低(這次的測試大於占19M內存,.netcore占用54M),打包方便,容易入門等。(C#的語言花樣有點多,初學者學習曲線長)
- 這里只是記錄下測試的結果,並無比較說明孰優孰劣的意思。當然后來我們選用了.netcore,確實秒殺結果令人滿意,一秒能出去近1000個訂單。