Zhuanzhuan 品質検査デスクトップ アプリケーションのアーキテクチャの進化

品質検査は、Zhuanzhuan の契約履行システムの重要な部分であり、携帯電話、タブレット、ノートブック、ヘッドフォン、時計、その他のカテゴリーの商品のソフトウェアおよびハードウェアの機能、外観および品質に関する包括的な検査を実施することで、買い手と売り手の品質を保証します。 . 中古取引の透明性と信頼性を高め、グリーン消費を促進します。

品質検査プロセスでは、標準化された生産ラインと自動化機器、品質検査APP、デスクトップアプリケーションなどを組み合わせて、最終的に包括的で信頼できる「品質検査レポート」が出力され、ユーザーに提示されます。中でもデスクトップ アプリケーションは決定的な役割を果たしており、この記事ではデスクトップ アプリケーション アーキテクチャの進化と実装に焦点を当てます。

背景1枚

品質検査用のデスクトップ アプリケーションは、初期段階では主に Qt で構築され、C/C++ が基礎的なサポートを提供していました。 C/C++ 開発者は、ビュー層、アプリケーション層、およびこれらのデスクトップ アプリケーションの基礎となる機能サポートのすべての開発反復に責任を負います。第 2 に、ビジネスの継続的な発展に伴い、一部のデスクトップ アプリケーションではスケーラビリティの低さと反復の難しさの問題が徐々に明らかになりました。

Zhuanzhuan 品質検査技術チームには、C/C++ 開発の学生に加えて、成熟したフロントエンドと Java バックエンドもいます。要約すると、ビュー レイヤー、フロントエンド テクノロジー エコシステム、およびビュー層の開発者にとっては、開発において大きな利点があり、アプリケーション層に関しては、Java テクノロジ エコシステムの利点は自明であり、同時に、Java バックエンドの学生は比較的包括的で深い理解が得られます。つまり、Java の学生はアプリケーションが非常に得意であり、レイヤー アーキテクチャの設計と実装の点で非常に適しています。

要約すると、チームの実際の状況に基づいて、著者のチームはデスクトップ アプリケーション用の新しい技術アーキテクチャである EJC (Electron、Java、C/C++) を提案しました。このアーキテクチャの主な利点は次のとおりです。

  • C/C++ 開発の学生が基礎となる機能の研究にさらに集中し、より大きな価値を発揮できるようにします。
  • Electron は本質的にフロントエンド テクノロジ スタックです。Java の学生はビジネス全体をよりよく理解し、アプリケーション層の設計経験に優れています。また、フロントエンドと Java のリソースは柔軟に展開しやすくなっています。
  • Electron と Java 自体はクロスエンドであるため、その後の品質検査デスクトップ アプリケーション (Windows および Mac) のすべてのエンドの統合に優れた利点があります。

2 EJC アーキテクチャ

簡単に言えば、EJC の技術アーキテクチャは、Electron (ビュー層/ユーザー層)、Java (アプリケーション層)、C/C++ (基本機能層) です。

2.1 電子

Electron は、Chromium と Node.js をベースにしたフレームワークで、Windows、macOS、Linux 用のクロスプラットフォーム デスクトップ アプリケーションのセットです。

  • これは本質的に、アプリケーションが最新の Web 標準を備えているように、Chromium カーネルが組み込まれたフロントエンド テクノロジ スタックであり、開発者はアプリケーションのロジックとインターフェイスの設計に集中でき、ブラウザの互換性操作に取り組む必要がなくなりました。
  • フル パッケージ アップデートとホット アップデートにより、ハイブリッド モバイル アプリケーション (ハイブリッド APP) の楽しみと同様に、プログラムが最新の状態に保たれます。
  • 安全なクロスプラットフォームのオペレーティング環境により、プログラムのクラッシュやシステム エラーの可能性が効果的に低減され、より信頼性が高く安定したアプリケーションが実現されます。
  • C/C++ 機能によってサポートされる豊富な API により、ソフトウェアとハ​​ードウェアの組み合わせがよりスムーズになり、機能がさらに拡張されます。

2.2 Java

Java アプリケーション層には主に次のものが含まれます。

  • 通信モジュール: HTTP、WebSocket、およびその他のプロトコルに基づいた通信機能を提供します。
  • 基礎となる対話型モジュール: ローカル コード (動的ライブラリ) を呼び出すための Java テクノロジ (JNI/JNA) をカプセル化します。
  • データ ストレージ: 軽量データベース SQLite を使用してデータを永続化し、データの高可用性とフォールト トレランスのための基本機能を提供します。
  • イベント リスニング: Spring に基づくイベントおよびリスニング メカニズムは、疎結合、高いスケーラビリティ、およびテスト容易性の利点を持つイベント駆動型プログラミング モデルを実装します。
  • ビジネスモジュール:必要なビジネスロジック処理。
  • 監視モジュール: クライアントのリアルタイムの動作パラメータ、ハードウェアの異常、その他のデータを記録し、定期的にクラウドに報告します。
  • 構成管理: クラウドから定期的に最新の構成を取得し、ローカル構成を上書きします。
  • スケジューリング戦略: デバイスの履歴ステータスに基づいて、ハードウェア (USB 通信ポート、USB ハブ、シェルフ上のその他の機器など) が誤動作するかどうかを予測します。障害が特定された場合は、他のデバイスを優先して障害情報を報告できます。 。

2.3 C/C++

基本機能層、コア SDK の実装。 Windows、IOS、Android、カメラ、ロボット アームなどとの低レベルの共通機能を提供します。

上記の説明に基づいて、転送品質検査中に著者が提示した EJC 技術アーキテクチャは次のとおりです。

EJC アーキテクチャ図

以下では、フロントエンド通信モジュールと Java アプリケーション層の基礎となる通信モジュールの紹介に焦点を当てます。

2.4 フロントエンド通信モジュール

Javaアプリケーション層は、HTTPプロトコルおよびWebSocketプロトコルの通信方式に対応しています。次に、フロントエンドと通信するためのいくつかのオプションと、EJC アーキテクチャでの選択と考慮事項を紹介します。

2.4.1 HTTPショートポーリング

クライアントは、最新のデータを取得するためにサーバーに定期的にリクエストを送信します。これにより、サーバーとネットワーク リソースが浪費されます。リアルタイム要件が低いシナリオに適しています: このメカニズムは、Java クライアントがクラウドから構成を取得するときに使用されます。

2.4.2 HTTP ロングポーリング

HTTP ショート ポーリングと比較して、HTTP ロング ポーリングは、クライアントがサーバーにリクエストを頻繁に送信することを回避し、ネットワークとサーバーのリソースのコストを節約しながら、よりタイムリーで信頼性の高いデータ プッシュを実現します。

2.4.3 SSE(サーバー送信イベント)

これは本質的に HTTP の長い接続であり、サーバーはデータ パケットをクライアントに送信するのではなく、テキスト/ストリーム形式のストリームを送信するため、クライアントは接続を閉じず、常にサーバーが新しいデータを送信するのを待ちます。ストリーム。 。サーバーがイベントをクライアントに一方向にプッシュするだけでよいシナリオに適しています。


実際のアプリケーション シナリオでは、サーバーはフロント エンドに情報を 1 回プッシュするだけで済みます (たとえば、フロント エンドは Java サーバーを呼び出してシステム ハードウェア構成情報を取得します)。フロント エンドとバック エンド間の通信方法として SSE を選択します。これには次のような利点があります。

  • http ショートポーリングよりもパフォーマンスが優れています。
  • http ロングポーリングよりも信頼性が高くなります。
  • WebSocket よりも軽量です。
  • 追加の構成や展開を必要とせずに、既存のインフラストラクチャとテクノロジーで使用できます。

2.4.4 Webソケット

WebSocket は、リアルタイム通信を可能にする TCP ベースの双方向通信プロトコルです。リアルタイム要件が高く、二重通信が必要なシステムに適しています。プライバシークリアリングツールなどの実際のアプリケーションでは、電話機を挿入してからプライバシークリアリングが完了するまでわずか 3 ~ 5 秒かかります。品質検査官は、電話機の状態の変化をリアルタイムで確認する必要があります。現時点では、Websocket を選択しています。データステータスをリアルタイムにプッシュし、フロントエンドに移動して表示します。

2.5 下部通信モジュール

Java が C/C++ を呼び出すには、JNI (Java Native Interface) と JNA (Java Native Access) の 2 つの方法があり、どちらも Java でローカルの基礎となる SDK を呼び出すために使用されるテクノロジです。

以下は、Java が基礎となる SDK を呼び出す方法を示す簡単なコード例 (IOS デバイス名の取得) です。スペースを節約するために、一部のキー コードのみが表示されます。

2.5.1 JNIの導入と使用

Java 言語によって提供される標準インターフェイス。Java アプリケーションが C/C++ 言語を呼び出したり、C/C++ 言語から呼び出されたりできるようにする一連の関数とデータ型を提供します。 JNI を使用すると、ネイティブ メソッドを作成することで C/C++ 言語との対話が可能になります。

  • ネイティブ メソッドを宣言するには、native キーワードを使用します。
public class JniDemo {
    
    
    /**
     * 获取IOS设备的名称
     * @param udid 设备UDID
     * @return 设备名称
     */
    public native String getDeviceNameByUDID(String udid);
}
  • javah コマンドを使用して、コード内のネイティブ メソッドに対応する C 言語ヘッダー ファイルを生成します。
> javah JniDemo
// JDK10+已经移除了javah命令工具,使用以下命令
> javac JniDemo.java -h outputDir
  • 上記のコマンドを実行すると、JniDemo.h という名前の C/C++ ヘッダー ファイルが生成されます。
#include <jni.h>
/* Header for class JniDemo */

#ifndef _Included_JniDemo
#define _Included_JniDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * 包含了 getDeviceNameByUDID 方法的声明
 * Class:     JniDemo
 * Method:    getDeviceNameByUDID
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_JniDemo_getDeviceNameByUDID
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif
  • C/C++ は、Java_JniDemo_getDeviceNameByUDID メソッドを実装するためのヘッダー ファイルを実装し、それを動的ライブラリにコンパイルします。
#include "jnidemo.h"

JNIEXPORT jstring JNICALL Java_JniDemo_getDeviceNameByUDID(JNIEnv *env, jobject, jstring udid)
{
    
    
    string udid_cpp = jstringTostring(env, udid);
    LHW_INFO("udid_cpp = " << udid_cpp);
    IOS_Device_Interface idi;
    string device_name = idi.get_device_name_by_udid(udid_cpp);
    LHW_INFO("device_name = " << device_name);
    return stringTojstring(env, device_name.c_str());
}
  • Java が使用するもの
public class JniDemo {
    
    
    /**
     * 获取IOS设备的名称
     * @param udid 设备UDID
     * @return 设备名称
     */
    public native String getDeviceNameByUDID(String udid);

    public static void main(String[] args) {
    
    
        System.loadLibrary("jniDemo");
        JniDemo obj = new JniDemo();
        String result = obj.getDeviceNameByUDID("00008110-001518392EE3801E");
        System.out.println("Result is " + result);
        // Result is iphone 13 pro
    }
}

2.5.2 JNAの導入と使用

JNA は、JNI に基づいて実装されたプログラミング フレームワークで、Java 型から C 型への自動変換を実装します。 Java 開発者は、ターゲットのネイティブ ライブラリの機能と構造を Java インターフェイスで記述するだけで済み、ネイティブ/JNI コードを記述する必要がなくなり、Java ダイナミック ライブラリの開発の難易度が大幅に軽減されます。

  • C/C++ コードを作成し、ヘッダー ファイルを宣言します (JNA によって呼び出される extern "C" キーワードが必要です)。
#pragma once
#include "pch.h"

#ifndef JNADemoAPI
#define JNADemoAPI __declspec(dllexport)
#endif // !_Included_JnaDemo

#ifdef __cplusplus
extern "C" {
    
    
#endif // __cplusplus

    JNADemoAPI const char* getDeviceNameByUDID(const char *udid);


#ifdef __cplusplus
}
#endif // __cplusplus

  • ヘッダー ファイルを実装し、動的ライブラリにコンパイルします。
#include "pch.h"
#include "JnaDemo.h"
#include "IOSDevice/ios_device_pimpl.h"

string IOS_Device_Interface::getDeviceNameByUDID(string udid) {
    
    
    return ios_device->get_deviceName_by_udid(udid);
}
  • Javaで使用されます。

まず、JNA ライブラリをプロジェクトに導入します。

<dependency>
  <groupId>com.sun.jna</groupId>
  <artifactId>jna</artifactId>
  <version>5.12.1</version>
</dependency>

ダイナミック ライブラリに対応する Java インターフェイス クラスを宣言します。

/**
 *  定义动态库接口
 */
public interface JnaDemo extends Library {
    
    
    /**
     * 与 C/C++ 中的函数名对应
     * @param 设备UDID
     * @return 设备名称
     */
    String getDeviceNameByUDID(String udid);
}

ダイナミック ライブラリをロードし、メソッドを呼び出します。


/**
 * 通过 JNA 调用 C/C++ 函数
 *
 */
public class JnaDemoTest {
    
    

    public static void main(String[] args) {
    
    
        // 加载名为 jnaDemo 动态库
        JnaDemo jnaDemo = Native.load("JnaDemo", JnaDemo.class);
        // 调用方法并获取结果
        String result = jnaDemo.getDeviceNameByUDID("00008110-001518392EE3801E");
        System.out.println("Result is " + result);
        // Result is iphone 13 pro
    }
}

2.5.3 選択と考慮事項

上記のサンプル コードを通じて、2 つのソリューションの長所と短所を比較し、パフォーマンス テストを実施しました。

JNI JNA
アドバンテージ コンパイル後、ネイティブ メソッドを C または C++ で実装できます。ローカル メソッドの呼び出しは、JNA よりも効率的です。 システムで一般的に使用される動的ライブラリをカプセル化し、直接使用できます。 JNIに比べて開発効率が比較的高く、Javaでネイティブメソッドを記述する必要がありません。
欠点がある 開発効率は比較的低く、Java でネイティブ メソッドを記述し、C/C++ ヘッダー ファイルをコンパイルして生成する必要があり、生成されたヘッダー ファイルに従って C/C++ をコーディングおよび実装する必要があります。 C++ コンパイルによって生成された動的ライブラリはサポートされていないため、C++ インターフェイス上で C 言語でカプセル化する必要があります。

開発者の観点から見ると、JNA は Java 開発者にとってよりフレンドリーですが、JNI は C/C++ 開発者にとってよりフレンドリーです。

同時に、JNI と JNA を使用して、IOS デバイス名の読み取りパフォーマンス テストをそれぞれ 100 ~ 500 回実施し、時間のかかる比較結果を取得しました。 8 コア 16G マシンで実行すると、次の結果が得られます。

数量を計算する(100倍) JNI JNA
1 1197ミリ秒 26957ミリ秒
2 2196ミリ秒 52800ミリ秒
3 2759ミリ秒 79260ミリ秒
4 4573ミリ秒 106377ミリ秒
5 6299ミリ秒 132482ミリ秒

上記の比較と性能テストを通じて、次の選択基準を策定しました。

  • 自社開発の SDK: Gaoyou は、基礎となる通信方法として JNI を使用します。利点は次のとおりです: JNI の方がパフォーマンスが高く、基礎となるデータ対話インターフェイスが Java によって定義されているため、C/C++ 開発者は実装に C または C++ を選択できるため、選択性と柔軟性が高まります。
  • 社外メーカー提供のSDK:メーカー提供のSDKを優先して呼び出します。利点は、C/C++ で動的ライブラリの層を再度カプセル化する必要がないため、開発リソースへの投資が削減されることです。

3 EJC アーキテクチャの実装

EJC アーキテクチャは、Zhuanzhuan 品質検査の複数のアプリケーションで正常に実装されており、以下では主に Windows ノートブック品質検査ツールへの EJC の実装について紹介します。

3.1 プロジェクトの背景

品質検査事業の発展に伴い、ノートパソコンの品質検査量は過去最高に達しました。 C/C++ で開発され、Qt を使用して構築された初期のラップトップ検査ツールは、主に次の点に反映され、ビジネスのニーズを満たすことができなくなりました。

  • 高いメンテナンスコスト: コードの複雑さは高く、メンテナンスには開発者がより多くの時間とエネルギーを投資する必要があります。
  • カバー率が低い:機能が充実していない、使いやすさが悪く、利用カバー率が低い。
  • 移植性が低い: Mac プラットフォームに移植できません。

上記のプロジェクト背景に基づいて、EJC アーキテクチャを使用してノートブック検査ツールを再構築しました。

3.2 アーキテクチャの実装

3.2.1 用語集

  • WMI: Windows Management Instrumentation は、Windows システムの標準情報サービスです。
  • WinAPI: Windows システムによって提供される低レベルのインターフェイス。
  • DLL©: EJC の C、C/C++ クラスメートによって開発された基礎となる SDK。

3.2.2 プロセスの説明

  • データ取得プロセスの開始: Electron の起動後 -> Java サーバーをバックグラウンドで非同期的に起動 -> ノートブックの基本データ項目の注釈の非同期グローバル スキャンを有効化 -> 読み取る必要があるコンピュータ属性の取得 -> スケジューラ分類実行属性取得コマンド - > 取得コマンド実行チェーンの実行 (水平方向にスケーラブルな取得方法) -> データ処理 -> データ エラー修正 -> SSE チャネルを介してページ レンダリングをプッシュします。
  • 品質検査プロセス補助プロセス: 品質検査プロセスに入る -> 品質検査項目の支援を要求 (フィンガープリントが正常かどうかなどの特定の機能) -> Java が最下位層 (Dll、Wmi などのメソッド) を呼び出す -> ; 補助品質検査結果を返す -> このページは、レンダリング品質検査項目のサポート結果を返します。

3.2.3 処理の説明

  • 実行チェーン: コンピューターの特定の属性を複数の方法で取得し、相互に修正する必要があることを考慮して、その独自の実行チェーンをターゲットを絞った方法で構成することで、より優れた読み取り精度とより便利な拡張を実現できます。
  • データ エラー修正: バッテリーの健全性値などの一部の属性はデフォルトで WMI によって読み取られますが、一部のメーカーでは WMI 標準に従って値が書き込まれず、結果が空になります。そのため、DLL© の他の取得メソッドを呼び出す必要があります。補足として。

3.3 プロジェクトのプレゼンテーション

3.3.1 入力モジュール

Java および C/C++ を通じてノートブックの重要な情報を読み取り、ノートブックの基本的な状況を取得します。入力機能により、現場担当者によるシステム標準品目の選択を支援するとともに、品質検査コードと関連付けて倉庫に保管します。これに基づいて、元の情報と標準製品 ID とのマッピング関係が生成され、次回同じモデルに対する作業手順が 1 つ削減され、同じモデルの品質検査における現場オペレータのポータビリティが容易になります。

ノートブックエントリーモジュール

3.3.2 品質検査モジュール

ブランド モデルを通じてシステムに対応する品質検査テンプレートを取得し、自動および補助的な品質検査機能を提供し、最前線の品質検査担当者がノートブックをより迅速かつ正確に検査できるように支援します。
ノートパソコンの品質検査モジュール

4 まとめ

この記事では、転送品質検査の EJC アーキテクチャに関する情報を共有し、実際の経験をいくつか紹介します。同様の問題を解決するための皆さんの助けになれば幸いです。現在、EJC アーキテクチャ システムは品質検査ビジネスにおいて複数のデスクトップ アプリケーションを導入し、安定的に稼働していますが、将来的にはより多くのアプリケーション シナリオをカバーし、ビジネスの大幅な発展に貢献する予定です。

5 参考リンク

  • https://www.electronjs.org
  • http://java-native-access.github.io/jna/5.13.0/javadoc/overview-summary.html#overview_description
  • https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html#wp914
  • https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events

著者について

メインライター: Wen Yunting、RD、Zhuanzhuan パフォーマンス テクノロジー部門。

この記事の参加者は、情熱的で革新的な小規模チームである EJC チームの他のパートナーでもあります。

Zhuanzhuan は、研究開発センターや業界パートナー向けの技術学習および交換プラットフォームであり、業界の最前線での実践経験や最先端の​​技術トピックを定期的に共有しています。
公開アカウント「Zhuanzhuan Technology」(総合)、「Zhuanzhuan FE」(FE に重点)、「Zhuanzhuan QA」(QA に重点)、その他の有用なプラクティスをフォローしてください。コミュニケーションやコミュニケーションを歓迎します。共有~

おすすめ

転載: blog.csdn.net/zhuanzhuantech/article/details/129622733