十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Envoy Mobile 实验性 Kotlin 应用:在 Android 模拟器中从零运行 hello_envoy_kt

Envoy Mobile 实验性 Kotlin 应用:在 Android 模拟器中从零运行 hello_envoy_kt Envoy Mobile 实验性 Kotlin 应用在 Android 模拟器中从零运行 hello_envoy_kt【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy本文以 Envoy Mobile本项目mobile/子工程中的实验性 Kotlin 示例应用 mobile/test/kotlin/apps/experimental 为对象完整讲解如何在 Android 模拟器中构建、安装并运行它包括模拟器镜像准备、Bazel 构建 APK、adb 安装与启动以及该应用内置的 Engine 配置和三类响应过滤器DemoFilter / BufferDemoFilter / AsyncDemoFilter的实现原理。读完本文你将掌握 Envoy Mobile 在 Android 端从“脚本启动”到“源码级理解”的完整闭环。一、这份 README 在讲什么仓库中 mobile/test/kotlin/apps/experimental/README.md 是一份极简的“如何运行”指南全文核心只有两条命令且要求从mobile根目录执行$ test/kotlin/apps/experimental/start_emulator.sh # 等待模拟器完全启动 $ test/kotlin/apps/experimental/start_app.sh这两条命令分别负责两件事start_emulator.sh自动下载 Android 30API 30模拟器系统镜像、创建名为test_android_emulator的 AVDPixel 4并启动模拟器start_app.sh用 Bazel 构建hello_envoy_ktAPK通过 adb 安装到模拟器并拉起应用主界面。README 虽短但它指向的示例应用却是 Envoy Mobile Kotlin API 的实验场应用内置了异步 Engine 初始化、DNS 缓存、Socket Tagging、原生 buffer 过滤器、String Accessor、事件追踪以及三种 Kotlin 响应过滤器。下文将以这两条脚本为主线逐层拆解每一步做了什么并结合源码说明应用内部机制。二、运行前置条件两个脚本开头都做了同一个硬性校验见 start_emulator.sh 与 start_app.shif [[ -z ${ANDROID_HOME} ]]; then echo ANDROID_HOME environment variable must be set. exit 1 fi因此运行前必须确保环境变量ANDROID_HOME已指向 Android SDK 根目录否则脚本立即退出并提示错误SDK 内包含cmdline-tools/latest提供sdkmanager与avdmanager、emulator与platform-tools提供adb系统已安装 Bazel用于构建 APK并具备 Envoy Mobile 仓库的 Bazel 工作区--configmobile-android-release这一配置在 mobile/BUILD 与仓库 Bazel 配置中定义面向 Android release 构建。应用本身对 Android 版本的要求见 AndroidManifest.xmluses-sdk android:minSdkVersion24 android:targetSdkVersion27/即最低支持 Android 7.0API 24同时声明了INTERNET与ACCESS_NETWORK_STATE两个网络权限——这正是该应用要发起真实网络请求https://api.lyft.com/ping所必需的。三、第一步启动模拟器start_emulator.sh 详解脚本完整逻辑如下#!/usr/bin/env bash set -e if [[ -z ${ANDROID_HOME} ]]; then echo ANDROID_HOME environment variable must be set. exit 1 fi echo y | ${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager --install system-images;android-30;google_apis;x86_64 --channel3 echo no | ${ANDROID_HOME}/cmdline-tools/latest/bin/avdmanager create avd -n test_android_emulator -k system-images;android-30;google_apis;x86_64 --device pixel_4 --force ${ANDROID_HOME}/emulator/emulator -avd test_android_emulator它依次完成三个动作安装系统镜像sdkmanager --install system-images;android-30;google_apis;x86_64 --channel3system-images;android-30;google_apis;x86_64表示 Android 30API 30、带 Google APIs、x86_64 架构的模拟器镜像--channel3允许从早期访问渠道获取镜像echo y自动确认许可协议该命令是幂等的镜像已安装时直接跳过。创建 AVDavdmanager create avd -n test_android_emulator -k system-images;... --device pixel_4 --force创建一个名为test_android_emulator的虚拟设备设备型号为pixel_4--force允许覆盖同名已有 AVD因此脚本可重复执行echo no回答“是否创建自定义硬件配置”的交互提问使用默认配置。启动模拟器emulator -avd test_android_emulator该命令会阻塞在前台直到模拟器退出。README 特意提示“等待模拟器完全启动Wait until the emulator is fully booted up”即需要在另一个终端继续执行下一步脚本或等待模拟器桌面完全出现后再执行start_app.sh。说明set -e使脚本在任何一步失败时立即中止保证镜像缺失、AVD 创建失败等情况不会带病继续。四、第二步构建、安装并启动应用start_app.sh 详解脚本完整逻辑如下#!/usr/bin/env bash set -e if [[ -z ${ANDROID_HOME} ]]; then echo ANDROID_HOME environment variable must be set. exit 1 fi bazel build --configmobile-android-release //test/kotlin/apps/experimental:hello_envoy_kt ${ANDROID_HOME}/platform-tools/adb install -r --no-incremental bazel-bin/test/kotlin/apps/experimental/hello_envoy_kt.apk ${ANDROID_HOME}/platform-tools/adb shell am start -n io.envoyproxy.envoymobile.helloenvoyexperimentaltest/.MainActivity三个步骤逐一拆解Bazel 构建 APKbazel build --configmobile-android-release //test/kotlin/apps/experimental:hello_envoy_kt目标//test/kotlin/apps/experimental:hello_envoy_kt在 mobile/test/kotlin/apps/experimental/BUILD 中定义为android_binary输出 APK 位于bazel-bin/test/kotlin/apps/experimental/hello_envoy_kt.apkandroid_binary依赖hello_envoy_kt_libkt_android_library后者编译 MainActivity.kt、DemoFilter.kt、BufferDemoFilter.kt、AsyncDemoFilter.kt 四个 Kotlin 源文件并依赖//:envoy_mobile_androidEnvoy Mobile 的 Android 引擎库与//examples/kotlin/shared:hello_envoy_shared_lib共享的 UI 组件如ResponseRecyclerViewAdapterBUILD 中还定义了detekt静态检查目标hello_envoy_kt_lint说明该应用同时纳入 Kotlin 代码风格门禁。安装 APKadb install -r --no-incremental bazel-bin/test/kotlin/apps/experimental/hello_envoy_kt.apk-r允许覆盖安装reinstall--no-incremental禁用增量安装确保完整安装、避免缓存不一致。启动主界面adb shell am start -n io.envoyproxy.envoymobile.helloenvoyexperimentaltest/.MainActivity直接通过组件名拉起MainActivity包名io.envoyproxy.envoymobile.helloenvoyexperimentaltest同时出现在 AndroidManifest.xml 与 BUILD 的custom_package中二者必须保持一致。五、应用内部做了什么Engine 构建与请求循环启动后MainActivity.kt 的onCreate使用AndroidEngineBuilder完成引擎装配这是理解 Envoy Mobile 配置面的最佳样例engine AndroidEngineBuilder(application) .setLogLevel(LogLevel.DEBUG) .setLogger { _, msg - Log.d(TAG, msg) } .addPlatformFilter(::DemoFilter) .addPlatformFilter(::BufferDemoFilter) .addPlatformFilter(::AsyncDemoFilter) .enableDNSCache(true) // required by DNS cache .addKeyValueStore(reserved.platform_store, SharedPreferencesStore(preferences)) .enableInterfaceBinding(true) .enableSocketTagging(true) .enableProxying(true) .addNativeFilter( envoy.filters.http.buffer, Any.newBuilder() .setTypeUrl(type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer) .setValue(ByteString.empty()) .build() .toByteArray() .toString(Charsets.UTF_8) ) .addStringAccessor(demo-accessor, { PlatformString }) .setOnEngineRunning { Log.d(TAG, Envoy async internal setup completed) } .setEventTracker({ ... }) .build()关键配置点及其源码印证三个平台过滤器DemoFilter、BufferDemoFilter、AsyncDemoFilter以构造函数引用注册到引擎分别演示同步、缓冲、异步三类响应过滤模式详见下文第六节DNS 缓存与键值存储enableDNSCache(true)后必须配套addKeyValueStore(reserved.platform_store, SharedPreferencesStore(preferences))源码注释明确标注 “required by DNS cache”缓存持久化落在 AndroidSharedPreferences上网络能力开关enableInterfaceBinding(true)、enableSocketTagging(true)、enableProxying(true)分别开启接口绑定、Socket 打标配合下面的.addSocketTag(1, 2)与系统代理支持原生过滤器通过addNativeFilter注入 Envoy 的 HTTP buffer 原生过滤器envoy.filters.http.buffer参数以 protobufAny编码传输String AccessoraddStringAccessor(demo-accessor, { PlatformString })注册了一个可被过滤器链读取的字符串访问器事件追踪setEventTracker将引擎内部事件Event emitted: key, value全部打到 Logcat。引擎构建完成后MainActivity在独立后台线程HandlerThread(hello_envoy_kt)上开启每秒一次的请求循环handler.postDelayed( object : Runnable { override fun run() { try { makeRequest() recordStats() } catch (e: IOException) { ... } handler.postDelayed(this, TimeUnit.SECONDS.toMillis(1)) } }, TimeUnit.SECONDS.toMillis(1) )makeRequest()使用RequestHeadersBuilder(RequestMethod.GET, https, api.lyft.com, /ping)构造请求并显式添加.addSocketTag(1, 2)代码注释特别说明该请求会走 h2 流而 Java 示例使用 http/1.1这是为了在 CI 端到端测试中同时覆盖两条协议路径。响应回调中只筛选FILTERED_HEADERSserver、filter-demo、buffer-filter-demo、async-filter-demo、x-envoy-upstream-service-time展示到RecyclerView列表状态码 200 时记为Success否则记录为FailurerecordStats()通过engine.pulseClient().counter(Element(foo), Element(bar), Element(counter))对自定义计数器执行increment()与increment(5)演示 Envoy Mobile 的 Stats 脉冲上报 API。六、三类实验性响应过滤器的实现差异这是该实验应用区别于 baseline 普通示例的核心部分三个过滤器展示了 Kotlin 过滤器的三种复杂程度。6.1 DemoFilter透传式同步过滤DemoFilter.kt 实现ResponseFilter是最简单的“处理即继续”模式在onResponseHeaders中给响应头追加filter-demo: 1数据、尾随头均直接透传override fun onResponseHeaders( headers: ResponseHeaders, endStream: Boolean, streamIntel: StreamIntel ): FilterHeadersStatusResponseHeaders { Log.d(DemoFilter, On headers!) val builder headers.toResponseHeadersBuilder() builder.add(filter-demo, 1) return FilterHeadersStatus.Continue(builder.build()) }Continue表示不阻塞过滤链立即将修改后的头传给下一个过滤器onResponseData/onResponseTrailers同样以Continue透传。6.2 BufferDemoFilter暂停 缓冲 恢复BufferDemoFilter.kt 演示“暂停过滤链、缓冲完整响应、再恢复迭代”的复杂模式类注释原文“pauses processing on the response filter chain, buffers until the response is complete, then resumes filter iteration”onResponseHeaders返回FilterHeadersStatus.StopIteration()暂停过滤链迭代并暂存响应头onResponseData每次收到数据都暂存由于请求了缓冲每次回调携带的是截至当前的累计数据若endStream为真则用FilterDataStatus.ResumeIteration(builder.build(), body)恢复迭代同时追加buffer-filter-demo: 1否则返回StopIterationAndBuffer()继续缓冲onResponseTrailers出现尾随头即代表流结束同样通过ResumeIteration恢复并追加头。该过滤器让开发者理解 Envoy Mobile 过滤链“暂停/缓冲/恢复”的完整生命周期控制。6.3 AsyncDemoFilter异步恢复回调式AsyncDemoFilter.kt 实现AsyncResponseFilter是三者中最复杂的它通过ResponseFilterCallbacks.resumeResponse()在任意异步上下文中恢复过滤链类注释原文“asynchronously triggers filter chain resumption”setResponseFilterCallbacks(callbacks)在回调中保存ResponseFilterCallbacks引用onResponseHeaders若endStream用Timer(AsyncResume, false).schedule(100) { callbacks.resumeResponse() }延迟 100ms 异步恢复onResponseData返回StopIterationAndBuffer()并同样在流结束时异步恢复onResponseTrailers出现即触发异步恢复真正恢复时进入onResumeResponse在其中追加async-filter-demo: 1并返回FilterResumeStatus.ResumeIteration(builder.build(), data, trailers)。该过滤器展示了 Envoy Mobile 对“异步回调中安全重入re-entrancy”的支持——过滤链的恢复可以由过滤器自身掌控时机而不必局限于同步调用栈。七、Bazel 目标结构与校验应用的两个 Bazel 目标定义在 mobile/test/kotlin/apps/experimental/BUILD目标规则说明hello_envoy_ktandroid_binary最终 APKcustom_package io.envoyproxy.envoymobile.helloenvoyexperimentaltest应用//library:proguard_rules混淆规则hello_envoy_kt_libkt_android_library编译四个 Kotlin 源文件与res/layout/activity_main.xml依赖//:envoy_mobile_android、//examples/kotlin/shared:hello_envoy_shared_lib及 recyclerview/protobuf-javalite 等外部 artifacthello_envoy_kt_lintdetektKotlin 静态检查目标基于//:kotlin_lint_config配置APK 安装启动后可通过以下命令验证运行状态# 观察 Envoy 引擎与过滤器日志TAG 分别为 MainActivity、DemoFilter 等 adb logcat -s MainActivity DemoFilter BufferDemoFilter AsyncDemoFilter # 预期可见每秒一次的请求循环日志、filter-demo/buffer-filter-demo/async-filter-demo 响应头、 # 以及 Envoy async internal setup completed 引擎就绪日志八、常见问题与排查ANDROID_HOME environment variable must be set.脚本硬性退出说明 SDK 路径未配置设置环境变量后重跑即可。sdkmanager: command not found$ANDROID_HOME/cmdline-tools/latest目录不存在需先安装 Android 命令行工具。模拟器未就绪导致安装失败adb install在模拟器完全启动前执行会报device offline/no devices。README 已提示“等待模拟器完全启动”可用adb wait-for-device或轮询adb shell getprop sys.boot_completed确认。重复执行脚本avdmanager create ... --force覆盖同名 AVD、sdkmanager --install幂等、adb install -r覆盖安装三处设计都保证脚本可重复执行。构建失败确认 Bazel 版本与仓库mobile/MODULE.bazel声明一致并提前拉取 Envoy 依赖首次构建耗时较长。九、总结从 mobile/test/kotlin/apps/experimental/README.md 的两条命令出发本文完整还原了 Envoy Mobile 实验性 Kotlin 应用在 Android 模拟器上的运行链路start_emulator.sh镜像安装 → AVD 创建 → 模拟器启动→start_app.shBazel 构建 → adb 安装 → am start 拉起。在此基础上进一步剖析了 MainActivity.kt 的 Engine 装配DNS 缓存、Socket Tagging、原生 buffer 过滤器、事件追踪等与三个实验性过滤器同步透传、缓冲恢复、异步回调恢复的源码实现。对于希望在 Android 端深入 Envoy Mobile 过滤链编程与引擎配置的开发者这个实验应用是最贴近生产 API 的入门样例——只需要一个配置好ANDROID_HOME的 Linux 环境、Bazel 与一个 x86_64 模拟器即可复现全部行为。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表