นี่คือการใช้งาน Hypertext Transfer Protocol เวอร์ชัน 2 ใน C
เลเยอร์เฟรมของ HTTP/2 ถูกนำมาใช้เป็นไลบรารี C ที่นำมาใช้ซ้ำได้ ยิ่งไปกว่านั้น เรายังติดตั้งไคลเอ็นต์ HTTP/2 เซิร์ฟเวอร์ และพร็อกซีอีกด้วย นอกจากนี้เรายังได้พัฒนาเครื่องมือทดสอบโหลดและการเปรียบเทียบประสิทธิภาพสำหรับ HTTP/2
ตัวเข้ารหัสและตัวถอดรหัส HPACK มีให้เป็น API สาธารณะ
nghttp2 เดิมได้รับการพัฒนาโดยใช้ RFC 7540 HTTP/2 และ RFC 7541 HPACK - การบีบอัดส่วนหัวสำหรับ HTTP/2 ตอนนี้เรากำลังอัปเดตโค้ดของเราเพื่อใช้ RFC 9113
ฐานรหัส nghttp2 ถูกแยกจากโครงการ spdylay (https://github.com/tatsuhiro-t/spdylay)
ตำแหน่งข้อมูลต่อไปนี้พร้อมให้ลองใช้การใช้งาน nghttp2 ของเรา
https://nghttp2.org/ (TLS + ALPN และ HTTP/3)
ตำแหน่งข้อมูลนี้รองรับ h2
, h2-16
, h2-14
และ http/1.1
ผ่าน ALPN และต้องใช้ TLSv1.2 สำหรับการเชื่อมต่อ HTTP/2
นอกจากนี้ยังรองรับ HTTP/3
http://nghttp2.org/ (อัปเกรด HTTP และ HTTP/2 โดยตรง)
h2c
และ http/1.1
จำเป็นต้องใช้แพ็กเกจต่อไปนี้เพื่อสร้างไลบรารี libnghttp2:
ในการสร้างเอกสาร คุณต้องติดตั้ง:
หากคุณต้องการ libnghttp2 (ไลบรารี C) เท่านั้น แพ็คเกจข้างต้นคือทั้งหมดที่คุณต้องการ ใช้ --enable-lib-only
เพื่อให้แน่ใจว่ามีเพียง libnghttp2 เท่านั้นที่ถูกสร้างขึ้น วิธีนี้จะหลีกเลี่ยงข้อผิดพลาดในการสร้างที่อาจเกิดขึ้นซึ่งเกี่ยวข้องกับการสร้างแอปพลิเคชันแบบรวมกลุ่ม
หากต้องการสร้างและรันแอปพลิเคชันโปรแกรม ( nghttp
, nghttpd
, nghttpx
และ h2load
) ในไดเร็กทอรี src
จำเป็นต้องมีแพ็กเกจต่อไปนี้:
หากต้องการเปิดใช้งานตัวเลือก -a
(การรับเนื้อหาที่เชื่อมโยงจากทรัพยากรที่ดาวน์โหลด) ใน nghttp
จำเป็นต้องมีแพ็คเกจต่อไปนี้:
หากต้องการเปิดใช้งานการสนับสนุน systemd ใน nghttpx จำเป็นต้องมีแพ็คเกจต่อไปนี้:
เครื่องมือ HPACK จำเป็นต้องมีแพ็คเกจต่อไปนี้:
หากต้องการสร้างซอร์สภายใต้ไดเร็กทอรีตัวอย่าง จำเป็นต้องมี libevent:
หากต้องการลดการกระจายตัวของฮีปในโปรแกรมเซิร์ฟเวอร์ที่รันระยะยาว ( nghttpd
และ nghttpx
) แนะนำให้ใช้ jemalloc:
เจมัลลอค
บันทึก
ปัจจุบัน Alpine Linux ไม่รองรับการเปลี่ยน malloc เนื่องจากข้อจำกัดด้าน musl ดูรายละเอียดในฉบับ #762
สำหรับ BoringSSL หรือ aws-lc build เพื่อเปิดใช้งานการบีบอัดใบรับรอง RFC 8879 TLS ในแอปพลิเคชัน จำเป็นต้องมีไลบรารีต่อไปนี้:
หากต้องการเปิดใช้งานการสนับสนุน mruby สำหรับ nghttpx จำเป็นต้องมี mruby เราจำเป็นต้องสร้าง mruby โดยเปิดใช้งาน C++ ABI อย่างชัดเจน และอาจต้องใช้ mrgems อื่น mruby ได้รับการจัดการโดย git submodule ภายใต้ไดเร็กทอรีบุคคลที่สาม/mruby ปัจจุบันการสนับสนุน mruby สำหรับ nghttpx ถูกปิดใช้งานตามค่าเริ่มต้น หากต้องการเปิดใช้งานการสนับสนุน mruby ให้ใช้ตัวเลือกกำหนดค่า --with-mruby
โปรดทราบว่าในขณะที่เขียนนี้ แพ็คเกจ libmruby-dev และ mruby ใน Debian/Ubuntu ไม่สามารถใช้ได้กับ nghttp2 เนื่องจากไม่ได้เปิดใช้งาน C++ ABI ในการสร้าง mruby จำเป็นต้องมีแพ็คเกจต่อไปนี้:
nghttpx รองรับเอ็นจิ้นการแยกสิทธิ์แบบ Neverbleed สำหรับ OpenSSL กล่าวโดยย่อคือ ช่วยลดความเสี่ยงของการรั่วไหลของคีย์ส่วนตัวเมื่อมีการหาประโยชน์จากข้อผิดพลาดร้ายแรงเช่น Heartbleed Neverbleed ถูกปิดใช้งานตามค่าเริ่มต้น หากต้องการเปิดใช้งานให้ใช้ตัวเลือกการกำหนดค่า --with-neverbleed
หากต้องการเปิดใช้งานการสนับสนุน HTTP/3 รุ่นทดลองสำหรับ h2load และ nghttpx จำเป็นต้องมีไลบรารีต่อไปนี้:
ใช้ตัวเลือกการกำหนดค่า --enable-http3
เพื่อเปิดใช้งานคุณสมบัติ HTTP/3 สำหรับ h2load และ nghttpx
ในการสร้างโปรแกรมเสริม eBPF เพื่อกำหนดทิศทางดาตาแกรม QUIC UDP ขาเข้าไปยังซ็อกเก็ตที่ถูกต้องสำหรับ nghttpx จำเป็นต้องมีไลบรารีต่อไปนี้:
ใช้ตัวเลือก --with-libbpf
กำหนดค่าเพื่อสร้างโปรแกรม eBPF จำเป็นต้องใช้ libelf-dev เพื่อสร้าง libbpf
สำหรับ Ubuntu 20.04 คุณสามารถสร้าง libbpf จากซอร์สโค้ดได้ nghttpx ต้องใช้โปรแกรม eBPF เพื่อโหลดการกำหนดค่าใหม่และการสลับไฟล์ปฏิบัติการแบบ hot swap
การคอมไพล์ซอร์สโค้ด libnghttp2 C ต้องใช้คอมไพเลอร์ C99 gcc 4.8 เป็นที่รู้กันว่าเพียงพอ ในการคอมไพล์ซอร์สโค้ด C++ จำเป็นต้องมีคอมไพเลอร์ที่สอดคล้องกับ C++20 อย่างน้อย g++ >= 12 และ clang++ >= 15 เป็นที่รู้กันว่าใช้งานได้
บันทึก
หากต้องการเปิดใช้งานการสนับสนุน mruby ใน nghttpx และใช้ตัวเลือกการกำหนดค่า --with-mruby
บันทึก
ผู้ใช้ Mac OS X อาจต้องใช้ตัวเลือก --disable-threads
กำหนดค่าเพื่อปิดใช้งานมัลติเธรดใน nghttpd, nghttpx และ h2load เพื่อป้องกันไม่ให้เกิดปัญหา เรายินดีต้อนรับแพตช์เพื่อให้การทำงานแบบมัลติเธรดบนแพลตฟอร์ม Mac OS X
บันทึก
หากต้องการคอมไพล์แอปพลิเคชันที่เกี่ยวข้อง (nghttp, nghttpd, nghttpx และ h2load) คุณต้องใช้ตัวเลือก --enable-app
กำหนดค่า และตรวจสอบให้แน่ใจว่าเป็นไปตามข้อกำหนดที่ระบุข้างต้น โดยปกติ กำหนดค่าการตรวจสอบสคริปต์การขึ้นต่อกันที่จำเป็นเพื่อสร้างแอปพลิเคชันเหล่านี้ และเปิดใช้งาน --enable-app
โดยอัตโนมัติ ดังนั้นคุณไม่จำเป็นต้องใช้งานอย่างชัดเจน แต่ถ้าคุณพบว่าแอปพลิเคชันไม่ได้ถูกสร้างขึ้น การใช้ --enable-app
อาจพบสาเหตุนั้น เช่น การพึ่งพาที่หายไป
บันทึก
เพื่อตรวจจับไลบรารีของบุคคลที่สาม จะใช้ pkg-config (แต่เราจะไม่ใช้ pkg-config สำหรับไลบรารีบางอัน (เช่น libev)) ตามค่าเริ่มต้น pkg-config จะค้นหาไฟล์ *.pc
ในตำแหน่งมาตรฐาน (เช่น /usr/lib/pkgconfig) หากจำเป็นต้องใช้ไฟล์ *.pc
ในตำแหน่งที่กำหนดเอง ให้ระบุพาธไปยังตัวแปรสภาพแวดล้อม PKG_CONFIG_PATH
แล้วส่งต่อเพื่อกำหนดค่าสคริปต์ เช่น:
$ ./configure PKG_CONFIG_PATH=/path/to/pkgconfig
สำหรับไลบรารีที่ได้รับการจัดการ pkg-config จะมีการกำหนดตัวแปรสภาพแวดล้อม *_CFLAG
และ *_LIBS
(เช่น OPENSSL_CFLAGS
, OPENSSL_LIBS
) การระบุสตริงที่ไม่ว่างเปล่าให้กับตัวแปรเหล่านี้จะแทนที่ pkg-config โดยสิ้นเชิง กล่าวอีกนัยหนึ่ง หากมีการระบุไว้ ระบบจะไม่ใช้ pkg-config ในการตรวจหา และผู้ใช้มีหน้าที่ระบุค่าที่ถูกต้องให้กับตัวแปรเหล่านี้ หากต้องการดูรายการตัวแปรเหล่านี้ทั้งหมด ให้รัน ./configure -h
หากคุณใช้ Ubuntu 22.04 LTS ให้รันสิ่งต่อไปนี้เพื่อติดตั้งแพ็คเกจที่จำเป็น:
sudo apt-get ติดตั้ง g++ clang ทำ binutils autoconf automake
autotools-dev libtool pkg-config
zlib1g-dev libssl-dev libxml2-dev libev-dev
libevent-dev libjansson-dev
libc-ares-dev libjemalloc-dev libsystemd-dev
ruby-dev วัวกระทิง libelf-dev
โปรเจ็กต์ nghttp2 เผยแพร่ไฟล์เก็บถาวร tar เป็นประจำซึ่งรวมถึงซอร์สโค้ด nghttp2 และไฟล์บิลด์ที่สร้างขึ้น สามารถดาวน์โหลดได้จากหน้าการเผยแพร่
การสร้าง nghttp2 จาก git ต้องใช้แพ็คเกจการพัฒนาเครื่องมืออัตโนมัติ การสร้างจากไฟล์เก็บถาวร tar ไม่ต้องการสิ่งเหล่านั้น และด้วยเหตุนี้จึงง่ายกว่ามาก ขั้นตอนการสร้างปกติจะเป็นดังนี้:
$ tar xf nghttp2-XYZtar.bz2
$ ซีดี nghttp2-XYZ
$ ./configure
$ ทำ
การสร้างจาก git นั้นง่ายมาก แต่โปรดตรวจสอบให้แน่ใจว่ามีการใช้ autoconf 2.68 เป็นอย่างน้อย:
$ git อัพเดตโมดูลย่อย --init
$ การตรวจสอบอัตโนมัติ -i
$ ออโต้เมค
$ คอนฟิกอัตโนมัติ
$ ./configure
$ ทำ
วิธีที่ง่ายที่สุดในการสร้าง Windows nghttp2 dll ดั้งเดิมคือการใช้ cmake Visual C++ Build Tools เวอร์ชันฟรีทำงานได้ดี
cmake
ภายใน nghttp2 โดยตรงcmake --build
เพื่อสร้างไลบรารี่โปรดทราบว่าขั้นตอนข้างต้นมักจะสร้างไลบรารี nghttp2 เท่านั้น ไม่มีการคอมไพล์แอปพลิเคชันแบบรวมกลุ่ม
ภายใต้สภาพแวดล้อม Mingw คุณสามารถคอมไพล์ได้เฉพาะไลบรารีเท่านั้น คือ libnghttp2-X.dll
และ libnghttp2.a
หากคุณต้องการคอมไพล์แอปพลิเคชัน ( h2load
, nghttp
, nghttpx
, nghttpd
) คุณต้องใช้สภาพแวดล้อม Cygwin
ภายใต้สภาพแวดล้อม Cygwin เพื่อคอมไพล์แอปพลิเคชันที่คุณต้องคอมไพล์และติดตั้ง libev ก่อน
ประการที่สอง คุณต้องยกเลิกการกำหนดมาโคร __STRICT_ANSI__
หากคุณไม่กำหนด ฟังก์ชัน fdopen
, fileno
และ strptime
จะไม่พร้อมใช้งาน
คำสั่งตัวอย่างดังนี้:
$ ส่งออก CFLAGS = "-U__STRICT_ANSI__ -I$libev_PREFIX/include -L$libev_PREFIX/lib"
$ ส่งออก CXXFLAGS=$CFLAGS
$ ./configure
$ ทำ
หากคุณต้องการคอมไพล์แอปพลิเคชันภายใต้ examples/
คุณต้องลบหรือเปลี่ยนชื่อ event.h
ออกจากการติดตั้งของ libev เนื่องจากขัดแย้งกับการติดตั้งของ libevent
หลังจากติดตั้งชุดเครื่องมือ nghttp2 ด้วย make install
อาจพบข้อผิดพลาดที่คล้ายกัน:
nghttpx: ข้อผิดพลาดขณะโหลดไลบรารีที่แชร์: libnghttp2.so.14: ไม่สามารถเปิดไฟล์วัตถุที่แชร์: ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว
ซึ่งหมายความว่าเครื่องมือไม่สามารถค้นหาไลบรารีที่แบ่งใช้ libnghttp2.so
ได้
หากต้องการอัปเดตแคชไลบรารีที่ใช้ร่วมกันให้รัน sudo ldconfig
บันทึก
เอกสารยังไม่สมบูรณ์
หากต้องการสร้างเอกสาร ให้รัน:
$ สร้าง html
เอกสารจะถูกสร้างขึ้นภายใต้ doc/manual/html/
เอกสารที่สร้างขึ้นจะไม่ถูกติดตั้งพร้อมกับ make install
เอกสารออนไลน์มีอยู่ที่ https://nghttp2.org/documentation/
หากต้องการสร้าง h2load และ nghttpx โดยเปิดใช้งานคุณสมบัติ HTTP/3 ให้รันสคริปต์กำหนดค่าด้วย --enable-http3
เพื่อให้ nghttpx โหลดการกำหนดค่าซ้ำและสลับปฏิบัติการได้ในขณะที่ยุติกระบวนการของผู้ปฏิบัติงานเก่าอย่างสวยงาม จำเป็นต้องมี eBPF รันสคริปต์กำหนดค่าด้วย --enable-http3 --with-libbpf
เพื่อสร้างโปรแกรม eBPF ต้องตั้งค่าวัสดุการคีย์ QUIC ด้วย --frontend-quic-secret-file
เพื่อให้การเชื่อมต่อที่มีอยู่ยังคงอยู่ในระหว่างการโหลดซ้ำ
ขั้นตอนโดยละเอียดในการสร้าง h2load และ nghttpx ที่เปิดใช้งาน HTTP/3 เป็นไปตาม
สร้าง aws-lc:
$ git clone --ความลึก 1 -b v1.39.0 https://github.com/aws/aws-lc
$ ซีดี aws-lc
$ cmake -B build -DDISABLE_GO=ON --install-prefix=$PWD/opt
$ make -j$(nproc) -C บิลด์
$ cmake -- ติดตั้งบิลด์
$ซีดี..
สร้าง nghttp3:
$ git clone --ความลึก 1 -b v1.6.0 https://github.com/ngtcp2/nghttp3
$ ซีดี nghttp3
$ git อัปเดตโมดูลย่อย --init --ความลึก 1
$ การตรวจสอบอัตโนมัติ -i
$ ./configure --prefix=$PWD/build --enable-lib-only
$ ทำ -j$(nproc)
$ ทำการติดตั้ง
$ซีดี..
สร้าง ngtcp2:
$ git clone --ความลึก 1 -b v1.9.1 https://github.com/ngtcp2/ngtcp2
$ ซีดี ngtcp2
$ git อัปเดตโมดูลย่อย --init --ความลึก 1
$ การตรวจสอบอัตโนมัติ -i
$ ./configure --prefix=$PWD/build --enable-lib-only --with-boringssl
BORINGSSL_CFLAGS="-I$PWD/../aws-lc/opt/include"
BORINGSSL_LIBS="-L$PWD/../aws-lc/opt/lib -lssl -lcrypto"
$ ทำ -j$(nproc)
$ ทำการติดตั้ง
$ซีดี..
หากการแจกจ่าย Linux ของคุณไม่มี libbpf-dev >= 0.7.0 ให้สร้างจากแหล่งที่มา:
$ git clone --ความลึก 1 -b v1.4.6 https://github.com/libbpf/libbpf
$ ซีดี libbpf
$ PREFIX=$PWD/build ทำการติดตั้ง -C src
$ซีดี..
สร้าง nghttp2:
$ โคลนคอมไพล์ https://github.com/nghttp2/nghttp2
$ ซีดี nghttp2
$ git อัพเดตโมดูลย่อย --init
$ การตรวจสอบอัตโนมัติ -i
$ ./configure --with-mruby --enable-http3 --with-libbpf
CC=เสียงดังกราว-15 CXX=เสียงดังกราว++-15
PKG_CONFIG_PATH="$PWD/../aws-lc/opt/lib/pkgconfig:$PWD/../nghttp3/build/lib/pkgconfig:$PWD/../ngtcp2/build/lib/pkgconfig:$PWD/ ../libbpf/build/lib64/pkgconfig"
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/../aws-lc/opt/lib -Wl,-rpath,$PWD/../libbpf/build/lib64"
$ ทำ -j$(nproc)
ควรพบโปรแกรม eBPF reuseport_kern.o
ใต้ไดเร็กทอรี bpf ส่งตัวเลือก --quic-bpf-program-file=bpf/reuseport_kern.o
ไปที่ nghttpx เพื่อโหลด ดูเพิ่มเติมที่ส่วน HTTP/3 ใน nghttpx - พร็อกซี HTTP/2 - HOW-TO
การทดสอบหน่วยทำได้โดยการเรียกใช้ make check
เรามีการทดสอบการรวมสำหรับพร็อกซีเซิร์ฟเวอร์ nghttpx การทดสอบเขียนด้วยภาษาโปรแกรม Go และใช้กรอบการทดสอบ เราขึ้นอยู่กับไลบรารีต่อไปนี้:
โมดูล Go จะดาวน์โหลดการอ้างอิงเหล่านี้โดยอัตโนมัติ
หากต้องการรันการทดสอบ ให้รันคำสั่งต่อไปนี้ภายใต้ไดเร็กทอรี integration-tests
:
$ ทำมัน
ภายในการทดสอบ เราใช้พอร์ต 3009 เพื่อรันเซิร์ฟเวอร์หัวข้อการทดสอบ
nghttp2 v1.0.0 นำเสนอการเปลี่ยนแปลงที่เข้ากันไม่ได้แบบย้อนหลังหลายประการ ในส่วนนี้ เราจะอธิบายการเปลี่ยนแปลงเหล่านี้และวิธีการโยกย้ายไปยังเวอร์ชัน 1.0.0
h2
และ h2c
ก่อนหน้านี้เราประกาศ h2-14
และ h2c-14
v1.0.0 ใช้เวอร์ชันโปรโตคอลสุดท้าย และเราเปลี่ยน ALPN ID เป็น h2
และ h2c
มาโคร NGHTTP2_PROTO_VERSION_ID
, NGHTTP2_PROTO_VERSION_ID_LEN
, NGHTTP2_CLEARTEXT_PROTO_VERSION_ID
และ NGHTTP2_CLEARTEXT_PROTO_VERSION_ID_LEN
ได้รับการอัปเดตเพื่อแสดงการเปลี่ยนแปลงนี้
โดยพื้นฐานแล้ว แอปพลิเคชันที่มีอยู่ไม่จำเป็นต้องทำอะไร เพียงแค่คอมไพล์ใหม่ก็เพียงพอแล้วสำหรับการเปลี่ยนแปลงนี้
เราใช้ "คำนำการเชื่อมต่อไคลเอ็นต์" เพื่อหมายถึง 24 ไบต์แรกของคำนำการเชื่อมต่อไคลเอ็นต์ สิ่งนี้ไม่ถูกต้องในทางเทคนิค เนื่องจากคำนำการเชื่อมต่อไคลเอ็นต์ประกอบด้วยสตริงไบต์เมจิกไคลเอ็นต์ขนาด 24 ไบต์ ตามด้วยเฟรม SETTINGS เพื่อความชัดเจน เราเรียก "client magic" สำหรับสตริงไบต์ 24 ไบต์นี้และ API ที่อัปเดต
NGHTTP2_CLIENT_CONNECTION_PREFACE
ถูกแทนที่ด้วย NGHTTP2_CLIENT_MAGIC
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN
ถูกแทนที่ด้วย NGHTTP2_CLIENT_MAGIC_LEN
NGHTTP2_BAD_PREFACE
ถูกเปลี่ยนชื่อเป็น NGHTTP2_BAD_CLIENT_MAGIC
NGHTTP2_CLIENT_CONNECTION_HEADER
และ NGHTTP2_CLIENT_CONNECTION_HEADER_LEN
ที่เลิกใช้แล้วถูกลบออกแล้ว
หากแอปพลิเคชันใช้มาโครเหล่านี้ ให้แทนที่มาโครเก่าด้วยมาโครใหม่ ตั้งแต่เวอร์ชัน 1.0.0 ไคลเอนต์เวทย์มนตร์จะถูกส่งโดยไลบรารี (ดูส่วนย่อยถัดไป) ดังนั้นแอปพลิเคชันไคลเอนต์อาจลบการใช้มาโครเหล่านี้ออกไป
ก่อนหน้านี้ไลบรารี nghttp2 ไม่ได้ส่งเวทย์มนตร์ของไคลเอนต์ ซึ่งเป็นสตริง 24 ไบต์แรกของคำนำการเชื่อมต่อไคลเอนต์ และแอปพลิเคชันไคลเอนต์จะต้องส่งด้วยตัวเอง ตั้งแต่เวอร์ชัน 1.0.0 ไคลเอ็นต์เมจิกจะถูกส่งโดยไลบรารีผ่านการเรียกครั้งแรกของ nghttp2_session_send()
หรือ nghttp2_session_mem_send2()
แอปพลิเคชันไคลเอ็นต์ที่ส่งเวทมนตร์ไคลเอ็นต์จะต้องลบโค้ดที่เกี่ยวข้องออก
ข้อมูลจำเพาะของ Alt-Svc ยังไม่สิ้นสุด เพื่อให้ API ของเรามีเสถียรภาพ เราได้ตัดสินใจลบ API ที่เกี่ยวข้องกับ Alt-Svc ทั้งหมดออกจาก nghttp2
NGHTTP2_EXT_ALTSVC
แล้วnghttp2_ext_altsvc
ถูกลบแล้วเราได้ลบฟังก์ชันการทำงานของ Alt-Svc ในซีรีส์ v0.7 ออกแล้ว และฟังก์ชันเหล่านี้ก็ไม่มีอะไรเลย แอปพลิเคชันที่ใช้แมโครและโครงสร้างเหล่านี้ ให้ลบบรรทัดเหล่านั้นออก
ก่อนหน้านี้ nghttp2_on_invalid_frame_recv_cb_called
รับ error_code
ซึ่งกำหนดใน nghttp2_error_code
เป็นพารามิเตอร์ แต่ไม่มีรายละเอียดเพียงพอที่จะแก้ไขข้อบกพร่อง ดังนั้นเราจึงตัดสินใจใช้ค่า nghttp2_error
ที่มีรายละเอียดมากขึ้นแทน
แอปพลิเคชันที่ใช้การโทรกลับนี้ควรอัปเดตลายเซ็นการโทรกลับ หากถือว่า error_code
เป็นรหัสข้อผิดพลาด HTTP/2 ให้อัปเดตโค้ดเพื่อให้ถือเป็น nghttp2_error
ก่อนหน้านี้ nghttp2 ไม่ได้ประมวลผลเวทย์มนตร์ไคลเอนต์ (สตริงไบต์ 24 ไบต์) เพื่อจัดการกับมัน เราต้องใช้ nghttp2_option_set_recv_client_preface()
ตั้งแต่เวอร์ชัน 1.0.0 เป็นต้นมา nghttp2 จะประมวลผล Magic Client ตามค่าเริ่มต้น และ nghttp2_option_set_recv_client_preface()
จะถูกลบออก
แอปพลิเคชั่นบางตัวอาจต้องการปิดการใช้งานพฤติกรรมนี้ ดังนั้นเราจึงเพิ่ม nghttp2_option_set_no_recv_client_magic()
เพื่อให้บรรลุเป้าหมายนี้
แอปพลิเคชันที่ใช้ nghttp2_option_set_recv_client_preface()
ที่มีค่าไม่เป็นศูนย์ ให้ลบออก
แอปพลิเคชันที่ใช้ nghttp2_option_set_recv_client_preface()
ที่มีค่าเป็นศูนย์หรือไม่ได้ใช้จะต้องใช้ nghttp2_option_set_no_recv_client_magic()
ที่มีค่าที่ไม่ใช่ศูนย์
ไดเร็กทอรี src
มีไคลเอ็นต์ HTTP/2 เซิร์ฟเวอร์ และโปรแกรมพร็อกซี
nghttp
เป็นไคลเอ็นต์ HTTP/2 สามารถเชื่อมต่อกับเซิร์ฟเวอร์ HTTP/2 ที่มีความรู้เดิม อัปเกรด HTTP และส่วนขยาย ALPN TLS
มีโหมดเอาต์พุตแบบละเอียดสำหรับจัดเฟรมข้อมูล นี่คือตัวอย่างเอาต์พุตจากไคลเอนต์ nghttp
:
$ nghttp -nv https://nghttp2.org
[ 0.190] เชื่อมต่อแล้ว
โปรโตคอลการเจรจา: h2
[0.212] recv การตั้งค่าเฟรม
(นิฟ=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.212] ส่งเฟรมการตั้งค่า
(นิฟ=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.212] ส่งเฟรมการตั้งค่า
- อ๊ากก
(นิฟ=0)
[ 0.212] ส่งเฟรม PRIORITY
(dep_stream_id=0, น้ำหนัก=201, พิเศษ=0)
[ 0.212] ส่งเฟรม PRIORITY
(dep_stream_id=0, น้ำหนัก=101, พิเศษ=0)
[ 0.212] ส่งเฟรม PRIORITY
(dep_stream_id=0, น้ำหนัก=1, พิเศษ=0)
[ 0.212] ส่งเฟรม PRIORITY
(dep_stream_id=7, น้ำหนัก=1, พิเศษ=0)
[ 0.212] ส่งเฟรม PRIORITY
(dep_stream_id=3, น้ำหนัก=1, พิเศษ=0)
[ 0.212] ส่งเฟรม HEADERS
- END_สตรีม | END_HEADERS | ลำดับความสำคัญ
(padlen=0, dep_stream_id=11, น้ำหนัก=16, พิเศษ=0)
- เปิดสตรีมใหม่
:method: รับ
:เส้นทาง: /
:scheme: https
:ผู้มีอำนาจ: nghttp2.org
ยอมรับ: */*
ยอมรับการเข้ารหัส: gzip, deflate
ตัวแทนผู้ใช้: nghttp2/1.0.1-DEV
[0.221] recv การตั้งค่าเฟรม
- อ๊ากก
(นิฟ=0)
[ 0.221] รับ (stream_id=13) :วิธีการ: GET
[ 0.221] รับ (stream_id=13) :scheme: https
[ 0.221] recv (stream_id=13) :path: /stylesheets/screen.css
[ 0.221] recv (stream_id=13) :ผู้มีอำนาจ: nghttp2.org
[0.221] recv (stream_id=13) ยอมรับการเข้ารหัส: gzip, deflate
[0.222] recv (stream_id=13) ตัวแทนผู้ใช้: nghttp2/1.0.1-DEV
[ 0.222] recv PUSH_PROMISE เฟรม <ความยาว=50, flags=0x04, stream_id=13>
- END_HEADERS
(padlen=0, สัญญา_สตรีม_id=2)
[ 0.222] รับ (stream_id=13) :สถานะ: 200
[ 0.222] recv (stream_id=13) วันที่: พฤหัสบดี 21 พฤษภาคม 2558 16:38:14 GMT
[ 0.222] recv (stream_id=13) ประเภทเนื้อหา: text/html
[ 0.222] recv (stream_id=13) แก้ไขล่าสุด: ศุกร์ 15 พฤษภาคม 2558 15:38:06 GMT
[ 0.222] recv (stream_id=13) etag: W/"555612de-19f6"
[ 0.222] รับลิงก์ (stream_id=13): ; rel=โหลดล่วงหน้า; เป็น=สไตล์ชีท
[0.222] recv (stream_id=13) การเข้ารหัสเนื้อหา: gzip
[0.222] เซิร์ฟเวอร์รับ (stream_id=13) เซิร์ฟเวอร์: nghttpx nghttp2/1.0.1-DEV
[ 0.222] recv (stream_id=13) ผ่าน: 1.1 nghttpx
[ 0.222] recv (stream_id=13) ความปลอดภัยในการขนส่งที่เข้มงวด: อายุสูงสุด=31536000
[ 0.222] recv HEADERS frame <ความยาว=166, flags=0x04, stream_id=13>
- END_HEADERS
(พาเลน=0)
- ส่วนหัวของคำตอบแรก
[0.222] recv ข้อมูลเฟรม
- END_STREAM
[ 0.222] รับ (stream_id=2) :สถานะ: 200
[ 0.222] recv (stream_id=2) วันที่: พฤหัสบดี 21 พฤษภาคม 2558 16:38:14 GMT
[ 0.222] recv (stream_id=2) ประเภทเนื้อหา: text/css
[ 0.222] recv (stream_id=2) แก้ไขล่าสุด: ศุกร์ 15 พฤษภาคม 2558 15:38:06 GMT
[ 0.222] recv (stream_id=2) etag: W/"555612de-9845"
[0.222] recv (stream_id=2) การเข้ารหัสเนื้อหา: gzip
[0.222] เซิร์ฟเวอร์รับ (stream_id=2): nghttpx nghttp2/1.0.1-DEV
[ 0.222] recv (stream_id=2) ผ่าน: 1.1 nghttpx
[ 0.222] recv (stream_id=2) ความปลอดภัยในการขนส่งที่เข้มงวด: อายุสูงสุด=31536000
[ 0.222] recv HEADERS frame <ความยาว=32, flags=0x04, stream_id=2>
- END_HEADERS
(พาเลน=0)
- ส่วนหัวการตอบกลับแบบพุชครั้งแรก
[0.228] recv ข้อมูลเฟรม <ความยาว=8715, flags=0x01, stream_id=2>
- END_STREAM
[ 0.228] ส่งเฟรม GOAWAY
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
การอัปเกรด HTTP ดำเนินการดังนี้:
$ nghttp -nvu http://nghttp2.org
[ 0.011] เชื่อมต่อแล้ว
[0.011] คำขออัปเกรด HTTP
รับ / HTTP/1.1
โฮสต์: nghttp2.org
การเชื่อมต่อ: อัปเกรด การตั้งค่า HTTP2
อัปเกรด: h2c
การตั้งค่า HTTP2: AAMAAABkAAQAAP__
ยอมรับ: */*
ตัวแทนผู้ใช้: nghttp2/1.0.1-DEV
[0.018] การตอบสนองการอัพเกรด HTTP
HTTP/1.1 101 โปรโตคอลการสลับ
การเชื่อมต่อ: อัปเกรด
อัปเกรด: h2c
[0.018] อัปเกรด HTTP สำเร็จ
[ 0.018] recv การตั้งค่าเฟรม
(นิฟ=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.018] ส่งเฟรมการตั้งค่า
(นิฟ=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.018] ส่งเฟรมการตั้งค่า
- อ๊ากก
(นิฟ=0)
[ 0.018] ส่งเฟรม PRIORITY
(dep_stream_id=0, น้ำหนัก=201, พิเศษ=0)
[ 0.018] ส่งเฟรม PRIORITY
(dep_stream_id=0, น้ำหนัก=101, พิเศษ=0)
[ 0.018] ส่งเฟรม PRIORITY
(dep_stream_id=0, น้ำหนัก=1, พิเศษ=0)
[ 0.018] ส่งเฟรม PRIORITY
(dep_stream_id=7, น้ำหนัก=1, พิเศษ=0)
[ 0.018] ส่งเฟรม PRIORITY
(dep_stream_id=3, น้ำหนัก=1, พิเศษ=0)
[ 0.018] ส่งเฟรม PRIORITY
(dep_stream_id=11, น้ำหนัก=16, พิเศษ=0)
[ 0.019] รับ (stream_id=1) :วิธีการ: GET
[ 0.019] recv (stream_id=1) :scheme: http
[ 0.019] recv (stream_id=1) :path: /stylesheets/screen.css
[0.019] recv (stream_id=1) โฮสต์: nghttp2.org
[0.019] recv (stream_id=1) ตัวแทนผู้ใช้: nghttp2/1.0.1-DEV
[ 0.019] recv PUSH_PROMISE เฟรม <ความยาว=49, flags=0x04, stream_id=1>
- END_HEADERS
(padlen=0, สัญญา_สตรีม_id=2)
[ 0.019] รับ (stream_id=1) :สถานะ: 200
[ 0.019] recv (stream_id=1) วันที่: พฤหัสบดี 21 พฤษภาคม 2558 16:39:16 GMT
[0.019] recv (stream_id=1) ประเภทเนื้อหา: text/html
[ 0.019] recv (stream_id=1) ความยาวเนื้อหา: 6646
[ 0.019] recv (stream_id=1) แก้ไขล่าสุด: ศุกร์ 15 พฤษภาคม 2558 15:38:06 GMT
[ 0.019] recv (stream_id=1) etag: "555612de-19f6"
[ 0.019] recv (stream_id=1) ลิงก์: ; rel=โหลดล่วงหน้า; เป็น=สไตล์ชีต
[0.019] recv (stream_id=1) ช่วงที่ยอมรับ: ไบต์
[0.019] recv (stream_id=1) เซิร์ฟเวอร์: nghttpx nghttp2/1.0.1-DEV
[ 0.019] recv (stream_id=1) ผ่าน: 1.1 nghttpx
[ 0.019] recv HEADERS frame <ความยาว=157, flags=0x04, stream_id=1>
- END_HEADERS
(พาเลน=0)
- ส่วนหัวของคำตอบแรก
[0.019] recv ข้อมูลเฟรม
- END_STREAM
[ 0.019] รับ (stream_id=2) :สถานะ: 200
[ 0.019] recv (stream_id=2) วันที่: พฤหัสบดี 21 พฤษภาคม 2558 16:39:16 GMT
[ 0.019] recv (stream_id=2) ประเภทเนื้อหา: text/css
[ 0.019] recv (stream_id=2) ความยาวเนื้อหา: 38981
[ 0.019] recv (stream_id=2) แก้ไขล่าสุด: ศุกร์ 15 พฤษภาคม 2558 15:38:06 GMT
[ 0.019] recv (stream_id=2) etag: "555612de-9845"
[0.019] recv (stream_id=2) ช่วงที่ยอมรับ: ไบต์
[0.019] เซิร์ฟเวอร์รับ (stream_id=2): nghttpx nghttp2/1.0.1-DEV
[ 0.019] recv (stream_id=2) ผ่าน: 1.1 nghttpx
[ 0.019] recv HEADERS frame <ความยาว=36, flags=0x04, stream_id=2>
- END_HEADERS
(พาเลน=0)
- ส่วนหัวการตอบกลับแบบพุชครั้งแรก
[ 0.026] recv ข้อมูลเฟรม
[0.027] recv ข้อมูลเฟรม <ความยาว=7952, flags=0x00, stream_id=2>
[ 0.027] ส่งเฟรม WINDOW_UPDATE
(window_size_increase=33343)
[ 0.032] ส่งเฟรม WINDOW_UPDATE
(window_size_increase=33707)
[ 0.032] recv ข้อมูลเฟรม
- END_STREAM
[ 0.032] recv การตั้งค่าเฟรม
- อ๊ากก
(นิฟ=0)
[ 0.032] ส่งเฟรม GOAWAY
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
การใช้ตัวเลือก -s
nghttp
จะพิมพ์ข้อมูลเวลาสำหรับการร้องขอ จัดเรียงตามเวลาที่เสร็จสิ้น:
$ nghttp -nas https://nghttp2.org/
***** สถิติ *****
ระยะเวลาขอ:
responseEnd: เวลาที่ได้รับไบต์สุดท้ายของการตอบกลับ
สัมพันธ์กับการเชื่อมต่อสิ้นสุด
requestStart: เวลาก่อนที่จะส่งคำขอไบต์แรก
สัมพันธ์กับการเชื่อมต่อสิ้นสุด หากแสดง '*' แสดงว่าเป็นเช่นนี้
ผลักดันโดยเซิร์ฟเวอร์
กระบวนการ: responseEnd - requestStart
รหัส: รหัสสถานะ HTTP
ขนาด: จำนวนไบต์ที่ได้รับเป็นเนื้อหาการตอบสนองที่ไม่มี
อัตราเงินเฟ้อ
URI: ขอ URI
ดูhttp://www.w3.org/TR/resource-timing/#processing-model
จัดเรียงตาม 'เสร็จสมบูรณ์'
รหัสการตอบสนองสิ้นสุดคำขอเริ่มต้นเส้นทางคำขอขนาดรหัสกระบวนการ
13 +37.19ms +280us 36.91ms 200 2K /
2 +72.65ms * +36.38ms 36.26ms 200 8K /stylesheets/screen.css
17 +77.43ms +38.67ms 38.75ms 200 3K /javascripts/octopress.js
15 +78.12ms +38.66ms 39.46ms 200 3K /javascripts/modernizr-2.0.js
การใช้ตัวเลือก -r
ทำให้ nghttp
เขียนข้อมูลเวลาโดยละเอียดเพิ่มเติมไปยังไฟล์ที่กำหนดในรูปแบบ HAR
nghttpd
เป็นเว็บเซิร์ฟเวอร์แบบสแตติกแบบมัลติเธรด
โดยค่าเริ่มต้น จะใช้การเชื่อมต่อ SSL/TLS ใช้ตัวเลือก --no-tls
เพื่อปิดการใช้งาน
nghttpd
ยอมรับเฉพาะการเชื่อมต่อ HTTP/2 ผ่าน ALPN หรือการเชื่อมต่อ HTTP/2 โดยตรง ไม่รองรับการอัพเกรด HTTP
ตัวเลือก -p
อนุญาตให้ผู้ใช้กำหนดค่าการพุชเซิร์ฟเวอร์
เช่นเดียวกับ nghttp
มันมีโหมดเอาต์พุตแบบละเอียดสำหรับการจัดเฟรมข้อมูล นี่คือตัวอย่างเอาต์พุตจาก nghttpd
:
$ nghttpd --no-tls -v 8080
IPv4: ฟัง 0.0.0.0:8080
IPv6: ฟัง :::8080
[id=1] [ 1.521] ส่งการตั้งค่าเฟรม
(นิฟ=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=1] [ 1.521] รับการตั้งค่าเฟรม <ความยาว=12, ธง=0x00, stream_id=0>
(นิฟ=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[id=1] [ 1.521] รับการตั้งค่าเฟรม <ความยาว=0, ธง=0x01, stream_id=0>
- อ๊ากก
(นิฟ=0)
[id=1] [ 1.521] รับเฟรมลำดับความสำคัญ <ความยาว=5, ธง=0x00, stream_id=3>
(dep_stream_id=0, น้ำหนัก=201, พิเศษ=0)
[id=1] [ 1.521] รับเฟรมลำดับความสำคัญ <ความยาว=5, ธง=0x00, stream_id=5>
(dep_stream_id=0, น้ำหนัก=101, พิเศษ=0)
[id=1] [ 1.521] รับเฟรมลำดับความสำคัญ <ความยาว=5, ธง=0x00, stream_id=7>
(dep_stream_id=0, น้ำหนัก=1, พิเศษ=0)
[id=1] [ 1.521] รับเฟรม PRIORITY <ความยาว=5, flags=0x00, stream_id=9>
(dep_stream_id=7, น้ำหนัก=1, พิเศษ=0)
[id=1] [ 1.521] รับเฟรมลำดับความสำคัญ <ความยาว=5, ธง=0x00, stream_id=11>
(dep_stream_id=3, น้ำหนัก=1, พิเศษ=0)
[id=1] [ 1.521] รับ (stream_id=13) :วิธีการ: GET
[id=1] [ 1.521] รับ (stream_id=13) :path: /
[id=1] [ 1.521] รับ (stream_id=13) :scheme: http
[id=1] [1.521] recv (stream_id=13) :อำนาจ: localhost:8080
[id=1] [ 1.521] รับ (stream_id=13) ยอมรับ: */*
[id=1] [ 1.521] recv (stream_id=13) ยอมรับการเข้ารหัส: gzip, deflate
[id=1] [ 1.521] recv (stream_id=13) ตัวแทนผู้ใช้: nghttp2/1.0.0-DEV
[id=1] [ 1.521] recv HEADERS frame <ความยาว=41, flags=0x25, stream_id=13>
- END_STREAM | END_HEADERS | ลำดับความสำคัญ
(padlen=0, dep_stream_id=11, น้ำหนัก=16, พิเศษ=0)
- เปิดสตรีมใหม่
[id=1] [ 1.521] ส่งการตั้งค่าเฟรม
- อ๊ากก
(นิฟ=0)
[id=1] [ 1.521] ส่งเฟรม HEADERS
- END_HEADERS
(พาเลน=0)
- ส่วนหัวของคำตอบแรก
:สถานะ: 200
เซิร์ฟเวอร์: nghttpd nghttp2/1.0.0-DEV
ความยาวเนื้อหา: 10
การควบคุมแคช: อายุสูงสุด = 3600
วันที่: วันศุกร์ที่ 15 พฤษภาคม 2558 เวลา 14:49:04 น. GMT
แก้ไขล่าสุด: วันอังคารที่ 30 กันยายน 2014 12:40:52 GMT
[id=1] [ 1.522] ส่งเฟรมข้อมูล
- END_STREAM
[id=1] [ 1.522] stream_id=13 ปิดแล้ว
[id=1] [ 1.522] รับเฟรม GOAWAY
(last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])
[id=1] [ 1.522] ปิดแล้ว
nghttpx
เป็นพร็อกซีย้อนกลับแบบมัลติเธรดสำหรับ HTTP/3, HTTP/2 และ HTTP/1.1 และขับเคลื่อน http://nghttp2.org และรองรับการพุชเซิร์ฟเวอร์ HTTP/2
เราปรับปรุงอินเทอร์เฟซบรรทัดคำสั่ง nghttpx
ใหม่และด้วยเหตุนี้ จึงมีหลายสิ่งที่เข้ากันไม่ได้ตั้งแต่ 1.8.0 หรือเก่ากว่า นี่เป็นสิ่งจำเป็นในการขยายขีดความสามารถ และรักษาความปลอดภัยของการปรับปรุงคุณสมบัติเพิ่มเติมในรุ่นอนาคต โปรดอ่านการย้ายจาก nghttpx เวอร์ชัน 1.8.0 หรือเวอร์ชันก่อนหน้า เพื่อทราบวิธีโยกย้ายจากเวอร์ชันก่อนหน้า
nghttpx
ใช้คุณลักษณะที่มุ่งเน้นประสิทธิภาพที่สำคัญใน TLS เช่น รหัสเซสชัน ตั๋วเซสชัน (ที่มีการหมุนเวียนคีย์อัตโนมัติ) การเย็บ OCSP การปรับขนาดบันทึกแบบไดนามิก ALPN การส่งต่อความลับ และ HTTP/2 nghttpx
ยังมีฟังก์ชันในการแชร์แคชเซสชันและคีย์ตั๋วระหว่างอินสแตนซ์ nghttpx
หลายรายการผ่าน memcached
nghttpx
มี 2 โหมดการทำงาน:
ตัวเลือกโหมด | ส่วนหน้า | แบ็กเอนด์ | บันทึก |
---|---|---|---|
โหมดเริ่มต้น | HTTP/3, HTTP/2, HTTP/1.1 | HTTP/1.1, HTTP/2 | พร็อกซีย้อนกลับ |
--http2-proxy | HTTP/3, HTTP/2, HTTP/1.1 | HTTP/1.1, HTTP/2 | ส่งต่อพร็อกซี |
โหมดที่น่าสนใจในขณะนี้คือโหมดเริ่มต้น มันทำงานเหมือนกับพร็อกซีย้อนกลับและรับฟัง HTTP/3, HTTP/2 และ HTTP/1.1 และสามารถใช้เป็นตัวยุติ SSL/TLS สำหรับเว็บเซิร์ฟเวอร์ที่มีอยู่ได้
ในทุกโหมด การเชื่อมต่อส่วนหน้าจะถูกเข้ารหัสโดย SSL/TLS ตามค่าเริ่มต้น หากต้องการปิดใช้งานการเข้ารหัส ให้ใช้คีย์เวิร์ด no-tls
ในตัวเลือก --frontend
หากปิดใช้งานการเข้ารหัส การเชื่อมต่อ HTTP/1.1 ขาเข้าสามารถอัปเกรดเป็น HTTP/2 ผ่านการอัปเกรด HTTP การเชื่อมต่อแบ็กเอนด์แบบฮาร์ดอื่นๆ จะไม่ถูกเข้ารหัสตามค่าเริ่มต้น หากต้องการเข้ารหัสการเชื่อมต่อแบ็กเอนด์ ให้ใช้คีย์เวิร์ด tls
ในตัวเลือก --backend
nghttpx
รองรับไฟล์กำหนดค่า ดูตัวเลือก --conf
และไฟล์การกำหนดค่าตัวอย่าง nghttpx.conf.sample
ในโหมดเริ่มต้น nghttpx
ทำงานเป็นพร็อกซีย้อนกลับไปยังเซิร์ฟเวอร์แบ็กเอนด์:
ไคลเอ็นต์ <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1, HTTP/2) --> เว็บเซิร์ฟเวอร์
[พร็อกซีย้อนกลับ]
ด้วยตัวเลือก --http2-proxy
มันทำงานเป็นพร็อกซีการส่งต่อ และเรียกว่าพร็อกซี HTTP/2 ที่ปลอดภัย:
ไคลเอ็นต์ <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> พร็อกซี
[พร็อกซีที่ปลอดภัย] (เช่น Squid, ATS)
Client
ในตัวอย่างข้างต้นจำเป็นต้องได้รับการกำหนดค่าให้ใช้ nghttpx
เป็นพร็อกซีที่ปลอดภัย
ในขณะที่เขียนบทความนี้ ทั้ง Chrome และ Firefox รองรับพร็อกซี HTTP/2 ที่ปลอดภัย วิธีหนึ่งในการกำหนดค่า Chrome ให้ใช้พร็อกซีที่ปลอดภัยคือการสร้างสคริปต์ proxy.pac ดังนี้:
function FindProxyForURL ( url , host ) {
return "HTTPS SERVERADDR:PORT" ;
}
SERVERADDR
และ PORT
คือชื่อโฮสต์/ที่อยู่และพอร์ตของเครื่อง nghttpx ที่กำลังทำงานอยู่ โปรดทราบว่า Chrome ต้องมีใบรับรองที่ถูกต้องสำหรับพร็อกซีที่ปลอดภัย
จากนั้นเรียกใช้ Chrome ด้วยอาร์กิวเมนต์ต่อไปนี้:
$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
การเชื่อมต่อ HTTP/2 แบ็กเอนด์สามารถส่งสัญญาณผ่านพร็อกซี HTTP พร็อกซีถูกระบุโดยใช้ --backend-http-proxy-uri
รูปต่อไปนี้แสดงให้เห็นว่า nghttpx สื่อสารกับพร็อกซี HTTP/2 ภายนอกผ่านพร็อกซี HTTP อย่างไร:
ไคลเอ็นต์ <-- (HTTP/3, HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/2) --
--===================---> พร็อกซี HTTP/2
(ช่องสัญญาณพร็อกซี HTTP) (เช่น nghttpx -s)
โปรแกรม h2load
เป็นเครื่องมือวัดประสิทธิภาพสำหรับ HTTP/3, HTTP/2 และ HTTP/1.1 UI ของ h2load
ได้รับแรงบันดาลใจอย่างมากจาก weighttp
(https://github.com/lighttpd/weighttp) การใช้งานทั่วไปมีดังนี้:
$ h2load -n100000 -c100 -m100 https://localhost:8443/
กำลังเริ่มต้นเกณฑ์มาตรฐาน...
เธรดวางไข่ #0: 100 ไคลเอนต์พร้อมกัน, คำขอทั้งหมด 100,000 รายการ
โปรโตคอล: TLSv1.2
รหัส: ECDHE-RSA-AES128-GCM-SHA256
คีย์ชั่วคราวของเซิร์ฟเวอร์: ECDH P-256 256 บิต
ความคืบหน้า: เสร็จไปแล้ว 10%
ความคืบหน้า: ดำเนินการไปแล้ว 20%
ความคืบหน้า: เสร็จไปแล้ว 30%
ความคืบหน้า: เสร็จไปแล้ว 40%
ความคืบหน้า: เสร็จไปแล้ว 50%
ความคืบหน้า: ดำเนินการไปแล้ว 60%
ความคืบหน้า: เสร็จไปแล้ว 70%
ความคืบหน้า: ดำเนินการไปแล้ว 80%
ความคืบหน้า: ดำเนินการไปแล้ว 90%
ความคืบหน้า: เสร็จสิ้น 100%
เสร็จสิ้นใน 771.26ms, 129658 req/s, 4.71MB/s
คำขอ: ทั้งหมด 100,000 รายการ, เริ่มต้น 100,000 รายการ, เสร็จสิ้น 100,000 รายการ, สำเร็จ 100,000 รายการ, ล้มเหลว 0 รายการ, ผิดพลาด 0 รายการ
รหัสสถานะ: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
การรับส่งข้อมูล: รวม 3812300 ไบต์, ส่วนหัว 1009900 ไบต์, ข้อมูล 1000000 ไบต์
ขั้นต่ำสูงสุดเฉลี่ย sd +/- sd
เวลาสำหรับการร้องขอ: 25.12ms 124.55ms 51.07ms 15.36ms 84.87%
เวลาในการเชื่อมต่อ: 208.94ms 254.67ms 241.38ms 7.95ms 63.00%
เวลาในการไบต์ที่ 1: 209.11ms 254.80ms 241.51ms 7.94ms 63.00%
ตัวอย่างข้างต้นออกคำขอทั้งหมด 100,000 รายการ โดยใช้ไคลเอ็นต์ที่ทำงานพร้อมกัน 100 รายการ (หรืออีกนัยหนึ่งคือ 100 เซสชัน HTTP/2) และสตรีมสูงสุด 100 รายการต่อไคลเอ็นต์ ด้วยตัวเลือก -t
นั้น h2load
จะใช้เธรดดั้งเดิมหลายรายการเพื่อหลีกเลี่ยงการทำให้คอร์เดียวในฝั่งไคลเอ็นต์อิ่มตัว
คำเตือน
อย่าใช้เครื่องมือนี้กับเซิร์ฟเวอร์ที่เปิดเผยต่อสาธารณะ นั่นถือเป็นการโจมตีดอส กรุณาใช้กับเซิร์ฟเวอร์ส่วนตัวของคุณเท่านั้น
หากเปิดใช้งาน HTTP/3 รุ่นทดลอง h2load จะสามารถส่งคำขอไปยังเซิร์ฟเวอร์ HTTP/3 ได้ เมื่อต้องการทำเช่นนี้ ให้ระบุตัวเลือก h3
ถึง --alpn-list
ดังนี้:
$ h2load --alpn-list h3 https://127.0.0.1:4433
สำหรับ nghttp2 v1.58 หรือเก่ากว่า ให้ใช้ --npn-list
แทน --alpn-list
ไดเร็กทอรี src
มีเครื่องมือ HPACK โปรแกรม deflatehd
เป็นเครื่องมือบีบอัดส่วนหัวของบรรทัดคำสั่ง โปรแกรม inflatehd
เป็นเครื่องมือคลายการบีบอัดส่วนหัวของบรรทัดคำสั่ง เครื่องมือทั้งสองอ่านอินพุตจาก stdin และเขียนเอาต์พุตไปยัง stdout ข้อผิดพลาดถูกเขียนถึง stderr พวกเขาใช้ JSON เป็นอินพุตและเอาต์พุต เรา (ส่วนใหญ่) ใช้รูปแบบข้อมูล JSON เดียวกับที่อธิบายไว้ที่ https://github.com/http2jp/hpack-test-case
โปรแกรม deflatehd
อ่านข้อมูล JSON หรือฟิลด์ส่วนหัว HTTP/1 แบบจาก STDIN และเอาต์พุตบล็อกส่วนหัวบีบอัดใน JSON
สำหรับอินพุต JSON วัตถุ ROOT JSON จะต้องมี cases
ค่าของมันจะต้องรวมลำดับของชุดส่วนหัวอินพุต พวกเขาแบ่งปันบริบทการบีบอัดเดียวกันและดำเนินการตามลำดับที่ปรากฏ แต่ละรายการในลำดับคือวัตถุ JSON และจะต้องมีคีย์ส่วน headers
ค่าของมันคืออาร์เรย์ของวัตถุ JSON ซึ่งรวมถึงคู่ชื่อ/ค่าหนึ่งคู่
ตัวอย่าง:
{
"cases" :
[
{
"headers" : [
{ ":method" : " GET " },
{ ":path" : " / " }
]
},
{
"headers" : [
{ ":method" : " POST " },
{ ":path" : " / " }
]
}
]
}
ด้วยตัวเลือก -t
โปรแกรมสามารถยอมรับบล็อกส่วนหัวของ HTTP/1 ที่คุ้นเคยมากขึ้น ชุดส่วนหัวแต่ละชุดจะถูกคั่นด้วยเส้นเปล่า:
ตัวอย่าง:
: วิธี: รับ
: โครงการ: https
:เส้นทาง: /
: วิธี: โพสต์
ผู้ใช้ตัวแทน: NGHTTP2
เอาต์พุตอยู่ในวัตถุ JSON ควรรวมถึงคีย์ cases
และค่าของมันคืออาร์เรย์ของวัตถุ JSON ซึ่งมีคีย์อย่างน้อยต่อไปนี้:
output_length
/ input_length
* 100ตัวอย่าง:
{
"cases" :
[
{
"seq" : 0 ,
"input_length" : 66 ,
"output_length" : 20 ,
"percentage_of_original_size" : 30.303030303030305 ,
"wire" : " 01881f3468e5891afcbf83868a3d856659c62e3f " ,
"headers" : [
{
":authority" : " example.org "
},
{
":method" : " GET "
},
{
":path" : " / "
},
{
":scheme" : " https "
},
{
"user-agent" : " nghttp2 "
}
],
"header_table_size" : 4096
}
,
{
"seq" : 1 ,
"input_length" : 74 ,
"output_length" : 10 ,
"percentage_of_original_size" : 13.513513513513514 ,
"wire" : " 88448504252dd5918485 " ,
"headers" : [
{
":authority" : " example.org "
},
{
":method" : " POST "
},
{
":path" : " /account "
},
{
":scheme" : " https "
},
{
"user-agent" : " nghttp2 "
}
],
"header_table_size" : 4096
}
]
}
เอาต์พุตสามารถใช้เป็นอินพุตสำหรับ inflatehd
และ deflatehd
ด้วยตัวเลือก -d
คีย์ header_table
พิเศษจะถูกเพิ่มและค่าที่เกี่ยวข้องรวมถึงสถานะของตารางส่วนหัวแบบไดนามิกหลังจากที่ชุดส่วนหัวที่สอดคล้องกันถูกประมวลผล ค่ารวมอย่างน้อยคีย์ต่อไปนี้:
referenced
เป็น true
มันจะอยู่ในชุดอ้างอิง size
รวมถึงค่าใช้จ่าย (32 ไบต์) index
สอดคล้องกับดัชนีของตารางส่วนหัว name
คือชื่อฟิลด์ส่วนหัวและ value
คือค่าฟิลด์ส่วนหัวmax_deflate_size
max_size
ในกรณีนี้ตัวเข้ารหัสจะใช้บัฟเฟอร์ max_deflate_size
แรกเท่านั้น เนื่องจากขนาดตารางส่วนหัวยังคงเป็น max_size
ตัวเข้ารหัสจึงต้องติดตามรายการนอก max_deflate_size
แต่ภายใน max_size
และตรวจสอบให้แน่ใจว่าไม่ได้อ้างอิงอีกต่อไปตัวอย่าง:
{
"cases" :
[
{
"seq" : 0 ,
"input_length" : 66 ,
"output_length" : 20 ,
"percentage_of_original_size" : 30.303030303030305 ,
"wire" : " 01881f3468e5891afcbf83868a3d856659c62e3f " ,
"headers" : [
{
":authority" : " example.org "
},
{
":method" : " GET "
},
{
":path" : " / "
},
{
":scheme" : " https "
},
{
"user-agent" : " nghttp2 "
}
],
"header_table_size" : 4096 ,
"header_table" : {
"entries" : [
{
"index" : 1 ,
"name" : " user-agent " ,
"value" : " nghttp2 " ,
"referenced" : true ,
"size" : 49
},
{
"index" : 2 ,
"name" : " :scheme " ,
"value" : " https " ,
"referenced" : true ,
"size" : 44
},
{
"index" : 3 ,
"name" : " :path " ,
"value" : " / " ,
"referenced" : true ,
"size" : 38
},
{
"index" : 4 ,
"name" : " :method " ,
"value" : " GET " ,
"referenced" : true ,
"size" : 42
},
{
"index" : 5 ,
"name" : " :authority " ,
"value" : " example.org " ,
"referenced" : true ,
"size" : 53
}
],
"size" : 226 ,
"max_size" : 4096 ,
"deflate_size" : 226 ,
"max_deflate_size" : 4096
}
}
,
{
"seq" : 1 ,
"input_length" : 74 ,
"output_length" : 10 ,
"percentage_of_original_size" : 13.513513513513514 ,
"wire" : " 88448504252dd5918485 " ,
"headers" : [
{
":authority" : " example.org "
},
{
":method" : " POST "
},
{
":path" : " /account "
},
{
":scheme" : " https "
},
{
"user-agent" : " nghttp2 "
}
],
"header_table_size" : 4096 ,
"header_table" : {
"entries" : [
{
"index" : 1 ,
"name" : " :method " ,
"value" : " POST " ,
"referenced" : true ,
"size" : 43
},
{
"index" : 2 ,
"name" : " user-agent " ,
"value" : " nghttp2 " ,
"referenced" : true ,
"size" : 49
},
{
"index" : 3 ,
"name" : " :scheme " ,
"value" : " https " ,
"referenced" : true ,
"size" : 44
},
{
"index" : 4 ,
"name" : " :path " ,
"value" : " / " ,
"referenced" : false ,
"size" : 38
},
{
"index" : 5 ,
"name" : " :method " ,
"value" : " GET " ,
"referenced" : false ,
"size" : 42
},
{
"index" : 6 ,
"name" : " :authority " ,
"value" : " example.org " ,
"referenced" : true ,
"size" : 53
}