一部のサービスにより、レンダリングのために数百MのデータをJAVAバックエンドからフロントエンドに送信する必要があり、サーバーからフロントエンドへの送信時間は0.5秒を超えることはできません。
インターネットでウェブサイトを見つけたのですが、あまり効果がないと感じています。自分の最適化の経験もここで共有しています。
目次
1.TOMCAT圧縮メカニズム
Tomcatには、データを圧縮できる圧縮メカニズムが付属しています。圧縮量によってデータが約20%に削減され、帯域幅に良い影響を与える可能性がありますが、速度の点では十分に機能しません。大容量(100M)で圧縮の場合、データ転送速度は大幅に向上しませんが、時間がかかります。データの圧縮と解凍にも、処理に一定の時間がかかります。そのため、計画は却下されました
参照アドレス:https://www.cnblogs.com/DDgougou/p/8675504.html
2、JAVAフィルター圧縮
Javaフィルターの圧縮は基本的にTomcatの圧縮メカニズムと同じであり、使用される圧縮方法もGzipです。テスト後の効果は基本的にTomcatと同じです。
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
public class GZIPResponseWrapper extends HttpServletResponseWrapper {
protected HttpServletResponse origResponse = null;
protected ServletOutputStream stream = null;
protected PrintWriter writer = null;
public GZIPResponseWrapper(HttpServletResponse response) {
super(response);
origResponse = response;
}
public ServletOutputStream createOutputStream() throws IOException {
return (new GZIPResponseStream(origResponse));
}
public void finishResponse() {
try {
if (writer != null) {
writer.close();
} else {
if (stream != null) {
stream.close();
}
}
} catch (IOException e) {}
}
@Override
public void flushBuffer() throws IOException {
stream.flush();
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if (writer != null) {
throw new IllegalStateException("getWriter() has already been called!");
}
if (stream == null)
stream = createOutputStream();
return (stream);
}
@Override
public PrintWriter getWriter() throws IOException {
if (writer != null) {
return (writer);
}
if (stream != null) {
throw new IllegalStateException("getOutputStream() has already been called!");
}
stream = createOutputStream();
writer = new PrintWriter(new OutputStreamWriter(stream, "UTF-8"));
return (writer);
}
@Override
public void setContentLength(int length) {}
}
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
public class GZIPResponseStream extends ServletOutputStream {
protected ByteArrayOutputStream baos = null;
protected GZIPOutputStream gzipstream = null;
protected boolean closed = false;
protected HttpServletResponse response = null;
protected ServletOutputStream output = null;
public GZIPResponseStream(HttpServletResponse response) throws IOException {
super();
closed = false;
this.response = response;
this.output = response.getOutputStream();
baos = new ByteArrayOutputStream();
gzipstream = new GZIPOutputStream(baos);
}
@Override
public void close() throws IOException {
if (closed) {
throw new IOException("This output stream has already been closed");
}
gzipstream.finish();
byte[] bytes = baos.toByteArray();
response.addHeader("Content-Length",
Integer.toString(bytes.length));
response.addHeader("Content-Encoding", "gzip");
output.write(bytes);
output.flush();
output.close();
closed = true;
}
@Override
public void flush() throws IOException {
if (closed) {
throw new IOException("Cannot flush a closed output stream");
}
gzipstream.flush();
}
@Override
public void write(int b) throws IOException {
if (closed) {
throw new IOException("Cannot write to a closed output stream");
}
gzipstream.write((byte)b);
}
public void write(byte b[]) throws IOException {
write(b, 0, b.length);
}
public void write(byte b[], int off, int len) throws IOException {
if (closed) {
throw new IOException("Cannot write to a closed output stream");
}
gzipstream.write(b, off, len);
}
public boolean closed() {
return (this.closed);
}
public void reset() {
//noop
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setWriteListener(WriteListener writeListener) {
}
}
package com.spdb.web.base;
import java.io.*;
import java.util.zip.GZIPOutputStream;
import javax.servlet.*;
import javax.servlet.http.*;
/**
* Description springmvc 压缩返回参数
* @param
* @Author junwei
* @Date 17:49 2020/3/26
**/
public class GZIPFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
if (req instanceof HttpServletRequest) {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String ae = request.getHeader("accept-encoding");
if (ae != null && ae.indexOf("gzip") != -1) {
GZIPResponseWrapper wrappedResponse = new GZIPResponseWrapper(response);
chain.doFilter(req, wrappedResponse);
wrappedResponse.finishResponse();
return;
}
chain.doFilter(req, res);
}
}
@Override
public void init(FilterConfig filterConfig) {
// noop
}
@Override
public void destroy() {
// noop
}
}
最後に、web.xmlファイルにフィルタリングを追加します(com.spdb.web.baseは、独自のプロジェクトのファイルの相対位置です)
<filter>
<filter-name>GZIPFilter</filter-name>
<filter-class>com.spdb.web.base.GZIPFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>GZIPFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
参照ウェブサイト:https://blog.csdn.net/cafebar123/article/details/80037589?depth_1-utm_source = distribute.pc_relevant.none-task&utm_source = distribute.pc_relevant.none-task
3、msgpack圧縮技術
Msgpackは非常に優れた圧縮プラグインであり、独自の圧縮変換アルゴリズムを備えており、ほとんどのプログラミング言語が含まれていますが、一連のテストの結果、JAVAとJSが見つかりました。
圧縮と解凍は同じアルゴリズムを使用しておらず、2つの間のデータ交換は共有できないため、あきらめました。
参照アドレス:https://msgpack.org/
4、ajaxポーリングメカニズム
Ajaxポーリングメカニズム、ここではアイデアとしてテストしています。1つのリクエストが複数のリクエストに分割され、データが実行されていないときにリクエストが続行されます。
利点は、複数のリクエストが分割された場合、データをすぐにレンダリングしてロードできますが、全体的なロード時間が長くなることです。さらに、バックエンドとフロントエンドのajaxロジックコードは比較的完全である必要があり、一連の非同期同期の問題を考慮する必要があります。いくつかのテストが試行されましたが、実用的ではないため、破棄されます。
参照アドレス:https://www.cnblogs.com/YangJieCheng/p/8367586.html
V.戻りデータ形式コレクションオブジェクトタイプ
この時点まで最適化する場合、圧縮は実際にはデータの量を減らすことであるため、データの量がルートから減少する場合は、それをどのように調整するか。コレクションの総量を減らすことは不可能です、
ただし、コレクション内のオブジェクトのキーを最適化することはできます
たとえば、通常のJSON、通常のページ付けコレクションはフロントエンドに返されます。この転送のメモリサイズを決定する文字列のデータ量によると、ここには150文字近くあります
{"total":28、 "rows":[
{"productid": "FI-SW-01"、 "productname": "Koi"、 "unitcost":10.00、 "status": "P"、 "listprice" :36.50、 "attr1": "Large"、 "itemid": "EST-1"}、
キー処理を簡素化することで、残り100文字、データのメモリサイズを30%削減し、データ量の削減により対応する伝送速度も向上します。
{"total":28、 "rows":[{"A": "FI-SW-01"、 "B": "Koi"、 "C":10.00、 "D": "P"、 "E" :36.50、 "F": "Large"、 "G": "EST-1"}、
結論として、通常、キーを単純化するこの方法により、速度が30%〜50%向上する可能性があります。不利な点は、フィールドの識別が明確でないことです。合意がない場合、データが何であるかわかりません。
6、データ形式の配列型を返します
5番目のスキームでは、これに基づいて最適化し、キーを簡略化してから、データ型を配列に変更し、キーを直接削除します。
文字数は約50文字です。当初の150文字に比べて1/3しか残っておらず、対応する伝送速度も60%〜70%向上しています。ただし、不利な点は、キーを単純化するよりも、これがどのデータであるかを読み取ることの方が難しいことです。フロントエンドとバックエンドは、データレンダリングのロジックについて合意する必要があります。
[[28]、[FI-SW-01、Koi、10.00、P、36.50、Large、EST-1]]
最後に、6番目のスキームを使用してレンダリングデータを処理します。結果からの送信時間は大幅に短縮されますが、このプロセスではある程度の難易度も高くなります。