动态创建FeignClient

之前在项目里面都是指定一个interface做FeignClient,带上FeignClient的注解,这样子每一个微服务都需要有个interface。在做中台项目的时候需要通过配置化来创建FeignClient,就想到怎么手动去创建FeignClient。一番操作猛如虎后,写个memo以防自己以后忘记了。 创建eureka服务 在 https://start.spring.io/ 中勾选Eureka Server,下载下来后: 代码:Application类上加注解 @EnableEurekaServer 配置文件: ...

MAC编译openjdk

配置mac环境:brew install freetype ccache,安装xcode,gcc和make都需要 代码推荐https://hg.openjdk.java.net/jdk/jdk12/ 去获取zip包(点击browse->zip) 下载解压后 chmod ...

JVM字节码调用指令

invokestatic:用于调用静态方法。 invokespecial:用于调用私有实例方法、构造器,以及使用 super 关键字调用父类的实例方法或构造器,和所实现接口的默认方法。 invokevirtual:用于调用非私有实例方法。 invokeinterface:用于调用接口方法。 invokedynamic:用于调用动态方法。 ...

任务调度系统调研

因为需要用到java系的调度系统,所以最近在调研。 国内的主要有xxl-job、saturn、quartz和sia-task,因为quartz有数据库锁的问题,saturn没有说明是否可以做任务依赖,所以初步选择xxl-job和sia-task。 xxl-job github: https://github.com/xuxueli/xxl-job/ xxl-job部署非常方便,起mysql、起调度中心和执行器即可: 部署 mysql ...

TF-Serving源码分析—模型加载部分

背景 因为要加一个检测模型加载是否成功的接口,需要读取TF-Serving中保存的加载到内存的model_config_file。 一开始在ServerCore里面加一个函数getConfig(),加锁访问该类中的config_,该变量保存了模型配置。 Status ServerCore::getConfig(std::unordered_map<string, string>* config_map) ...

GUARDED_BY —— clang的线程安全分析模块 thread safety analysis

通过代码注解(annotations )告诉编译器哪些成员变量和成员函数是受哪个 mutex 保护,这样如果忘记了加锁,编译器会给警告。因为在后续维护别人的代码时候,往往不像原作者那样深刻理解设计意图,特别容易遗漏线程安全的假设。 Thread Safety Annotations 可以方便阅读代码,而且在编译的时候会检查锁的状态。 其工作原理非常类似于多线程程序的类型系统。除了声明数据类型之外,还可以声明在多线程环境中如何控制对该数据的访问。比如如果foo遍历被互斥锁mu保护,那么只要有一段代码在没有先锁定mu的情况下读取或写入foo, ...

const在变量前后的含义

const int * p1=&me;//p1可变,p1不可变,此时不能用p1来修改,但是p1可以转向 int * const p2=&me;//p2不可变,p2可变,此时允许p2来修改其值,但是p2不能转向。 const int ...

C++的std::optional

解决函数多个返回值 为了解决C++函数返回多个值的问题,以前的做法通常是把返回指的指针作为入参传入,用函数的返回值作为运行状态的标识,比如下面这段,把指针output传入: #include <iostream> using namespace std; int func(const string& str, ...

JVM内存 — 《java核心技术》

JVM内存区域划分 程序计数器,每个线程都有自己的程序计数器,存储当前线程正在执行的Java方法的JVM指令地址; Java虚拟机栈,每个线程在创建时都会创建一个虚拟机栈,内部保存一个个栈帧,对应着一次次方法调用。如果在该方法中调用了其他方法,则会创建新的栈帧。栈帧中存储着局部变量表、操作数栈、动态链接、方法正常退出或异常退出的定义等; 堆,放置Java对象实例,是垃圾收集器重点照顾的区域; 方法区,所有线程共享的一块内存区域,用于存储元数据, ...

Spring sidecar模式纳入TF-Serving(二):mac上编译TF-Serving

前言 因为卤煮的云主机只有1G的内存,blade编译的时候一直OOM,所以只能在自己的mac上编译。 blade和TF-Serving版本、gcc版本之间都需要匹配,特别是bazel和TF-Serving之间匹配,不然经常因为各种原因装不上,这里列一下清单: 名称 版本 下载地址 TF-Serving r1.15 https://github.com/tensorflow/serving ...

Java的类加载过程 - 《Java核心技术》

Java类加载步骤 加载:将字节码数据从不同的数据源读取到JVM中,并映射为JVM认可的数据结构; 链接:把原始类定义信息平滑的转化入JVM,包括: 验证:验证字节信息是符合Java虚拟机规范的。 准备:创建类或接口中的静态变量,并初始化静态变量的初始值。 解析:将常量池中的符号引用替换为直接引用。 初始化:真正执行类初始化的代码逻辑,包括静态字段赋值、执行类定义中的静态初始化块内的逻辑。 双亲委派模型 简单来说就是当类加载器试图加载某个类型的时候, ...

K8s概述(三):最佳实践

如何配置pod pod的生命周期: Pending:etcd已经保存了Pod的状态,但是这个Pod还没有被scheduled,还没拉取image Running:Pod已经schedule到node上,kubelet已经创建了所有的容器 Succeeded:Pod中所有容器被终止,不再重启 Failed:Pod中所有容器被终止,至少有一个容器是因为失败而终止 Unknown:API server与Pod的通信中断,通常是因为与kubelet的通信中断 init ...

K8s概述(二):k8s组件选型

存储 使用 Volume是将宿主机目录与容器目录绑定挂载在一起。k8s把存储抽象为PV、PVC,把存储提供者与使用者分离。使用者只需要声明希望持有的持久化存储的属性(PVC),提供者提供可用的各种类型存储、节点、用户名密码等,提供PV。这样子的好处是使用者不需要关心底层是使用什么存储设备来实现的。 存储的选择 存储的选择:排除NFS,有单点问题,在GlusterFS和Ceph中做选择。根据网上找到的一篇文章以及本人自己dd后的测试结果,GlusterFS比Ceph略快一些: ...

K8s概述(一):几种集群方案的对比

几种集群方案简介 下面以docker部署为主,主流的容器化集群部署方案主要有以下几种: Docker Compose:帮助在同一个节点上部署多个容器。 Docker Swarm:多台机器上部署容器。开箱即用,快速部署容器。偏重容器部署 K8s:社区活跃度高,组件丰富。微服务化,偏重应用的部署。 Marathon+Mesos:大数据组件部署。 ...

K8s概述(前言)

卤煮之前在某厂商做toB项目的时候,需要去客户那里做私有化部署。一开始用的手工部署,多机部署要维护互联关系,还有各种词典、健康检查等都需要自己手动做,模块多起来之后简直就是灾难。后面上了整套k8s部署,大大的解放了生产力,把问题转移到了如何更好的使用k8s上面。 这里我对比一下跟物理机部署比起来,为什么我们要用k8s做私有化部署: 物理机、虚拟机部署 k8s容器化部署 创建一个AWS实例、或一台可用物理机 起一个容器 Puppet/ansible指明安装部署的二进制文件、 ...

Spring sidecar模式纳入TF-Serving(一):sidecar模式实验

前言 因为客服在线模块在线上要使用到tf-serving做在线推理,所以需要把C++模块集成进来。这一篇主要讲sidecar的实验部分,会起一个Django进程嵌入SpringCloud中做非JVM微服务来做实验。 起Eureka 在 https://start.spring.io/ 勾选Eureka Server Application加上EnableEurekaServer: @SpringBootApplication @EnableEurekaServer public class CloudApplication ...

LongAdder

LongAdder是jdk8新增的用于高并发环境的计数器。 Atomicxxx使用硬件级别的指令CAS来更新计数器的值,在高并发的情况下每次只能有一个线程能成功,竞争失败的线程会非常多,白白浪费了很多cpu事件,因为竞争失败的线程会自旋。 jdk8的AtomicLong: // jdk1.8的AtomicLong的实现代码,这段代码在sun.misc.Unsafe中 // 当线程竞争很激烈时,while判断条件中的CAS会连续多次返回false,这样就会造成无用的循环,循环中读取volatile变量的开销本来就是比较高的 // 因为这样,在高并发时,AtomicXXX并不是那么理想的计数方式 public ...

Java并发类库提供的线程池有哪几种? 分别有什么特点? - 《Java核心》笔记

通常都是使用Executors提供的通用线程池创建方法去创建不同配置的线程池,主要区别在于不同的ExecutorService类型或者不同的初始参数,主要分为五类: newCachedThreadPool() 用于处理大量短时间工作任务的线程池。会试图缓存线程并重用,当无缓存线程可用时,会创建新的工作线程。如果线程闲置时间超过60秒,则被终止并移出缓存。长时间闲置时,这种线程池不会消耗什么资源。其内部使用SynchronousQueue作为工作队列。 newFixedThreadpool(int nThreads) 重用固定数目的线程,背后使用的是无界的工作队列。如果任务数量超过了nThread,将在工作队列中等待空闲线程出现。 ...

AQS(转)

简介 AQS:AbstractQueuedSynchronizer,队列同步器,Java中同步组件的基础框架。JUC并发包中的核心基础组件。 AQS解决了子类实现同步器时涉及到的大量细节问题,例如获取同步状态、FIFO同步队列。 基于AQS构建的同步器中,只能在一个时刻发生阻塞,从而降低上下文切换的开销,提高了吞吐量。 AQS的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态。 AQS使用一个int类型的成员变量state来表示同步状态,当state>0时表示已经获取了锁,当state ...

LockSupport源码分析

concurrent包基于AQS框架,AQS框架基于两个类: Unsafe(提供CAS操作) LockSupport(提供park/unpark操作) 概念 LockSupport public static void park() { UNSAFE.park(false, 0L); } public static void ...

条件变量pthread_cond_t

条件变量是什么 条件变量是线程同步的一种手段,用于阻塞线程直到条件发生。 条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个/多个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"信号。 代码示例: #include <pthread. ...

并发包中的ConcurrentLinkedQueue和LinkedBlockingQueue有什么区别? - 《Java 核心技术》笔记

Concurrent* 容器,基于lock-free,在常见的多线程访问场景,一般可以提供较高吞吐量; LinkedBlockingQueue内部基于锁,并提供了BlockingQueue的等待性方法。 Concurrent* 性质 java.util.concurrent包提供的容器(Queue、List、Set)、Map从命名上可以大概分为Concurrent* 、CopyOnWrite和Blocking等三类: Concurrent没有类似CopyOnWrite之类容器相对较重的修改开销; Concurrent提供了较低的遍历一致性。比如当利用迭代器遍历时, ...

Java并发包提供的并发工具类 - 《java核心》笔记

提供了各种丰富的同步结构,包括CountDownLatch、CyclicBarrier、Semaphore等,可以实现更加丰富的多线程操作,比如利用Semaphore作为资源控制器,限制同时进行工作的线程数量; 各种线程安全的容器,比如ConcurrentHashMap,有序的ConcurrentSkipListMap,通过类似快照机制实现线程安全的动态数组CopyOnWriteArrayList; 各种并发队列实现,比如BlockedQueue,ArrayBlockingQueue、SynchorousQueue,或针对特定场景的PriorityBlockingQueue等; 强大的Executor,可以创建各种不同类型的线程池,调度任务运行等。 问题 ...

死锁 - 《Java 核心》笔记

定位死锁常见方式 必定会出现死锁的程序: public class DeadLockSample extends Thread { private String first; private String second; public DeadLockSample(String name, String first, String ...

ConcurrentSkipListMap实现原理

跳表介绍 跳表是一种随机层次的数据结构,通过建立多级索引,实现以二分查找遍历一个有序链表。 SkipList让已排序的数据分布在多层链表中,以0~1随机数决定一个数据的向上攀升与否,以时间换空间的一个算法。 SkipList的性质: 多层结构,level通过一定概率随机产生; 每一层都是一个有序链表; 最底层包含所有元素; 如果一个元素出现在第i层,则i层以下也包含这个元素; 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。 性能对比 ConcurrentHashMap和ConcurrentSkipListMap对比, ...

Phaser

Phaser是JDK1.7引入的一个同步工具类,适用于一些需要分阶段的任务处理。一种人物可以分为多个阶段,现希望保证只有前面一个阶段的任务完成后才能开始后面的任务。这种场景可以使用多个CyclicBarrier来实现,但是需要明确知道总共有多少个阶段,且无法动态修改。Phaser可以同时解决这两个问题。 同步器 作用 CountDownLatch 倒数计时器 CyclicBarrier 循环栅栏,初始时设定参与线程数,当线程到达栅栏后,会等待其他线程的到达。当到达栅栏的总数满足指定数后,所有等待的线程继续执行。 ...

ForkJoinPool

ForkJoinPool的作用 ThreadPoolExecutor每个任务都是单独线程处理的。如果某个任务耗时很大,就可能出现其他线程都在等着这个线程结束的情况。 为了处理这种问题,ForkJoinPool将一个大任务拆分为多个小任务,使用fork可以将小任务分发给其他线程同时处理,使用join可以将多个线程处理的结果进行汇总。 ForkJoinPool的原理 ForkJoinPool中每个线程都有自己的双端列表用于存储任务。这个双端列表对于工作窃取算法非常重要。 public class ForkJoinWorkerThread extends Thread { final ForkJoinPool pool; // 工作线程所在的线程池 ...

协程

why 协程 协程的两大特点: 占用的资源更少; 所有的切换和调度都发生在用户态。 协程是一种轻量级、用户态的执行单元。拥有自己的寄存器上下文和栈。协程调度切换时,把寄存器上下文和栈保存到其他地方。在切回来的时候再恢复回来。 线程:抢占式多任务。 协程:协作式多任务。 不管是进程还是线程,阻塞、切换调度的时候都需要陷入系统调用,由CPU跑调度程序,再由调度程序决定跑哪一个进程( ...