首页 文章 精选 留言 我的

精选列表

搜索[过拟合],共10000篇文章
优秀的个人博客,低调大师

98%的程序员,都没有研究过JVM重排序和顺序一致性

重排序 数据依赖性 如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性。数据依赖分下列三种类型: 名称 代码示例 说明 写后读 a = 1;b = a; 写一个变量之后,再读这个位置。 写后写 a = 1;a = 2; 写一个变量之后,再写这个变量。 读后写 a = b;b = 1; 读一个变量之后,再写这个变量。 上面三种情况,只要重排序两个操作的执行顺序,程序的执行结果将会被改变。 前面提到过,编译器和处理器可能会对操作做重排序。编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。 注意,这里所说的数据依赖性仅针对单个处理器中执行的指令序列和单个线程中执行的操作,不同处理器之间和不同线程之间的数据依赖性不被编译器和处理器考虑。 as-if-serial语义 as-if-serial语义的意思指:不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。编译器,runtime 和处理器都必须遵守as-if-serial语义。 为了遵守as-if-serial语义,编译器和处理器不会对存在数据依赖关系的操作做重排序,因为这种重排序会改变执行结果。但是,如果操作之间不存在数据依赖关系,这些操作可能被编译器和处理器重排序。为了具体说明,请看下面计算圆面积的代码示例: COPYdouble pi = 3.14; //A double r = 1.0; //B double area = pi * r * r; //C 上面三个操作的数据依赖关系如下图所示: 如上图所示,A和C之间存在数据依赖关系,同时B和C之间也存在数据依赖关系。因此在最终执行的指令序列中,C不能被重排序到A和B的前面(C排到A和B的前面,程序的结果将会被改变)。但A和B之间没有数据依赖关系,编译器和处理器可以重排序A和B之间的执行顺序。下图是该程序的两种执行顺序: as-if-serial语义把单线程程序保护了起来,遵守as-if-serial语义的编译器,runtime 和处理器共同为编写单线程程序的程序员创建了一个幻觉:单线程程序是按程序的顺序来执行的。as-if-serial语义使单线程程序员无需担心重排序会干扰他们,也无需担心内存可见性问题。 程序顺序规则 根据happens- before的程序顺序规则,上面计算圆的面积的示例代码存在三个happens- before关系: COPYA happens- before B; B happens- before C; A happens- before C; 这里的第3个happens- before关系,是根据happens- before的传递性推导出来的。 这里A happens- before B,但实际执行时B却可以排在A之前执行(看上面的重排序后的执行顺序),如果A happens- before B,JMM并不要求A一定要在B之前执行。JMM仅仅要求前一个操作(执行的结果)对后一个操作可见,且前一个操作按顺序排在第二个操作之前。这里操作A的执行结果不需要对操作B可见;而且重排序操作A和操作B后的执行结果,与操作A和操作B按happens- before顺序执行的结果一致。在这种情况下,JMM会认为这种重排序并不非法(not illegal),JMM允许这种重排序。 在计算机中,软件技术和硬件技术有一个共同的目标:在不改变程序执行结果的前提下,尽可能的开发并行度。编译器和处理器遵从这一目标,从happens- before的定义我们可以看出,JMM同样遵从这一目标。 重排序对多线程的影响 现在让我们来看看,重排序是否会改变多线程程序的执行结果。请看下面的示例代码: COPYclass ReorderExample { int a = 0; boolean flag = false; public void writer() { a = 1; //1 flag = true; //2 } public void reader() { if (flag) { //3 int i = a * a; //4 …… } } } flag变量是个标记,用来标识变量a是否已被写入。这里假设有两个线程A和B,A首先执行writer()方法,随后B线程接着执行reader()方法。线程B在执行操作4时,能否看到线程A在操作1对共享变量a的写入? 答案是:不一定能看到。 由于操作1和操作2没有数据依赖关系,编译器和处理器可以对这两个操作重排序;同样,操作3和操作4没有数据依赖关系,编译器和处理器也可以对这两个操作重排序。让我们先来看看,当操作1和操作2重排序时,可能会产生什么效果?请看下面的程序执行时序图: 如上图所示,操作1和操作2做了重排序。程序执行时,线程A首先写标记变量flag,随后线程B读这个变量。由于条件判断为真,线程B将读取变量a。此时,变量a还根本没有被线程A写入,在这里多线程程序的语义被重排序破坏了! 注:本文统一用红色的虚箭线表示错误的读操作,用绿色的虚箭线表示正确的读操作。 下面再让我们看看,当操作3和操作4重排序时会产生什么效果(借助这个重排序,可以顺便说明控制依赖性)。 下面是操作3和操作4重排序后,程序的执行时序图: 在程序中,操作3和操作4存在控制依赖关系。当代码中存在控制依赖性时,会影响指令序列执行的并行度。为此,编译器和处理器会采用猜测(Speculation)执行来克服控制相关性对并行度的影响。以处理器的猜测执行为例,执行线程B的处理器可以提前读取并计算a*a,然后把计算结果临时保存到一个名为重排序缓冲(reorder buffer ROB)的硬件缓存中。当接下来操作3的条件判断为真时,就把该计算结果写入变量i中。 从图中我们可以看出,猜测执行实质上对操作3和4做了重排序。重排序在这里破坏了多线程程序的语义! 在单线程程序中,对存在控制依赖的操作重排序,不会改变执行结果(这也是as-if-serial语义允许对存在控制依赖的操作做重排序的原因);但在多线程程序中,对存在控制依赖的操作重排序,可能会改变程序的执行结果。 顺序一致性 数据竞争与顺序一致性保证 当程序未正确同步时,就会存在数据竞争。java内存模型规范对数据竞争的定义如下: 在一个线程中写一个变量, 在另一个线程读同一个变量, 而且写和读没有通过同步来排序。 当代码中包含数据竞争时,程序的执行往往产生违反直觉的结果。如果一个多线程程序能正确同步,这个程序将是一个没有数据竞争的程序。 JMM对正确同步的多线程程序的内存一致性做了如下保证: 如果程序是正确同步的,程序的执行将具有顺序一致性(sequentially consistent)–即程序的执行结果与该程序在顺序一致性内存模型中的执行结果相同(马上我们将会看到,这对于程序员来说是一个极强的保证)。这里的同步是指广义上的同步,包括对常用同步原语(lock,volatile和final)的正确使用。 顺序一致性内存模型 顺序一致性内存模型是一个被计算机科学家理想化了的理论参考模型,它为程序员提供了极强的内存可见性保证。顺序一致性内存模型有两大特性: 一个线程中的所有操作必须按照程序的顺序来执行。 (不管程序是否同步)所有线程都只能看到一个单一的操作执行顺序。在顺序一致性内存模型中,每个操作都必须原子执行且立刻对所有线程可见。 顺序一致性内存模型为程序员提供的视图如下: 在概念上,顺序一致性模型有一个单一的全局内存,这个内存通过一个左右摆动的开关可以连接到任意一个线程。同时,每一个线程必须按程序的顺序来执行内存读/写操作。从上图我们可以看出,在任意时间点最多只能有一个线程可以连接到内存。当多个线程并发执行时,图中的开关装置能把所有线程的所有内存读/写操作串行化。 为了更好的理解,下面我们通过两个示意图来对顺序一致性模型的特性做进一步的说明。 假设有两个线程A和B并发执行。其中A线程有三个操作,它们在程序中的顺序是:A1->A2->A3。B线程也有三个操作,它们在程序中的顺序是:B1->B2->B3。 假设这两个线程使用监视器来正确同步:A线程的三个操作执行后释放监视器,随后B线程获取同一个监视器。那么程序在顺序一致性模型中的执行效果将如下图所示: 现在我们再假设这两个线程没有做同步,下面是这个未同步程序在顺序一致性模型中的执行示意图: 未同步程序在顺序一致性模型中虽然整体执行顺序是无序的,但所有线程都只能看到一个一致的整体执行顺序。以上图为例,线程A和B看到的执行顺序都是:B1->A1->A2->B2->A3->B3。之所以能得到这个保证是因为顺序一致性内存模型中的每个操作必须立即对任意线程可见。 但是,在JMM中就没有这个保证。未同步程序在JMM中不但整体的执行顺序是无序的,而且所有线程看到的操作执行顺序也可能不一致。比如,在当前线程把写过的数据缓存在本地内存中,且还没有刷新到主内存之前,这个写操作仅对当前线程可见;从其他线程的角度来观察,会认为这个写操作根本还没有被当前线程执行。只有当前线程把本地内存中写过的数据刷新到主内存之后,这个写操作才能对其他线程可见。在这种情况下,当前线程和其它线程看到的操作执行顺序将不一致。 同步程序的顺序一致性效果 下面我们对前面的示例程序ReorderExample用监视器来同步,看看正确同步的程序如何具有顺序一致性。 请看下面的示例代码: COPYclass SynchronizedExample { int a = 0; boolean flag = false; public synchronized void writer() { a = 1; flag = true; } public synchronized void reader() { if (flag) { int i = a; …… } } } 上面示例代码中,假设A线程执行writer()方法后,B线程执行reader()方法。这是一个正确同步的多线程程序。根据JMM规范,该程序的执行结果将与该程序在顺序一致性模型中的执行结果相同。下面是该程序在两个内存模型中的执行时序对比图: 在顺序一致性模型中,所有操作完全按程序的顺序串行执行。而在JMM中,临界区内的代码可以重排序(但JMM不允许临界区内的代码“逸出”到临界区之外,那样会破坏监视器的语义)。JMM会在退出监视器和进入监视器这两个关键时间点做一些特别处理,使得线程在这两个时间点具有与顺序一致性模型相同的内存视图(具体细节后文会说明)。虽然线程A在临界区内做了重排序,但由于监视器的互斥执行的特性,这里的线程B根本无法“观察”到线程A在临界区内的重排序。这种重排序既提高了执行效率,又没有改变程序的执行结果。 从这里我们可以看到JMM在具体实现上的基本方针:在不改变(正确同步的)程序执行结果的前提下,尽可能的为编译器和处理器的优化打开方便之门。 未同步程序的执行特性 对于未同步或未正确同步的多线程程序,JMM只提供最小安全性:线程执行时读取到的值,要么是之前某个线程写入的值,要么是默认值(0,null,false),JMM保证线程读操作读取到的值不会无中生有(out of thin air)的冒出来。为了实现最小安全性,JVM在堆上分配对象时,首先会清空内存空间,然后才会在上面分配对象(JVM内部会同步这两个操作)。因此,在以清空的内存空间(pre-zeroed memory)分配对象时,域的默认初始化已经完成了。 JMM不保证未同步程序的执行结果与该程序在顺序一致性模型中的执行结果一致。因为未同步程序在顺序一致性模型中执行时,整体上是无序的,其执行结果无法预知。保证未同步程序在两个模型中的执行结果一致毫无意义。 和顺序一致性模型一样,未同步程序在JMM中的执行时,整体上也是无序的,其执行结果也无法预知。同时,未同步程序在这两个模型中的执行特性有下面几个差异: 顺序一致性模型保证单线程内的操作会按程序的顺序执行,而JMM不保证单线程内的操作会按程序的顺序执行(比如上面正确同步的多线程程序在临界区内的重排序)。这一点前面已经讲过了,这里就不再赘述。 顺序一致性模型保证所有线程只能看到一致的操作执行顺序,而JMM不保证所有线程能看到一致的操作执行顺序。这一点前面也已经讲过,这里就不再赘述。 JMM不保证对64位的long型和double型变量的读/写操作具有原子性,而顺序一致性模型保证对所有的内存读/写操作都具有原子性。 第3个差异与处理器总线的工作机制密切相关。在计算机中,数据通过总线在处理器和内存之间传递。每次处理器和内存之间的数据传递都是通过一系列步骤来完成的,这一系列步骤称之为总线事务(bus transaction)。总线事务包括读事务(read transaction)和写事务(write transaction)。读事务从内存传送数据到处理器,写事务从处理器传送数据到内存,每个事务会读/写内存中一个或多个物理上连续的字。这里的关键是,总线会同步试图并发使用总线的事务。在一个处理器执行总线事务期间,总线会禁止其它所有的处理器和I/O设备执行内存的读/写。下面让我们通过一个示意图来说明总线的工作机制: 如上图所示,假设处理器A,B和C同时向总线发起总线事务,这时总线仲裁(bus arbitration)会对竞争作出裁决,这里我们假设总线在仲裁后判定处理器A在竞争中获胜(总线仲裁会确保所有处理器都能公平的访问内存)。此时处理器A继续它的总线事务,而其它两个处理器则要等待处理器A的总线事务完成后才能开始再次执行内存访问。假设在处理器A执行总线事务期间(不管这个总线事务是读事务还是写事务),处理器D向总线发起了总线事务,此时处理器D的这个请求会被总线禁止。 总线的这些工作机制可以把所有处理器对内存的访问以串行化的方式来执行;在任意时间点,最多只能有一个处理器能访问内存。这个特性确保了单个总线事务之中的内存读/写操作具有原子性。 在一些32位的处理器上,如果要求对64位数据的写操作具有原子性,会有比较大的开销。为了照顾这种处理器,java语言规范鼓励但不强求JVM对64位的long型变量和double型变量的写具有原子性。当JVM在这种处理器上运行时,会把一个64位long/ double型变量的写操作拆分为两个32位的写操作来执行。这两个32位的写操作可能会被分配到不同的总线事务中执行,此时对这个64位变量的写将不具有原子性。 当单个内存操作不具有原子性,将可能会产生意想不到后果。请看下面示意图: 如上图所示,假设处理器A写一个long型变量,同时处理器B要读这个long型变量。处理器A中64位的写操作被拆分为两个32位的写操作,且这两个32位的写操作被分配到不同的写事务中执行。同时处理器B中64位的读操作被分配到单个的读事务中执行。当处理器A和B按上图的时序来执行时,处理器B将看到仅仅被处理器A“写了一半“的无效值。 注意,在JSR -133之前的旧内存模型中,一个64位long/ double型变量的读/写操作可以被拆分为两个32位的读/写操作来执行。从JSR -133内存模型开始(即从JDK5开始),仅仅只允许把一个64位long/ double型变量的写操作拆分为两个32位的写操作来执行,任意的读操作在JSR -133中都必须具有原子性(即任意读操作必须要在单个读事务中执行)。 本文由传智教育博学谷狂野架构师教研团队发布。 如果本文对您有帮助,欢迎关注和点赞;如果您有任何建议也可留言评论或私信,您的支持是我坚持创作的动力。 转载请注明出处!

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

唯一通过德国联邦信息安全局考核的浏览器

在近期德国网络安全机构“德国联邦信息安全局(BSI)”针对几大 Web 浏览器进行的审查中,Firefox 在安全性上获得了最高分,并且是唯一通过所有强制性安全功能最低要求的浏览器。 不过前提是 BSI 只对 Mozilla Firefox 68(ESR)、Google Chrome 76、Microsoft Internet Explorer 11 和 Microsoft Edge 44 进行了测试,并不包括 Safari、Brave、Opera 与 Vivaldi 等浏览器。 此次测试是使用 BSI 于 2019 年 9 月发布的“现代安全浏览器”指南中详述的规则进行的。BSI 通常根据该指南就可以安全使用哪些浏览器向政府机构和私营公司提供建议。此次指南更新完善了现代浏览器新增和改进的安全措施与机制,例如HSTS、SRI、CSP 2.0、遥测处理和改进的证书处理机制。 根据 BSI 的新指南,被认为安全的现代 Web 浏览器必须满足以下最低要求: 必须支持 TLS 必须具有受信任证书的列表 必须支持扩展验证(EV)证书 必须根据证书吊销列表(CRL)或在线证书状态协议(OCSP)验证加载的证书 浏览器必须使用图标或颜色高亮来显示通信何时加密到远程服务器或采用明文形式 仅在经过特定用户的批准后,才允许连接到使用过期证书运行的远程网站 必须支持HTTP Strict Transport Security (HSTS) (RFC 6797) 必须支持Same Origin Policy (SOP) 必须支持Content Security Policy (CSP)2.0 必须支持子资源完整性(SRI) 必须支持自动更新 必须为关键的浏览器组件和扩展支持单独的更新机制 必须对浏览器更新进行签名和验证 浏览器的密码管理器必须以加密形式存储密码 必须仅在用户输入主密码之后允许访问浏览器的内置密码库 用户必须能够从浏览器的密码管理器中删除密码 用户必须能够阻止或删除 cookie 文件 用户必须能够阻止或删除自动完成历史记录 用户必须能够阻止或删除浏览历史记录 组织管理员必须能够配置或阻止浏览器发送遥测/使用数据 浏览器必须支持一种机制来检查有害内容/URL 浏览器应允许组织运行本地存储的 URL 黑名单 必须支持一些设置,用户可以在其中启用/禁用插件、扩展或脚本 浏览器必须能够导入集中创建的配置设置,非常适合大规模企业部署 必须允许管理员禁用基于云的配置文件同步功能 必须在初始化后以最小的操作系统权限运行在操作系统中 必须支持沙箱 所有浏览器组件必须彼此隔离,并且与操作系统隔离。隔离组件之间的通信只能通过定义的接口进行,不能直接访问隔离组件的资源 网页需要彼此隔离,最好以独立进程的形式,还要允许线程级隔离 必须使用支持堆栈和堆内存保护的编程语言对浏览器进行编码 浏览器供应商必须在公开披露安全漏洞后不超过 21 天提供安全更新。如果主浏览器供应商未能提供安全更新,则组织必须移至新的浏览器 浏览器必须使用 OS 内存保护,例如地址空间布局随机化(ASLR)或数据执行保护(DEP) 组织管理员必须能够管理或阻止未经批准的附件/扩展的安装 根据 BSI 的说法,Firefox 是唯一支持以上所有要求的浏览器,其它浏览器测试不通过的原因包括: 缺少对主密码机制的支持(Chrome、IE、Edge) 没有内置的更新机制(IE) 没有阻止遥测收集的选项(Chrome、IE、Edge) 不支持 SOP(IE) 不支持 CSP(IE) 不支持 SRI(IE) 不支持浏览器配置文件/不同的配置(IE、Edge) 缺乏组织透明度(Chrome、IE、Edge) 消息来源: https://www.zdnet.com/article/germanys-cyber-security-agency-recommends-firefox-as-most-secure-browser

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

还没体验过无人超市?手把手教你用计算机识别技术自己开一家!

2016年年末,Amazon无人超市横空出世。在这家无人超市,店内的相机能够自动追踪你拿取的商品;完成购物后,你无需排队等候收银,只用直接走出超市。 自此之后,阿里和京东也已相继加入战局,先后推出无人超市体验店。一时间,无人超市的概念已实现了大规模普及。 无人超市的“黑科技”到底是什么呢?今天,文摘菌就为大家科普其中最重要的一环——基于计算机视觉技术的物体识别。 首先,让我们分析一下实现无人超市的两大难点。 难点一:把商品加入购物车 超市里的智能货架需要能够追踪到客户拿走了什么商品。我们可以用两个物品识别模型来实现这个功能,一个用来跟踪手部动作以获取被拿起的物品。另一个独立模型则用于检测货架的空间。请看下面的动画,同时使用两个模型可以大大降低误判。 难点二:自动结账 无人超市的需要解决的另一难点是,实现摄像头对物品的一次性识别,这样我们就不需要

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

一个没听说过的品牌成为印度手机老大,美国人又惊到了

【大咖・来了 第7期】10月24日晚8点观看《智能导购对话机器人实践》 说实话,美国媒体现在颇有些“天朝上国,万邦来朝”感觉,这也难怪,美国互联网仍是世界的中心,有苹果、微软、Google、Facebook 这几座大山在,就算是有了互联网世界的绝对话语权。但是来自中国等地的互联网力量迅速崛起,让美国评论者们感到了深深的压力,就像不久前彭博社抱怨 CES 中有太多的亚洲人来,以至于拉斯维加斯的酒店都不够住了一样。 不过要是比人口数量,以及市场容量的话,中国和印度无疑要大大胜过美国。先是在不久前的季度统计中,小米成为中国智能手机份额***,让外国友人大吃 一惊。而后在最近的统计中,印度手机品牌Micromax 取代三星成为印度市场份额***的厂商,再一次让印度之外的外国友人大吃一惊,当然其中也有我。 不过关于Micromax 的统计是基于Canalys 的统计,该机构指出,在刚刚过去的 2014 年第四季度,Micromax 在印度的市场份额为 22%,超过了三星的 20%,成为印度智能手机的老大。对此,三星表示并不认可,他们援引GfK 的数据称,三星仍是印度市场***,份额为34.3%。姑且不讨论这一组出入有些大的谁对谁错,印度智能手机市场正在出现和中国类似的格局:本土品牌依靠***性价比的手机快速占领原本属于国际大品牌的市场份额。 (Micromax Canvas Knight 手机) 并且,这不是没有征兆的,只有当Micromax 取代三星成为市场***这样“量变产生质变”的结果出现时,人们才会意识到,(印度/中国)国产手机居然如此强势。早在 2013 年的时候,Micromax 就在不断拉近与三星的距离,并且在印度前几的智能手机品牌中,印度本土的 Micromax、Karbonn、Lava 和国际品牌形成分庭抗礼之势: (2013 Q1 到 Q2 印度智能机份额变化) 《福布斯》对此现象给了一个很无奈的标题《这些听都没听过的牌子怎样颠覆中国和印度手机市场》,文章中有个很有意思的对比: 无锁版的 iPhone 6 售价 649 美元起,比美国人均年收入 53143 美元(2013 年数据)的 1% 多一点,在中国,这是中国人均年收入的 10%,而在印度,买一个 iPhone 6 要花掉他们人均年收入的 43%。 严格来说,《福布斯》给出的对比并不一定精确,一是 iPhone 6 在中国和印度的售价要高于美国本土,二是就中印美三国国情来看,中印的人均收入反映的问题很有限,毕竟中印国民之间的贫富差距,地区差异远大于美国。 正是这样,在太平洋对岸的人们看来,收入的巨大差距使得不同于苹果和三星高价路线的Micromax 和小米们成功在市场份额逆袭,为了制造符合更多人价格预期的手机,来自中国和印度本土厂商们以各种方式降低成本,包括被广泛复制的线上销售,和线上抢购。 而这些出货量巨大的厂商也吸引着志同道合的小伙伴,去年 Google 选择的首批 Android One 伙伴就是印度三家本土厂商Micromax、Karbonn、Spice,这批 Android One 智能手机的价格当时低至6399 卢比(105 美元)。 曾经智能手机的主旋律是苹果和三星的缠斗,如今的格局已经变成了在发达市场,苹果三星斗争还将继续;在发展中市场,则是苹果如何稳固地位,本土品牌如何再进一步、三星如何逆转的三国演义了。 【责任编辑: chenqingxiang TEL:(010)68476606】

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

Spring Cloud Edgware新特性之一:解决Eureka中Jersey 1.x版本过旧的问题-不使用Jersey

Spring Cloud是当前炙手可热的微服务开发框架。它的功能强大,组件丰富,设计优雅。目前Spring Cloud还在不断发展之中。 Spring Cloud即将发布Spring Cloud Edgware 版本。该版本解决了不少Bug,新增了不少新特性,本系列博客将为大家详细阐述在Spring Cloud Edgware中新增的特性。 为了让描述更加的贴合实际,本文将结合笔者所在团队遇到的实际情况进行讲解。 背景 Eureka服务器与客户端之间默认使用Jersey 1.x 进行基于HTTP协议的交互。然而我们团队,需使用docker-client (https://github.com/docker-java/docker-java) 。这货只支持Jersey 2.x ,而Jersey 1.x与2.x并不兼容。 寻求方案 于是,我们团队面临如下几种选择: 使用Eureka提供的eureka-client-jersey2 模块,即使用Jersey 2.x 来代替Jersey 1.x https://github.com/Netflix/eureka/tree/master/eureka-client-jersey2 。然而,这种方式不够稳妥,原因是eureka-client-jersey2 是由社区提供,并非由Eureka官方团队维护,并且已经很久不更新了。 放弃使用docker-client ,使用其他的Docker客户端,例如https://github.com/spotify/docker-client (该项目支持Jersey 1.x以及Jersey 2.x)。 升级Spring Cloud Netflix 到1.4.x,即:Spring Cloud Edgware 【笔者认为的最佳方案】。 本文探讨的就是在Spring Cloud Edgware 中Eureka的点点滴滴。 废弃Eureka Client的Jersey Spring Cloud Edgware 中,Jersey并非必选。可为Eureka Client禁用掉Jersey,转而使用我们想要的HTTP客户端,例如RestTemplate。只需将Jersey的包从依赖中删除,Spring Cloud就会自动配置一个基于Spring RestTemplate 的传输客户端。操作如下: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> <exclusions> <exclusion> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> </exclusion> <exclusion> <groupId>com.sun.jersey</groupId> <artifactId>jersey-core</artifactId> </exclusion> <exclusion> <groupId>com.sun.jersey.contribs</groupId> <artifactId>jersey-apache-client4</artifactId> </exclusion> </exclusions> </dependency> 收益 简单的操作后,有两个好处: 再也不用烦Jersery的版本冲突问题 依赖减少了一些。 原理及代码 详见:https://github.com/spring-cloud/spring-cloud-netflix/issues/1849 。简单来说,就是Eureka提供了一个抽象,允许用户为Eureka Client定制自己的HTTP客户端,而不像老版本,强制使用Jersery。 本文链接: http://www.itmuch.com/spring-cloud/edgware-new-eureka-jersey1/ **版权声明: **本博客由周立创作,采用 CC BY 3.0 CN 许可协议。可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。

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

期货L2五档和逐笔成交到底能下到哪些字段,我在CMES踩过的记录

之前在搞一个期指跨期套利的脚本,被分钟线数据折磨得够呛。别的源头拉回来的1分钟K线,经常同一个时间戳有两笔收盘价不一样,也不知道该信哪个,算出来的价差信号全是毛刺。后面硬着头皮换到数据源:CMES金融数据库试了下,它家的分钟线居然没有这种重叠脏数据,顺势就把网站挂出来的几类期货L2行情都摸了一遍。

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

做比价系统和 ERP 货源对接,这几个价格坑 90% 的人都踩过

做电商数据开发、比价工具、跨境 ERP 货源对接的时候,价格字段是最基础也最容易出错的环节。很多开发者直接把接口返回的某个价格字段当成用户最终付款价,结果业务上线后频繁出现报价偏差、客户投诉。京东平台的价格体系尤其复杂,原价、促销价、券后价、到手价,几个字段看起来差不多,实际含义和获取方式天差地别。今天就把京东原价和券后价这两个最核心的字段彻底讲清楚,帮你避开业务落地里最常见的价格陷阱。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

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

Nacos

Nacos

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

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

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

用户登录
用户注册