DooD:Docker+Jenkins

DooD:Docker+Jenkins

1. 基础环境 本文基于64位的CentOS 7.2系统,内核版本如下: 图1 宿主机的操作系统内核版本 Docker版本如下: 图2 Docker版本 如需安装Docker,请点击:安装Docker 如需安装Docker加速器,请点击:配置Docker加速器 2.在容器中调用docker命令有以下几种方式 2.1 DooD(Docker-outside-of-Docker) 其实就是运行一个Jenkins镜像的docker容器,这种方式使用socket套接字(一般默认是/var/run/docker.sock文件)和宿主机进行交互,只限于本地通信。不会去监听任何端口。在创建Jenkins镜像时,可以给jenkins用户赋予sudo权限来调用docker命令;或者将jenkins用户加入到docker组,就可以直接在容器中调用docker命令,下文会分别讲到两种情况的Dockerfile的写法。不过相比较于不同的宿主机docker组的不同,使用sudo更具有普适性和可移植性。 2.2 DinD(Docker in Docker) 顾名思义,就是在Docker容器中重新安装一个Docker应用。容器中安装Docker和宿主机安装的Docker是完全没有关联的两个程序。一般情况下,我们想要的只是一个运行于docker的CI/CD环境,我们需要容器内外只有一个docker engine。 DinD显然比我们想要的要复杂的多,而且可能还有一些意想不到的问题会出现。 更详细的了解,请参考下面两篇文章: https://zhuanlan.zhihu.com/p/27208085 https://github.com/jpetazzo/dind 2.3 使用HTTP/HTTPS与Docker Engine通讯 Docker还可以对外暴露Remote API,通过http/https就可以与docker engine进行通信,因为打开Remote API相应的要对外暴露端口,所以相对来说是不安全的。 在Jenkins容器中可以通过配置相应的Docker plugin,并在“系统管理”——>“系统设置”——>“云”中增添响应的Remote API信息。 详细信息请参考: https://docs.docker.com/engine/security/https/ 进过对比,我使用的是第一种方式:DooD。 注意点:请确保宿主机的doeker server已经开启本地套接字访问和远程通信 3.在宿主机上开启本地套接字访问和远程通信 默认情况下,Docker守护进程会生成一个socket(/var/run/docker.sock)文件来进行本地进程通信,而不会监听任何端口,因此只能在本地使用docker客户端或者使用Docker API进行操作。 如果想在其他主机上操作Docker主机,就需要让Docker守护进程监听一个端口,这样才能实现远程通信。 目前开启本地套接字访问和远程通信有以下两种方式: 3.1 修改/etc/docker/daemon.json 把以下内容添加进json文件中,注意添加前请确认23

干货|一篇文章带你学习分布式事务

干货|一篇文章带你学习分布式事务

一. 事务 1.1 什么是事务 数据库事务(简称:事务,Transaction)是指数据库执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。 事务拥有以下四个特性,习惯上被称为ACID特性: 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态是指数据库中的数据应满足完整性约束。除此之外,一致性还有另外一层语义,就是事务的中间状态不能被观察到(这层语义也有说应该属于原子性)。 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行,如同只有这一个操作在被数据库所执行一样。 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。在事务结束时,此操作将不可逆转。 1.2 本地事务 起初,事务仅限于对单一数据库资源的访问控制: 架构服务化以后,事务的概念延伸到了服务中。倘若将一个单一的服务操作作为一个事务,那么整个服务操作只能涉及一个单一的数据库资源: 这类基于单个服务单一数据库资源访问的事务,被称为本地事务(Local Transaction)。 二. 分布式事务应用架构 本地事务主要限制在单个会话内,不涉及多个数据库资源。但是在基于SOA(Service-Oriented Architecture,面向服务架构)的分布式应用环境下,越来越多的应用要求对多个数据库资源,多个服务的访问都能纳入到同一个事务当中,分布式事务应运而生。 最早的分布式事务应用架构很简单,不涉及服务间的访问调用,仅仅是服务内操作涉及到对多个数据库资源的访问。 当一个服务操作访问不同的数据库资源,又希望对它们的访问具有事务特性时,就需要采用分布式事务来协调所有的事务参与者。 对于上面介绍的分布式事务应用架构,尽管一个服务操作会访问多个数据库资源,但是毕竟整个事务还是控制在单一服务的内部。如果一个服务操作需要调用另外一个服务,这时的事务就需要跨越多个服务了。在这种情况下,起始于某个服务的事务在调用另外一个服务的时候,需要以某种机制流转到另外一个服务,从而使被调用的服务访问的资源也自动加入到该事务当中来。下图反映了这样一个跨越多个服务的分布式事务: 如果将上面这两种场景(一个服务可以调用多个数据库资源,也可以调用其他服务)结合在一起,对此进行延伸,整个分布式事务的参与者将会组成如下图所示的树形拓扑结构。在

开启String去重XX:+UseStringDeduplication的利与弊

开启String去重XX:+UseStringDeduplication的利与弊

首先来看下由JDK开发组研究得出的一组有趣的统计数据: 1.java应用内存里面的字符串占比大概是25%。 2.java应用内存里面的字符串有13.5%是重复的。 3.字符串的平均长度是45。 由于存在重复字符串导致高达13.5%的内存被浪费了!你可以用HeapHero来分析看下你的应用中有多少内存是因为重复字符串被浪费掉的。 什么是重复字符串呢? 看下面的代码: String string1 = new String("Hello World"); String string2 = new String("Hello World"); 1 2 上面定义了两个字符串对象string1和string2,它们的内容是一样的,都是Hello World,但是string1和string2是两个不同的对象。string1.equals(String2)=true,但是string1==string2=false,string1和string2就是所谓的重复对象。 为啥有这么多的重复字符串? 应用中存在重复字符串的原因有很多种,下面我们来看下常见的两种情况: 1.开发者为每一个请求都创建新的字符串对象,而不是使用诸如public satatic final String 来重复利用他们,上面的例子可以用以下方式进行优化: public static final String HELLO_WORLD = "Hello World"; String string1 = HELLO_WORLD; String string2 = HELLO_WORLD; 1 2 3 2.假如你正在开发一个银行或者电商系统,数据库中的每一笔交易记录都需要存储货币名称(‘USD’, ‘EUR’, ‘INR’, ….),现在有一个用户登陆了系统然后查看历史的交易记录,因此你的应用需要从数据库中读取这个用户的所有交易记录。如果这个用户是在美国,因为每一笔交易都有货币,因此你的应用需要为每一笔交易都创建USD这个字符串,如果这个用户有成千上万比的交易,你的应用就需要为这一个用户在内存中创建成千上万个USD字符串。 与此类似,应用还需要多次从数据库中读取很多列(用户名、地址、状态、联系方式等等),这个过程中也会产生重复对象。你的应用通过JSON/XML跟外部进行交互的时候,会进行大量的字符串操作,也会产生大量的重复字符串。 JDK开发组很早就注意到这个问题了,因此后来也产生了很多解决方案,最新的解决方案就是使用XX:+UseStringDeduplication参数。 -XX:+UseStringDeduplication 花最小力气去掉重复字符串的办法就是使用XX:+UseStringDeduplication参数,当在JVM启动时传递了这个参数的时候,JVM在做GC的同时会做重复字符串消除。GC的时候,JVM会检查内存中的所有对象,然后识别出重复的字符串对象并消除之。 是不是意味着只要给JVM传递XX:+UseStringDeduplication就

安装homebrew报错curl: (7) Failed to connect to raw.githubusercontent.com port 443: Operation

安装homebrew报错curl: (7) Failed to connect to raw.githubusercontent.com port 443: Operation

react native搭建环境,安装homebrew的时候,在终端输入 /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 提示: curl: (7) Failed to connect to raw.githubusercontent.com port 443: Operation 解决方法: 这个是stackoverflow的解决方法,英文的,我翻译了一下 我的翻译: 先在浏览器输入这个地址: https://raw.githubusercontent.com/Homebrew/install/master/install 看是否能打开,不能打开就是你网络有问题,不要问我哦。 能打开如下: 把这个网页保存名为brew_install.rb的文件,保存的位置你随便,只要自己能找到。 则在终端输入curl $ curl curl: try 'curl --help' or 'curl --manual' for more information 这样就没错,要是报错,那我就不知道了! 然后在终端进入存放这个文件的目录(这个不用我教吧),然后终端输入 ruby brew_install.rb 然后等安装homebrew吧! 作者:kangxx 链接:https://www.jianshu.com/p/68efabd2e32b 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Reference 、ReferenceQueue 详解

Reference 、ReferenceQueue 详解

ReferenceQueue 引用队列,在检测到适当的可到达性更改后,垃圾回收器将已注册的引用对象添加到该队列中 实现了一个队列的入队(enqueue)和出队(poll还有remove)操作,内部元素就是泛型的Reference,并且Queue的实现,是由Reference自身的链表结构( 单向循环链表 )所实现的。 ReferenceQueue名义上是一个队列,但实际内部并非有实际的存储结构,它的存储是依赖于内部节点之间的关系来表达。可以理解为queue是一个类似于链表的结构,这里的节点其实就是reference本身。可以理解为queue为一个链表的容器,其自己仅存储当前的head节点,而后面的节点由每个reference节点自己通过next来保持即可。 属性 head:始终保存当前队列中最新要被处理的节点,可以认为queue为一个后进先出的队列。当新的节点进入时,采取以下的逻辑: r.next = (head == null) ? r : head; head = r; 然后,在获取的时候,采取相应的逻辑: Reference<? extends T> r = head; if (r != null) { head = (r.next == r) ? null : r.next; // Unchecked due to the next field having a raw type in Reference r.queue = NULL; r.next = r; 方法 enqueue():待处理引用入队 boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */ synchronized (lock) { // Check that since getting the lock this reference hasn't already been // enqueued (and even then removed) ReferenceQueue<?> queue = r.queue; if ((queue == NULL) || (queue == ENQUEUED)) { return false; } assert queue == this; r.queue = ENQUEUED; r.next = (head == null) ? r : head; head = r; queueLength++; if (r instanceof FinalReference) { sun.misc.VM.addFinalRefCount(1); } lock.notifyAll(); // ① return true; } } ① lock.notifyAll(); 👈通知外部程序之前阻塞在当前队列之上的情况。( 即之前一直没有拿到待处理的对象,如ReferenceQueue的remove()方法 ) Reference java.lang.ref.Reference 为 软(soft)引用

联系我们

联系电话

4000-640-466

联系邮箱

service@f-li.cn

办公地址

上海黄浦区外滩源1号

谢谢,您的信息已成功发送。
请填写信息。