容器精华问答 如何进行跨机器的Container做Link?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了容器精华问答 如何进行跨机器的Container做Link?相关的知识,希望对你有一定的参考价值。

参考技术A

云计算的发展日新月异,新技术层出不穷,尤其容器技术自2013年Docker容器问世以来一路高歌猛进红遍大江南北,与虚拟机相比,容器更显优势,有着更轻量、更快捷、占用资源更少,业界也对容器技术有非常大需求,俨然成为了云计算的主流标准和趋势。今天,我们就一起来看看关于容器的精华问答吧。

1

Q:什么是容器?你为什么需要它们?

A: 容器是针对以下问题的解决方案:在切换运行环境后,如何保证软件能够可靠地运行?这种切换可能是从程序员的笔记本电脑到测试环境、从某个测试阶段部署到线上,也可能是从数据中心的某台物理机到私有云或者公有云上的某台虚拟机。

2

Q:Docker的创始人Solomon Hykes说过“你在Python2.7下测试,线上却运行着Python3,奇怪的事情就发生了;或者你依赖具体某个SSL版本的功能,但服务器上却安装着另外版本的SSL;你在Debian系统上进行了测试,生产环境却是Red Hat,那各种各样的奇怪的事情就会发生。”对于以上几个问题,容器是如何解决的呢?

A: 简单地说,一个容器包含了完整的运行时环境:一个应用、这个应用所需的全部依赖、类库、其他二进制文件、配置文件,它们统一被打入了一个包中。通过将应用平台和其依赖容器化,操作系统发行版本和其他基础环境造成的差异,都被抽象掉了。

3

Q:Docker容器的内存,硬盘,CPU等参数如何控制?

A: Docker容器基于Linux Container技术,LXC基于Linux内核cgroup机制,可以实现对内存、CPU的控制 。Docker 只依赖于Linux kernel 对 LXC 的支持,包括cgroup,namespace。换句话说,只要系统的Linux Kernel 支持 LXC, 打包在 Docker里的应用就可以跨Linux系统运行。

4

Q:虚拟机和容器有些类似,那么二者之间有什么区别呢?

A: 使用虚拟化技术时,可以被分发的文件包是一台虚拟机,它包含了整个操作系统和应用。一台运行着三个虚拟机的物理服务器,需要有一个管理虚拟机软件的中间层,以及运行在这个中间层之上的三个独立操作系统。

5

Q:如何进行跨机器的Container做Link ?

A: 官网给的是在同一台机器的Container之间做的Link,默认情况下不可能,躲藏在宿主后面的Container不拥有真实的IP,无法通过DNS解释得到IP。Container如果要跨机器通讯,通常有两种方式:

1. 端口映射: 把Container中监听的端口(比如80)映射到宿主机的49888端口, 然后就可以通过访问宿主机IP+ 映射端口(49888), 访问到Container中监听的端口。

2. 宿主机搭网桥,给每个Container分配一个IP,外部就可以直接访问该容器了。

---------------- --------------

福利

1、扫描添加我微信,备注“ 姓名+公司职位 ”,加入【 云计算学习交流群 】,和志同道合的朋友们共同打卡学习!

2、 公众号后台回复:白皮书,获取IDC最新数据白皮书整理资料!

推荐阅读:

真香,朕在看了!

并发编程精华问答| Java线程池使用时注意事项

一、Java线程池七个参数介绍
二、线程池中重要参数的配置
三、使用线程池遇到的坑
四、Java线程池使用时的注意事项


虽然线程池能大大提高服务器的并发性能,但使用它也会存在一定风险。与所有多线程应用程序一样,用线程池构建的应用程序容易产生各种并发问题,如对共享资源的竞争和死锁。此外,如果线程池本身的实现不健壮,或者没有合理地使用线程池,还容易导致与线程池有关的死锁、系统资源不足和线程泄漏等问题。


01

Java线程池七个参数介绍


public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

1、corePoolSize 线程池核心线程大小

        线程池中会维护一个最小的线程数量,即使这些线程处理空闲状态,他们也不会被销毁,除非设置了allowCoreThreadTimeOut。这里的最小线程数量即是corePoolSize。


2、maximumPoolSize 线程池最大线程数量

        一个任务被提交到线程池以后,首先会找有没有空闲存活线程,如果有则直接将任务交给这个空闲线程来执行,如果没有则会缓存到工作队列(后面会介绍)中,如果工作队列满了,才会创建一个新线程,然后从工作队列的头部取出一个任务交由新线程来处理,而将刚提交的任务放入工作队列尾部。线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制,这个数量即由maximunPoolSize指定


3、keepAliveTime 空闲线程存活时间

        一个线程如果处于空闲状态,并且当前的线程数量大于corePoolSize,那么在指定时间后,这个空闲线程会被销毁,这里的指定时间由keepAliveTime来设定。


4、unit 空闲线程存活时间单位

        keepAliveTime的计量单位。


5、workQueue 工作队列

        新任务被提交后,会先进入到此工作队列中,任务调度时再从队列中取出任务。jdk中提供了四种工作队列:

        - ArrayBlockingQueue基于数组的有界阻塞队列,按FIFO排序。新任务进来后,会放到该队列的队尾,有界的数组可以防止资源耗尽问题。当线程池中线程数量达到corePoolSize后,再有新任务进来,则会将任务放入该队列的队尾,等待被调度。如果队列已经是满的,则创建一个新线程,如果线程数量已经达到maxPoolSize,则会执行拒绝策略。

        - LinkedBlockingQuene基于链表的无界阻塞队列(其实最大容量为Interger.MAX),按照FIFO排序。由于该队列的近似无界性,当线程池中线程数量达到corePoolSize后,再有新任务进来,会一直存入该队列,而不会去创建新线程直到maxPoolSize,因此使用该工作队列时,参数maxPoolSize其实是不起作用的。

        - SynchronousQuene一个不缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务。也就是说新任务进来时,不会缓存,而是直接被调度执行该任务,如果没有可用线程,则创建新线程,如果线程数量达到maxPoolSize,则执行拒绝策略。

        - PriorityBlockingQueue具有优先级的无界阻塞队列,优先级通过参数Comparator实现


6、threadFactory 线程工厂

        创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等等。


7、handler 拒绝策略

        当工作队列中的任务已到达最大限制,并且线程池中的线程数量也达到最大限制,这时如果有新任务提交进来,该如何处理呢。这里的拒绝策略,就是解决这个问题的,jdk中提供了4种拒绝策略:

        - CallerRunsPolicy(用调用者所在线程来执行任务):该策略下,在调用者线程中直接执行被拒绝任务的run方法,除非线程池已经shutdown,则直接抛弃任务。

        - AbortPolicy(直接抛出异常,这是默认策略):该策略下,直接丢弃任务,并抛出RejectedExecutionException异常。

        - DiscardPolicy(直接丢弃任务):该策略下,直接丢弃任务,什么都不做。

        - DiscardOldestPolicy(丢弃阻塞队列中最靠前的任务,并执行当前任务):该策略下,抛弃进入队列最早的那个任务,然后尝试把这次拒绝的任务放入队列。



02

线程池中重要参数的配置


corePoolSize : 核心线程数量;

workQueue : 等待队列;

maximumPoolSize : 最大线程数量。

提交任务时,判断的顺序为 corePoolSize -> workQueue ->maximumPoolSize


- 当线程数小于核心线程数时,创建核心线程。

- 当线程大于等于核心线程数,且任务队列未满时,将任务放入队列。

- 当线程数大于核心线程数,且任务队列已满时,检查最大线程数是否已满,若未满,创建非核心线程,若满,根据拒绝策略抛出异常拒绝任务。



03

使用线程池遇到的问题(坑)


1、任务提交后长时间没有执行

        任务进入了队列,线程还在执行之前的任务。提交的任务还在排队等待执行中。

        本质原因是对线程和队列的优先级认识不深刻,有一种错觉以为是所有线程都忙的时候才进入任务队列。实际上相反,是队列满的时候才会新建线程(线程数大于core size时)。


2、线程执行任务中无故消失

        - 线程拒绝策略配置为CallerRunsPolicy、DiscardOldestPolicy、DiscardPolicy时 ,线程池满了不会抛出异常。建议将拒绝策略配置为AbortPolicy

        - 一般情况下,代码中只会去捕捉RuntimeException,如果抛出Error(比如内存溢出)则会导致线程退出,而异常信息又没有拿到。最佳的解决办法是给线程池设置UncaughtExceptionHandler



04

Java线程池使用时的注意事项


1、建议使用new ThreadPoolExecutor(...)的方式创建线程池

线程池的创建不应使用 Executors 去创建,而应该通过 ThreadPoolExecutor 创建,这样可以让读者更加明确地知道线程池的参数设置运行规则规避资源耗尽的风险,这一点在也阿里巴巴JAVA开发手册中也有明确要求。这一点不容小觑,曾有同学因为线程池使用不当导致生产的同一台机器上部署的多个应用都因无法创建线程池而出现故障。


2、合理设置线程数

- 线程池的工作线程数设置应根据实际情况配置,CPU密集型业务(搜索、排序等)CPU空闲时间较少,线程数不能设置太多。

- 如果是CPU密集型任务,就需要尽量压榨CPU,参考值可以设为 NCPU+1。

- 如果是IO密集型任务,参考值可以设置为2*NCPU。


3、设置能代表具体业务的线程名称

这样方便通过日志的线程名称识别所属业务。具体实现可以通过指定ThreadPoolExecutor的ThreadFactory参数。如使Spring提供的CustomizableThreadFactory






并发编程精华问答(八)| Java线程池使用时注意事项

END



来源 | 海兴



扫描二维码

获取更多精彩

海兴破颈记






以上是关于容器精华问答 如何进行跨机器的Container做Link?的主要内容,如果未能解决你的问题,请参考以下文章

markdown [export container]如何将docker容器导出到其他机器。 #docker

Hadoop精华问答 | Hadoop 和Spark有什么区别?

Mysql精华问答| 分库分表之后,ID主键及事务如何处理

Kafka精华问答 | Kafka的主要应用场景有哪些?

虚拟化精华问答 | 虚拟化的关键技术有哪些?

并发编程精华问答| Java线程池使用时注意事项