GZIPOutputStream および GZIPInputStream データの圧縮と解凍

ヒント:記事作成後に目次を自動生成することもできますが、生成方法については右のヘルプを参照してください。


序文

最近、パフォーマンス最適化のバッチを引き継ぎました...
そのようなインターフェイスに遭遇しました。最適化できるすべての部分が最適化されています (ビジネス ロジックのバッチ処理、データの前処理、データ キャッシュ、テーブル ルックアップ フィールドの削減、テーブル インデックスの追加、等。)。

但是,这个接口里有个外部调用会去查询3000+数据,得到的数据大小约为1.5M,耗时:2s
外部系统接口执行时间为:0.8s
那么就意味着...数据传输消耗了:1s+

解决方法:
外部系统将出参:压缩
自己系统将得到数据:解压
これによりデータ転送時間を短縮します

その他の側面: パラメータ出力の冗長フィールドを削減します。

1. ついに圧縮への道を歩み始める GZIPOutputStream

json文字列を圧縮して暗号化します(セキュリティを確保するため)

    public static String getCompressionStr(String jsonStr) throws Exception {
    
    
        
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        GZIPOutputStream gos = new GZIPOutputStream(out);

        gos.write(jsonStr.getBytes(StandardCharsets.UTF_8));
        gos.close();

        byte[] encodeBytes = Base64.getEncoder().encode(out.toByteArray());
        return new String(encodeBytes);
   

2. データを受信して​​解凍する GZIPInputStream

受信した文字列を復号化して解凍します。

    public static String getDecompressionStr(String compressionStr) throws Exception {
    
    
        byte[] decodedBytes = Base64.getDecoder().decode(compressionStr);
        
        GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(decodedBytes));
        BufferedReader bf = new BufferedReader(new InputStreamReader(gis, StandardCharsets.UTF_8));

        StringBuilder outStr = new StringBuilder();
        String line;

        while ((line = bf.readLine()) != null) {
    
    
            outStr.append(line);
        }

        return StringEscapeUtils.unescapeJava(outStr.toString());
    }

3. テストデモ

****重要なヒント************
1: 検証するときは、ログを個別に印刷することを忘れないでください。ログは非常に大きいため、ログ データを表示するのが困難になります。
2: アイデアの設定を調整します -> エディタ -> 一般 -> コンソール
コンソール サイクル バッファ サイズを 10240 に上書きします。

public class Demo {
    
    

    public static void main(String[] args) {
    
    
        String jsonStr = getJsonStr();
        System.out.println(jsonStr);
        
        try {
    
    
            String compressionStr = getCompressionStr(jsonStr);
//            System.out.println(compressionStr);

            String decompressionStr = getDecompressionStr(compressionStr);
//            System.out.println(decompressionStr);

            List<User> users = JSONArray.parseArray(decompressionStr, User.class);
            System.out.println(users.get(100));
            System.out.println(users.get(100).getUserId());
            System.out.println(users.get(100).getName());
            System.out.println(users.get(100).getAddress());


        } catch (Exception e) {
    
    
            System.err.println(e.getMessage());
        }
    }
	
	/**
	 * 随便创建10000个对象,userId,name,address
	 **/
    public static String getJsonStr() {
    
    
        List<User> users = new ArrayList<>();
        String address = "让我感到为难的 是挣扎的自由\n" +
                "分别总是在九月 回忆是思念的愁\n" +
                "深秋嫩绿的垂柳 亲吻着我额头\n" +
                "在那座阴雨的小城里 我从未忘记你\n" +
                "成都 带不走的 只有你\n" +
                "和我在成都的街头走一走 喔…\n" +
                "直到所有的灯都熄灭了也不停留";
        for (int i = 0; i < 10000; i++) {
    
    
            users.add(new User((long) (i + 1), "张三" + (i + 1), address));
        }
        return JSONArray.toJSONString(users);
    }

4. 検証結果

ここに画像の説明を挿入します
1: 10,000 オブジェクトのサイズは 3328KB
2: 圧縮サイズは 80KB
3: 解凍後のサイズは 3328KB
4: 解凍後、データはオブジェクトに変換でき (ネストされたオブジェクトがサポートされます)、通常どおり使用できます。

            List<User> users = JSONArray.parseArray(decompressionStr, User.class);

            System.out.println(users.get(100));
            System.out.println(users.get(100).getUserId());
            System.out.println(users.get(100).getName());
            System.out.println(users.get(100).getAddress());
    对应的输出结果为:
    
User(userId=101, name=张三101, address=让我感到为难的 是挣扎的自由
分别总是在九月 回忆是思念的愁
深秋嫩绿的垂柳 亲吻着我额头
在那座阴雨的小城里 我从未忘记你
成都 带不走的 只有你
和我在成都的街头走一走 喔…
直到所有的灯都熄灭了也不停留)

101

张三101

让我感到为难的 是挣扎的自由
分别总是在九月 回忆是思念的愁
深秋嫩绿的垂柳 亲吻着我额头
在那座阴雨的小城里 我从未忘记你
成都 带不走的 只有你
和我在成都的街头走一走 喔…
直到所有的灯都熄灭了也不停留
            

要約する

パフォーマンスの最適化は本当に面倒です。
特にプロダクトマネージャーのサンドボックス設計(機能を強制的に実装するために一度に3,000個のデータを取得するのは無理があります) 最後に最適化の結果についてお話しましょう:生産ラインでは12秒だったインターフェースが最終的に2秒に短縮されました

別の説明:
StringEscapeUtils を除き、この記事では jdk に付属するライブラリのみが使用されます。

ただし、StringEscapeUtils は lang3 で非推奨になりました。これは、共通テキスト
import org.apache.commons.text.StringEscapeUtils;
//import org.apache.commons.lang3.StringEscapeUtils;で置き換えることができます。

    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-text</artifactId>
        <version>1.10.0</version>
    </dependency>

おすすめ

転載: blog.csdn.net/qq_37700773/article/details/130234173