本文重点比较使用虚拟线程的SpringBoot和使用Actix框架的Rust,来实现QR码生成器API。这两种技术都是成熟的,无需进一步介绍。接下来,让我们直接深入测试设置的细节。
所有测试都在装有16GB RAM的MacBook Pro M1上进行。使用的测试工具是Bombardier的定制版本,支持在请求体中包含随机URL。这些测试使用的软件版本如下:
这个QR码生成器应用程序被设计成接收一个JSON请求体,其中包含一个名为"urlToEmbed"的必需参数。该应用程序的主要功能是为指定的URL生成一个QR码,并在HTTP响应中以PNG格式传送QR码。为增加复杂性,该应用程序在HTTPS上运行。
(1) SpringBoot(虚拟线程)
server.port=3000server.ssl.certificate=/Users/mayankc/Work/source/certs/cert.pemserver.ssl.certificate-private-key=/Users/mayankc/Work/source/certs/key.pem
package com.example.qr;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer;import org.springframework.context.annotation.Bean;import java.util.concurrent.Executors;@SpringBootApplicationpublic class QrApplication { public static void main(String[] args) { SpringApplication.run(QrApplication.class, args); } @Bean public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() { return protocolHandler -> { protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor()); }; }}
package com.example.qr;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.http.ResponseEntity;import org.springframework.http.HttpStatus;import org.springframework.http.HttpHeaders;import org.springframework.web.bind.annotation.RestController;import java.util.Optional;import com.example.qr.QrRequest;import com.example.qr.QrGenerator;@RestControllerpublic class QrController { @PostMapping("/qr") public ResponseEntity handleRequest(@RequestBody QrRequest qrRequest) { if(qrRequest.getUrlToEmbed() == null) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } try { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.add(HttpHeaders.CONTENT_TYPE, "image/png"); return new ResponseEntity<byte[]>( QrGenerator.generateQR(qrRequest.getUrlToEmbed(), 512, 512), httpHeaders, HttpStatus.OK); } catch (Exception e) { return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } }}
package com.example.qr;import java.io.ByteArrayOutputStream;import java.io.IOException;import com.google.zxing.BarcodeFormat;import com.google.zxing.WriterException;import com.google.zxing.client.j2se.MatrixToImageConfig;import com.google.zxing.client.j2se.MatrixToImageWriter;import com.google.zxing.common.BitMatrix;import com.google.zxing.qrcode.QRCodeWriter;public class QrGenerator { public static byte[] generateQR(String text, int width, int height) throws WriterException, IOException { QRCodeWriter qrCodeWriter = new QRCodeWriter(); BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height); ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream(); MatrixToImageConfig con = new MatrixToImageConfig() ; MatrixToImageWriter.writeToStream(bitMatrix, "PNG", pngOutputStream, con); byte[] pngData = pngOutputStream.toByteArray(); return pngData; }}
package com.example.qr;public class QrRequest { private String urlToEmbed; public String getUrlToEmbed() { return this.urlToEmbed; } public void setUrlToEmbed(String urlToEmbed) { this.urlToEmbed = urlToEmbed; }}
(2) Rust
[package]name = "actix_qr_generator"version = "0.1.0"edition = "2021"[dependencies]actix-web = { version = "4", features = ["openssl"] } qrcode-generator = "4.1.8"serde = { version = "1.0", features = ["derive"] }serde_json = "1"openssl = { version = "0.10" , features = ["vendored"] }
use actix_web::{web, post, App, HttpServer, HttpResponse, Responder};use qrcode_generator::QrCodeEcc;use serde::Deserialize;use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};#[derive(Deserialize)]struct QrRequest { urlToEmbed: String,}#[post("/qr")]async fn generate_qr(qr_request: web::Json<QrRequest>) -> impl Responder { if qr_request.urlToEmbed.is_empty() { return HttpResponse::BadRequest().into(); } let result: Vec<u8> = qrcode_generator::to_png_to_vec(qr_request.urlToEmbed.clone(), QrCodeEcc::Low, 512) .unwrap(); return HttpResponse::Ok() .content_type("image/png") .body(result);}#[actix_web::main]async fn main() -> std::io::Result<()> { let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); builder .set_private_key_file("/Users/mayankc/Work/source/perfComparisons/certs/key.pem", SslFiletype::PEM) .unwrap(); builder .set_certificate_chain_file("/Users/mayankc/Work/source/perfComparisons/certs/cert.pem") .unwrap(); HttpServer::new(|| App::new().service(generate_qr)) .bind_openssl("127.0.0.1:3000", builder)? .run() .await}// 注意 ================================================// 该应用程序已在发布模式下构建。// =====================================================
为了全面评估性能,这里进行了一系列细致的检查。每个检查包括10万个请求,并在10、50和100个并发连接的范围内评估它们的效率。考虑到QR码生成的资源密集型特性,故意保持了稍低的请求量,与其他场景相比。
结果如下:
根据以下公式,还生成了一个得分卡。对于每个测量,获取获胜的差距。如果获胜的差距是:
得分卡如下:
本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-11260-0.html使用Spring Boot和Rust生成二维码的性能比较(附代码)
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com