首页 文章 精选 留言 我的

精选列表

搜索[驱动分发],共10004篇文章
优秀的个人博客,低调大师

IOS内测分发策略

当苹果应用没有上交appstore审核,出于开始内侧阶段时,我们如何邀请别人测试和使用? plist苹果安装包实现 使用七牛云存储解决ios7.1的app部署问题 推荐两个现在比较流行的app内测辅助网站 蒲公英 和Fir。这样的创业网站都是抓住了企业开发app,在appstore提交之前需要内测的需求,前者通过企业证书发包用户上传的应用,而后者则更多依赖UDID。这样的网站的确为开发者提供了便利,但是作为创业公司想要发展还需要突破一些瓶颈,减少对苹果平台的依赖。作为IOS开发者及发布者,对于发布应用到这些网站其实本身也存在一定的风险,app随时可能因为不可控因素,下载安装出现问题。

优秀的个人博客,低调大师

Android 异步消息分发机制

Android的消息机制–主要是指 Handler 的运行机制 和 MessageQueue 、 looper 的工作过程。 MessageQueueMessageQueue 消息队列,用来存储消息,虽然称为消息队列,但是它的存储结构是采用 单链表的数据结构来存储消息队列的。 包含两个操作插入(enqueueMessage) 和 读取(next) enqueueMessage :往消息链表 中插入一条信息 next:从消息列表中读取一天消息,并将其从消息队列中移除,next方法是一个无限循环的方法,如果消息列表里没有消息,那么会一直阻塞在这里。 LooperLooper 消息循环,用来处理消息。 Looper 会不停的从 MessageQueue 中查看是否有新的消息,如果有新消息就会立即处理Looper.java private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } 在 Looper 的构造方法会创建一个MessageQueue,消息队列,然后将当前线程的对象保存起来。 public static @Nullable Looper myLooper() { return sThreadLocal.get(); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); } 问题 为什么Looper.prepare() 不能被调用两次?答:因为每次调用 Looper.prepare() 的时候的都会判断 ThreadLocal是否已经存储当前的 Looper 对象,如果已经存在就会抛出异常。 /** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } final long traceTag = me.mTraceTag; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } try { msg.target.dispatchMessage(msg); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycleUnchecked(); } } loop 方法就是一个死循环,跳出死循环的方法,是 MessageQueue的 Next 方法为空,即queue.next() 为空。Looper 调用 quit 方法或者 quitSafely 方法,通知消息队列退出,会使 MessageQueue 的 next 方法 返回为空。 loop 调用 MessageQueue 的 next 方法获取新的消息,如果 没有消息,next 方法会一直阻塞在那里,导致 loop 方法也会一直阻塞在那里。 如果 next 方法返回了新的消息,Looper 就会处理新的消息,调用 msg.target.dispatchMessage(msg),msg.target 就是发送这条消息的 Handler 对象(Handler 中有讲解)。这样就把代码逻辑切换到指定线程去执行了。 3. ThreadLocal线程内部的数据存储类, 通过它可以在指定的线程存储数据,而且存储后,只能在指定线程获取存储的数据,其他线程无法获取。 应用:当某些数据是以线程为作用域,并且不同线程具有不同数据 存在Looper中,并不是线程,作用是在每个线程中存储数据 问题:Handler内部是如何获取当前线程的 Looper 的?Handler.java public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; } 答:Handler 通过 ThreadLocal 获取每个线程的 Looper. ThreadLocal 可以在不同线程中互不干扰的存储并提供数据。 在调用 Looper.prepare() 的时候 “sThreadLocal.set(new Looper(quitAllowed));” - 创建了一个 Looper 实例并将一个Looper的实例放入了ThreadLocal 存储。然后在 Handler 中 调用“mLooper = Looper.myLooper();”-从 sThreadLocal.get() 获取到 Looper 对象。 问题:主线程中为什么可以默认使用Handler?答: 线程默认是没有Looper 的 ,如果要使用 Handler ,就必须为线程创建 Looper. 但是主线程,也就是 UI 线程,它就是 ActivityThread, ActivityThread 被创建的时候默认会初始化 Looper,当前UI线程调用了Looper.prepare()和Looper.loop()方法. Handler主要工作:发送和接收消息; public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis); } private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); } 由上面可以看出 Handler 发送消息的过程就是向消息链表中插入了一条消息,MessageQueue 的 next 方法会返回这条消息给 Looper,Looper 收到消息,通过msg.target.dispatchMessage(msg) 交给 Handler 处理。 上面 enqueueMessage 方法首先 “msg.target = this;” 会把 this 赋值给 msg.target ,也就是说 把Handler 赋值给 msg的 target 属性。 public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } 首先会检查 Message的 callback 是否为 null,不为空就处理通过 handleCallback 来处理消息。 callback 是一个 Runnable 接口,就是 Handler 的 post 方法传递的 Runnable 参数 private static void handleCallback(Message message) { message.callback.run(); } 举个栗子 第一种handler 的使用方式,post方法 Handler mHandler = new handler(); mHandler.post(new Runnable() { @Override public void run() { Log.e("TAG", Thread.currentThread().getName()); mTxt.setText("yoxi"); } }); 其次 查看 mCallback 是否为空,mCallback 是个接口 public interface Callback { public boolean handleMessage(Message msg); } Callback 提供另一种使用 Handler 的方式,不想派生Handler的子类,可以通过 Callback 来实现。 举个栗子 第二种使用 Handler 的方式 private Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case value: break; default: break; } }; }; 最后,调用 Handler的 handleMessage 方法来处理消息。 原文发布时间为:2018-08-25本文来自云栖社区合作伙伴“Android开发中文站”,了解相关信息可以关注“Android开发中文站”。

优秀的个人博客,低调大师

OpenTelemetry 演示与 OpenTelemetry 的 Elastic 分发

作者:来自 ElasticRoger Coll 了解 Elastic 如何致力于支持用户使用 OpenTelemetry。探索我们对 OpenTelemetry Demo 的公开部署,并了解 Elastic 的解决方案如何增强你的可观察性体验。 最近,Elastic 为各种 OpenTelemetry 组件引入了 Elastic Distributions (EDOT),我们很自豪地宣布,这些 EDOT 组件现已在 Elastic 的 OpenTelemetry Demo 分支中可用。我们还公开了一个 Kibana 端点,让你可以深入了解演示的实时数据并亲自探索其功能。在这篇博文中,我们将详细说明分支背后的原因,并探索它引入的强大新功能。我们还将全面概述如何利用这些增强功能与 OpenTelemetry (EDOT) 的 Elastic Distributions 进行高级错误检测,以及 EDOT Collector(Elastic Agent 的尖端发展)进行无缝数据收集和分析。 什么是 OpenTelemetry 演示? OpenTelemetry 演示是一个基于微服务的应用程序,由 OpenTelemetry 社区创建,旨在展示其在现实的分布式系统环境中的功能。这个演示应用程序称为 OpenTelemetry Astronomy Shop,它模拟了一个由 10 多个互连微服务(以多种语言编写:Go、Java、.NET、Node.js 等)组成的电子商务网站,通过 HTTP 和 gRPC 进行通信。每项服务都完全使用 OpenTelemetry 进行检测,生成全面的跟踪、指标和日志。该演示是了解如何在实际应用程序中实现和使用 OpenTelemetry 的宝贵资源。 其中一项微服务名为 loadgenerator,它会自动开始向演示的各个端点生成请求,模拟多个客户端与系统交互的真实环境。这有助于复制具有并发用户活动的繁忙实时应用程序的行为。 Elastic 的分支 Elastic 认识到了通过分支 OpenTelemetry Demo 并集成高级 Elastic 功能来增强 OpenTelemetry Demo 的机会,以实现更深入的可观察性和更简单的监控。虽然分支是推荐的 OpenTelemetry 方法,但我们的目标是尽可能利用上游版本的强大基础和最新更新。为了实现这一点,Elastic 的 OpenTelemetry Demo 分支每天都会从上游进行拉取,将它们与 Elastic 特定的更改无缝集成。为了避免冲突,我们不断向上游做出贡献,确保 Elastic 的修改始终是附加的或可通过环境变量进行配置的。其中一个贡献是 .env.override 文件,它专为供应商分支而设计,用于覆盖演示中使用的微服务镜像和配置文件。 使用 Elastic 发行版获得更深入的洞察 在 Elastic 的 OpenTelemetry Demo 分支的最新更新中,我们已将用于检测的一些微服务 OTel SDK 替换为 Elastic 的专用发行版。这些更改确保与 Elastic 的可观察性工具进行更深入的集成,提供更丰富的洞察和更强大的监控功能。以下是分支的一些更改: Java 服务:广告、欺诈检测和 Kafka 服务现在使用 OpenTelemetry Java 代理的 Elastic 发行版。发行版中包含的功能之一是堆栈跟踪,它提供有关 span 起源于代码路径中何处的精确信息。在此处了解有关 Elastic Java 代理的更多信息。 Cart 服务已升级为使用 OpenTelemetry .NET 代理的 Elastic 发行版。此替换可让你了解如何使用 OpenTelemetry .NET 的 Elastic 发行版 (EDOT .NET) 开始在 .NET 应用程序中使用 OpenTelemetry,而无需进行任何代码更改。在此博客文章中了解有关 Elastic .NET 代理的更多信息。 在 Payment 服务中,我们配置了 OpenTelemetry Node.js 代理的 Elastic 发行版。该发行版附带 host-metrics 扩展,Kibana 提供了精选的服务指标 UI。在此处阅读有关 Elastic Node.js 代理的更多信息。 Recommendation 服务现在利用 EDOT Python,取代了标准的 OpenTelemetry Python 代理。Python 发行版是零代码(或自动)检测的另一个示例,这意味着发行版将设置 OpenTelemetry SDK 并为你启用所有推荐的检测。在此博客文章中了解有关 Elastic Python Agent 的更多信息。 需要强调的是,OpenTelemetry 的 Elastic 发行版不捆绑专有软件,它们建立在原始 OTel SDK 之上,但它们提供了一些优势,例如安装的单一软件包、使用合理的默认配置轻松自动检测、自动日志遥测发送等等。沿着这些思路,最终目标是将尽可能多的 EDOT 功能贡献给上游 OpenTelemetry 代理;它们的设计方式是,作为扩展实现的附加功能可直接与 OTel SDK 配合使用。 使用 Elastic Collector Distribution 收集数据 OpenTelemetry Demo 应用程序生成信号并将其发送到 OpenTelemetry Collector OTLP 端点。在 Demo 的分支中,EDOT 收集器设置为将所有 OTLP 信号从微服务转发到APM 服务器OTLP 端点。此外,它还将收集器收集的所有其他指标和日志发送到Elasticsearch端点。 如果分支部署在 Kubernetes 环境中,收集器将自动开始收集系统的指标。收集器将配置为使用hostmetrics 接收器来监控所有 K8s 节点的指标,使用kuebeletstats 接收器来检索 Kubelet 的指标,使用 filelog 接收器来收集所有集群的指标。 微服务生成的信号和 EDOT 收集器收集的信号都富含 Kubernetes 元数据,使用户可以无缝关联它们。这样可以轻松跟踪和观察每个服务在哪些 Kubernetes 节点和 pod 上运行,从而深入了解应用程序性能和基础设施健康状况。 了解有关 Elastic 的 OpenTelemetry Collector 发行版的更多信息:https://www.elastic.co/observability-labs/blog/elastic-distribution-opentelemetry-collector 使用 Elastic 进行错误检测 OpenTelemetry Demo 结合了flagd,这是一个用于模拟错误场景的功能标志评估引擎。例如,paymentServiceFailure 标志将强制对 charge 服务收费端点的每个请求都产生错误。由于该服务使用 OpenTelemetry 进行检测,因此错误将被捕获到生成的跟踪中。然后,我们可以使用 Kibana 强大的可视化和搜索工具将错误追溯到其根本原因。 另一个可用标志名为 adServiceHighCpu,它会导致广告服务中的 CPU 负载过高。可以通过服务的指标或其 Kubernetes pod 的相关指标来监控这种增加的 CPU 使用率: 模拟场景的完整列表可在此链接中找到。 开始你自己的探索 准备好探索带有 Elastic 的 OpenTelemetry Demo 及其增强的可观察性功能了吗?点击 Kibana 链接,开始你自己的探索,了解 Elastic 和 OpenTelemetry 如何改变你的可观察性方法。 现场演示:https://ela.st/demo-otel 但这还不是全部 —— 如果你想更进一步,你可以直接使用自己的 Elasticsearch 堆栈部署 OpenTelemetry Demo。按照此处提供的步骤进行设置,并开始从你自己的环境中获得有价值的见解。 原文:OpenTelemetry Demo with the Elastic Distributions of OpenTelemetry — Elastic Observability Labs

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册