zoukankan      html  css  js  c++  java
  • Java&Go三种HTTP客户端性能测试

    在学完Golang语言HTTP客户端实践Go语言HTTPServer开发的六种实现之后,我自然开始了Java&Go两种语言的HTTP客户端性能测试。

    之前在写10万QPS,K6、Gatling和FunTester终极对决!这个文章以及单机12万QPS——FunTester复仇记的时候,都是把CPU跑满了,为了达到12万QPS,我把所有除了统计以外的代码都删除了,这次就不搞这么极端了。而且在我自己初测的时候发现笔记本电脑最多只能跑到80%CPU,不知道是不是macOS限制了,再说消耗自己电脑,我也是心疼。

    服务端

    服务端依旧采取moco_FunTester框架的moco服务,代码如下:

    class Share extends MocoServer {
    
        static void main(String[] args) {
            def util = new ArgsUtil(args)
            def server = getServerNoLog(util.getIntOrdefault(0,12345))
            server.response("Have Fun ~ Tester !")
    //        server.response(delay(textRes("Have Fun ~ Tester !"),10))
            def run = run(server)
            waitForKey("fan")
            run.stop()
        }
    }
    
    

    本次测试两种服务状态,一种无延迟HTTP服务,另外一种是低延迟(5ms以及10ms),总计三种HTTP服务。由于Go语言HTTP的库自带了HTTP服务开发功能,后面我会再写一篇文章,对比一下三种HTTP服务的性能:Java netty、Go(net/http)以及Go(/valyala/fasthttp)。

    测试用例

    FunTester

    FunTester测试框架用的是Java HttpClient,对HttpClient API做了封装,然后配合FunTester性能测试框架完成本次测试。实测中封装和框架对性能影响可忽略。

    class HttpClientTest extends FunLibrary {
    
        static final String uri = "http://localhost:12345/test/fun"
        static final HttpRequestBase get = FunLibrary.getHttpGet(uri)
    
        static final int thread = 10
        static final int times = 10000
    
        public static void main(String[] args) {
            RUNUP_TIME = 0
            def tester = new FunTester()
            new Concurrent(tester, thread, DEFAULT_STRING).start()
        }
    
        private static class FunTester extends FixedThread<HttpRequestBase> {
    
            FunTester() {
                super(get, times, true)
            }
    
            @Override
            protected void doing() throws Exception {
                FunLibrary.executeOnly(get)
            }
    
            @Override
            FixedThread clone() {
                return new FunTester()
            }
        }
    
    }
    
    

    Go(net/http)

    这里我写了一个测试方法,使用了Go语言的协程和chan知识点,比较粗糙,但能用。代码时有改动,后台回复git可以获取多个项目的git仓库地址,包含本项目。

    var key bool = false
    
    const (
    	url    = "http://localhost:8001/test/fun"
    	thread = 20
    	times  = 10000
    )
    
    func TestPer(t *testing.T) {
    	get := funtester.Get(url, nil)
    	c := make(chan int)
    
    	start := time.Now().UnixMilli()
    	for i := 0; i < thread; i++ {
    		go func() {
    			sum := 0
    			for i := 0; i < times; i++ {
    				if key {
    					break
    				}
    				funtester.Response(get)
    				sum++
    			}
    			key = true
    			c <- sum
    		}()
    	}
    	total := 0
    	for i := 0; i < thread; i++ {
    		num := <-c
    		total += num
    	}
    	end := time.Now().UnixMilli()
    	diff := end - start
    	log.Printf("总耗时: %f", float64(diff)/1000)
    
    	log.Printf("请求总数: %d", total)
    	log.Printf("QPS: %f", float64(total)/float64(diff)*1000.0)
    
    }
    
    

    Go(/valyala/fasthttp)

    与net/http类似,不同之处是/valyala/fasthttp无法使用同一个对象进行压测。所以每次都要创建一个对象,但是实测居然效率更高,fasthttp对象池果然牛。而且传说中10倍于net/http,着实有点吹牛了。

    var key bool = false
    
    const (
    	url    = "http://localhost:8001/test/fun"
    	thread = 20
    	times  = 10000
    )
    
    func TestPerFast(t *testing.T) {
    	c := make(chan int)
    	start := time.Now().UnixMilli()
    	for i := 0; i < thread; i++ {
    		go func() {
    			sum := 0
    			for i := 0; i < times; i++ {
    				if key {
    					break
    				}
    				get := funtester.FastGet(url, nil)
    				funtester.FastResponse(get)
    				sum++
    
    			}
    			key = true
    			c <- sum
    		}()
    	}
    	total := 0
    	for i := 0; i < thread; i++ {
    		num := <-c
    		total += num
    	}
    	end := time.Now().UnixMilli()
    	diff := end - start
    	//total := thread * times
    	log.Printf("总耗时: %f", float64(diff)/1000)
    
    	log.Printf("请求总数: %d", total)
    	log.Printf("QPS: %f", float64(total)/float64(diff)*1000.0)
    
    }
    
    

    测试

    无延迟服务

    1线程

    框架 CPU 内存 QPS
    FunTester 51.04 354.9 MB 17715
    Go(net/http) 104.26 14.8 MB 13120
    Go(/valyala/fasthttp) 81.67 5.3 MB 20255

    5线程

    框架 CPU 内存 QPS
    FunTester 230.08 555.5 MB 59626
    Go(net/http) 323.45 14.9 MB 43143
    Go(/valyala/fasthttp) 215.73 6.4 MB 68659

    10线程

    框架 CPU 内存 QPS
    FunTester 356.43 685.2 MB 81795
    Go(net/http) 573.08 1.36 GB 36431
    Go(/valyala/fasthttp) 321.85 6.8 MB 82093

    截止到此,CPU已经基本满荷运行,实际80%,不知道是不是macOS的限制,现在CPU只能跑到80%左右。

    实际测试结果非常明显,总体CPU指标,FunTester/valyala/fasthttp相差不多,/valyala/fasthttp在CPU方面有些许优势,但是在内存上,简直无法理解。见鬼了一样。相比之下net/http逊色很多,在低并发的时候除了内存表现较好意外,CPU和QPS均低于FunTester/valyala/fasthttp,但是在10线程的情况下,CPU跑满,内存直线飙升,着实无法理解。等我再深入学习之后,估计能明白这个问题了。

    延迟5ms服务

    10线程

    框架 CPU 内存 QPS
    FunTester 19.63 163.9 MB 1671
    Go(net/http) 31.18 14.2 MB 1440
    Go(/valyala/fasthttp) 15.63 6.8 MB 1709

    20线程

    框架 CPU 内存 QPS
    FunTester 36.88 235.3 MB 3318
    Go(net/http) 48.47 14.4 MB 2400
    Go(/valyala/fasthttp) 32.81 7.5 MB 3339

    结论跟无延迟服务差不多。总体讲/valyala/fasthttp > FunTester > net/http。即使Go语言加成,net/http除了内存以外,其他两项指标均不如Java写的FunTester。

    结论

    /valyala/fasthttp真心牛逼,建议使用Go语言进行HTTP性能测试的,直接跳过net/http

    PS:下一次我将测试三种HTTP服务端的性能,敬请期待。

    欢迎关注FunTester,Have Fun ~ Tester !

  • 相关阅读:
    PAT 甲题 1155 Heap Paths
    PAT甲题 1014 Waiting in Line
    PAT甲题 1014 Waiting in Line
    AcWing 840. 模拟散列表
    2019新生赛 %%%xxh
    AcWing 240. 食物链
    AcWing 143. 最大异或对
    AcWing 838. 堆排序
    AcWing 836. 合并集合
    AcWing 837. 连通块中点的数量
  • 原文地址:https://www.cnblogs.com/FunTester/p/15624124.html
Copyright © 2011-2022 走看看