JSONデータ最適化ソリューション

一部のサービスにより、レンダリングのために数百MのデータをJAVAバックエンドからフロントエンドに送信する必要があり、サーバーからフロントエンドへの送信時間は0.5秒を超えることはできません。

インターネットでウェブサイトを見つけたのですが、あまり効果がないと感じています。自分の最適化の経験もここで共有しています。

目次

1.TOMCAT圧縮メカニズム

2、JAVAフィルター圧縮

3、msgpack圧縮技術

4、ajaxポーリングメカニズム

V.戻りデータ形式コレクションオブジェクトタイプ

6、データ形式の配列型を返します


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番目のスキームを使用してレンダリングデータを処理します。結果からの送信時間は大幅に短縮されますが、このプロセスではある程度の難易度も高くなります。

おすすめ

転載: blog.csdn.net/qq_37203082/article/details/106660058