Rumah  >  Artikel  >  Java  >  Metrik Boleh Menipu Anda: Mengukur Masa Pelaksanaan dalam Persekitaran Disatukan Sambungan

Metrik Boleh Menipu Anda: Mengukur Masa Pelaksanaan dalam Persekitaran Disatukan Sambungan

王林
王林asal
2024-08-14 22:44:02308semak imbas

Mengukur masa pelaksanaan permintaan kepada perkhidmatan luaran adalah penting untuk pemantauan dan pengoptimuman prestasi. Walau bagaimanapun, apabila sambungan kepada perkhidmatan luaran ini dikumpulkan, anda mungkin secara tidak sengaja mengukur lebih daripada sekadar masa permintaan. Khususnya, jika permintaan mengambil masa terlalu lama dan anda kehabisan sambungan yang tersedia, logik tersuai anda mungkin mula termasuk masa menunggu untuk mendapatkan sambungan daripada kolam. Ini boleh membawa kepada metrik yang mengelirukan, menyebabkan anda tersalah tafsir prestasi sistem anda. Mari kita teliti bagaimana perkara ini berlaku dan bagaimana anda boleh mengelak daripada tertipu oleh metrik anda sendiri.

Perangkap: Termasuk Masa Menunggu dalam Metrik

Apabila semua sambungan dalam kolam sedang digunakan, permintaan tambahan mesti menunggu sehingga sambungan tersedia. Masa menunggu ini boleh memesongkan metrik anda jika tidak diukur secara berasingan daripada masa permintaan sebenar.

Senario: Kehabisan Sambungan

  1. Keadaan Awal: Kumpulan sambungan anda mempunyai bilangan sambungan tetap, yang semuanya sedang digunakan.
  2. Permintaan Baharu: Permintaan baharu masuk tetapi mesti menunggu sehingga sambungan tersedia.
  3. Masa Tunggu: Permintaan menunggu (mungkin untuk jumlah masa yang banyak) sehingga sambungan adalah percuma.
  4. Masa Permintaan: Setelah sambungan diperoleh, permintaan sebenar dibuat.

Jika logik tersuai anda mengukur jumlah masa sejak permintaan dibuat sehingga respons diterima, anda termasuk kedua-dua masa menunggu dan masa permintaan.

Contoh Praktikal: Menghasilkan Semula Masalah dalam Boot Spring dengan Apache HttpClient 5

Untuk menggambarkan cara anda boleh tertipu oleh metrik anda sendiri dalam persekitaran terkumpul sambungan, mari kita lihat contoh praktikal menggunakan Spring Boot dan Apache HttpClient 5. Kami akan menyediakan aplikasi Spring Boot yang ringkas yang membuat permintaan HTTP untuk perkhidmatan luaran, ukur masa pelaksanaan permintaan ini dan tunjukkan cara keletihan kumpulan sambungan boleh membawa kepada metrik yang mengelirukan.

Untuk mensimulasikan kelewatan dalam perkhidmatan luaran, kami akan menggunakan imej httpbin Docker. Httpbin menyediakan perkhidmatan permintaan dan respons HTTP yang mudah digunakan, yang boleh kami gunakan untuk membuat kelewatan buatan dalam permintaan kami.

@SpringBootApplication
@RestController
public class Server {

    public static void main(String... args) {
        SpringApplication.run(Server.class, args);
    }

    class TimeClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {

        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
                throws IOException {
            var t0 = System.currentTimeMillis();
            try {
                return execution.execute(request, body);
            } finally {
                System.out.println("Request took: " + (System.currentTimeMillis() - t0) + "ms");
            }
        }
    }

    @Bean
    public RestClient restClient() {
        var connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(2); // Max number of connections in the pool
        connectionManager.setDefaultMaxPerRoute(2); // Max number of connections per route

        return RestClient.builder()//
                .requestFactory(new HttpComponentsClientHttpRequestFactory(
                        HttpClients.custom().setConnectionManager(connectionManager).build()))
                .baseUrl("http://localhost:9091")//
                .requestInterceptor(new TimeClientHttpRequestInterceptor()).build();
    }

    @GetMapping("/")
    String hello() {
        return restClient().get().uri("/delay/2").retrieve().body(String.class);
    }
}

Dalam kod di atas kami mencipta pemintas permintaan (ClientHttpRequestInterceptor) untuk mengukur masa yang kami fikir akan menjadi masa pelaksanaan permintaan kepada perkhidmatan luaran yang disokong oleh httpbin.

Kami juga secara eksplisit menetapkan kolam kepada saiz yang sangat kecil iaitu 2 sambungan untuk memudahkan masalah menghasilkan semula.

Kini kami hanya perlu memulakan httpbin, jalankan apl but spring kami dan jalankan ujian mudah menggunakan ab

$ docker run -p 9091:80 kennethreitz/httpbin
ab -n 10 -c 4 http://localhost:8080/
...
Percentage of the requests served within a certain time (ms)
  50%   4049
  66%   4054
  75%   4055
  80%   4055
  90%   4057
  95%   4057
  98%   4057
  99%   4057
 100%   4057 (longest request)
Request took: 2021ms
Request took: 2016ms
Request took: 2022ms
Request took: 4040ms
Request took: 4047ms
Request took: 4030ms
Request took: 4037ms
Request took: 4043ms
Request took: 4050ms
Request took: 4034ms

Jika kita melihat nombor, kita dapat melihat bahawa walaupun kita menetapkan kelewatan buatan selama 2 saat untuk pelayan luaran, kita sebenarnya mendapat kelewatan selama 4 saat untuk kebanyakan permintaan. Selain itu, kami mendapati bahawa hanya permintaan pertama memenuhi kelewatan yang dikonfigurasikan selama 2 saat, manakala permintaan seterusnya mengakibatkan kelewatan selama 4 saat.

Masa untuk membuat profil

Profil adalah penting apabila menghadapi gelagat kod pelik kerana ia mengenal pasti kesesakan prestasi, mendedahkan isu tersembunyi seperti kebocoran memori dan menunjukkan cara aplikasi anda menggunakan sumber sistem.

Kali ini kami akan memprofilkan apl yang sedang berjalan menggunakan JFR semasa menjalankan ujian beban ab.

$ jcmd <pid> JFR.start name=app-profile  duration=60s filename=app-profile-$(date +%FT%H-%M-%S).jfr
$ ab -n 50 -c 4 http://localhost:8080/
...
Percentage of the requests served within a certain time (ms)
  50%   4043
  66%   4051
  75%   4057
  80%   4060
  90%   4066
  95%   4068
  98%   4077
  99%   4077
 100%   4077 (longest request)

Jika kami membuka fail JFR dan melihat pada flamegraph, kami dapat melihat bahawa kebanyakan masa pelaksanaan dibelanjakan oleh klien HTTP kami. Masa pelaksanaan pelanggan dibahagikan antara menunggu perkhidmatan luaran kami bertindak balas dan menunggu untuk mendapatkan sambungan daripada kumpulan.

Metrics Can Fool You: Measuring Execution Time in Connection-Pooled Environments

Itu menjelaskan sebab masa tindak balas yang kami lihat adalah dua kali ganda daripada jangkaan kelewatan tetap selama 2 saat yang kami tetapkan untuk pelayan luaran kami. Kami mengkonfigurasi kumpulan 2 sambungan. Walau bagaimanapun, dalam ujian kami, kami melaksanakan 4 permintaan serentak. Jadi, hanya 2 permintaan pertama akan disampaikan dalam jangka masa 2 saat. Permintaan seterusnya perlu menunggu kolam untuk melepaskan sambungan, sekali gus meningkatkan masa tindak balas yang diperhatikan.

Jika kita melihat pada flamegraph sekali lagi, kita juga boleh mengetahui mengapa masa yang diukur oleh ClientHttpRequestInterceptor kami tidak menggambarkan masa yang diambil oleh pelayan luaran untuk bertindak balas tetapi masa yang diperlukan untuk mendapatkan sambungan dari kolam ditambah masa yang diperlukan untuk melaksanakan permintaan sebenar kepada pelayan luaran. Pemintas kami sebenarnya sedang membungkus jejak tindanan yang akhirnya memanggil pengurus kolam untuk mendapatkan sambungan: PoolingHttpClientConnectionManager

Memantau masa tindak balas mana-mana klien HTTP sebaiknya dilakukan menggunakan metrik terbina dalamnya kerana metrik ini direka khusus untuk menangkap maklumat pemasaan yang tepat. Mereka mengambil kira semua aspek kitaran hayat permintaan HTTP, termasuk pemerolehan sambungan, penghantaran data dan pengendalian tindak balas. Ini memastikan bahawa ukuran adalah tepat dan konsisten dengan prestasi sebenar pelanggan.

Atas ialah kandungan terperinci Metrik Boleh Menipu Anda: Mengukur Masa Pelaksanaan dalam Persekitaran Disatukan Sambungan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn