• 关于

    java 线程 恢复

    的搜索结果

回答

问题发生后,第一时间是快速保留问题现场供后面排查定位,然后尽快恢复服务。保留现场的具体操作:打印堆栈信息,命令行:jstack -l 'java进程PID'打印内存镜像,命令行:jmap -dump:format=b,file=hprof 'java进程PID'生成core文件,命令行:gcore 'java进程PID'保留gc日志文件保留业务日志文件查看JAVA堆内存运行分配:命令行:jstat -gcutil 'java进程PID' 1000完成以上操作后,尽快重启JAVA进程或回滚,恢复服务。当应用系统运行缓慢,页面加载时间变长,后台长时间无影响时,都可以参考以下归类的解决方法。绝大部分的JAVA程序运行时异常都是Full GC、OOM(java.lang.OutOfMemoryError)、线程过多。主要分这么几大类:持续发生Full GC,但是系统不抛出OOM错误堆内存溢出:java.lang.OutOfMemoryError:Java heap space线程过多:java.lang.OutOfMemoryError:unable to create new native threadJAVA进程退出CPU占用过高通常来说,可以用一些常用的命令行来打印堆栈、内存使用分配、打印内存镜像文件来分析,比如jstack、jstat、jmap等。但是某些时刻,还是需要引入更高阶的代码级分析工具(比如btrace)才能定位到具体原因。针对每一种问题,我会依据具体的case来详细说明解决方式。

昊蓝 2019-12-02 01:47:07 0 浏览量 回答数 0

回答

程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。 由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,一个处理器都只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都有一个独立的程序计数器,各个线程之间计数器互不影响,独立存储。称之为“线程私有”的内存。程序计数器内存区域是虚拟机中唯一没有规定OutOfMemoryError情况的区域。

星尘linger 2020-04-12 21:44:00 0 浏览量 回答数 0

回答

**Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域。**这些区域都有各自的用途,以及创建和销毁的时间,有些区域随着虚拟机进程的启动而存在,有些区域则是依赖线程的启动和结束而建立和销毁。Java 虚拟机所管理的内存被划分为如下几个区域: 不同虚拟机的运行时数据区可能略微有所不同,但都会遵从 Java 虚拟机规范, Java 虚拟机规范规定的区域分为以下 5 个部分: 程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成;Java 虚拟机栈(Java Virtual Machine Stacks):用于存储局部变量表、操作数栈、动态链接、方法出口等信息;本地方法栈(Native Method Stack):与虚拟机栈的作用是一样的,只不过虚拟机栈是服务 Java 方法的,而本地方法栈是为虚拟机调用 Native 方法服务的;Java 堆(Java Heap):Java 虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对象实例都在这里分配内存;方法区(Methed Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。 原文链接:https://thinkwon.blog.csdn.net/article/details/104390752

剑曼红尘 2020-03-11 11:23:16 0 浏览量 回答数 0

阿里云高校特惠,助力学生创业梦!0元体验,快速入门云计算!

学生动手场景应用,快速了解并掌握云服务器的各种新奇玩法!

问题

关于Android线程与ui绘制的问题

爵霸 2019-12-01 20:17:52 981 浏览量 回答数 1

问题

Java运行环境(Centos64位OpenJDK1.7)

烟圈206 2019-12-01 21:59:58 6170 浏览量 回答数 6

回答

一、Java内存分配     Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域存储不同类型的数据,这些区域的内存分配和销毁的时间也不同,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。根据《Java虚拟机规范(第2版)》的规定,Java虚拟机管理的内存包括五个运行时数据区域,如下图所示:      1、方法区     方法区(Method Area)是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息(包括类的名称、方法信息、成员变量信息)、常量、静态变量、以及编译器编译后的代码等数据。当方法区无法满足内存分配需求时,将抛出OutOfMemeryError异常。     运行时常量池(Runtime Constant Pool)是方法区的一部分,此区域会在两种情况下存储数据。     (1)class文件的常量池中的数据     class文件中的常量池用于存放编译期生成的各种字面值和常量,这部分内容在类被加载后存放到方法区的运行时常量池中。     字面值:private String name="zhangSan";private int age = 23+3;     常量:private final String TAG = "MainActivity";private final int age = 26;     (2)运行期间生成的常量     运行时常量池相对于class文件常量池的另外一个重要特征是具备动态性,Java语言并不要求常量一定只能在编译期产生,也就是并非预置入class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的便是String类的intern()方法。String str = "abc".intern();当运行时常量池中存在字符串"abc时,将该字符串的引用返回,赋值给str,否则创建字符串"abc",加入运行时常量池中,并返回引用赋值给str。既然运行时常量池是方法区的一部分,自然会受到方法区内存的限制,当常量池无法再申请到内存时会抛出OutOfMemoryError异常。 2、虚拟机栈     虚拟机栈是线程私有的内存空间,每个线程都有一个线程栈,每个方法被执行时都会创建一个栈帧,方法执行完成,栈帧弹出,线程运行结束,线程栈被回收。虚拟机栈就是Java中的方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,这个栈帧用于存储局部变量表、操作数栈、指向当前方法所属的类的运行时常量池的引用、方法返回地址等信息,每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。局部变量表用来存储方法中的局部变量,包括方法中声明的变量以及函数形参。对于基本数据类型的变量,则直接存储它的值,对于引用类型的变量,则存的是指向对象的引用。局部变量表的大小在编译器就可以确定其大小,并且在程序执行期间局部变量表的大小是不会改变的。程序中的所有计算过程都是在借助于操作数栈来完成的。指向运行时常量池的引用,因为在方法执行的过程中有可能需要用到类中的常量,所以必须要有一个引用指向当前方法所属的类的运行时常量池。方法返回地址,当一个方法执行完毕之后,要返回之前调用它的地方,因此在栈帧中必须保存一个方法返回地址。     在Java虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。 3、本地方法栈     本地方法栈也是线程私有的内存空间,本地方法栈与Java栈所发挥的作用是非常相似的,它们之间的区别不过是Java栈执行Java方法,本地方法栈执行的是本地方法,有的虚拟机直接把本地方法栈和虚拟机栈合二为一。 4、堆     Java堆是Java虚拟机所管理的内存中最大的一块,在虚拟机启动时创建,此内存区域的目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。从内存分配的角度来看,线程共享的Java堆中可能划分出多个线程私有的分配缓冲区(TLAB)。Java堆可以处于物理上不连续的内存空间,只要逻辑上连续即可,在实现上,既可以实现固定大小的,也可以是扩展的。如果堆中没有足够的内存分配给实例,并且堆也无法再拓展时,将会抛出OutOfMemeryError异常。     堆是运行时动态分配内存,对象在没有引用变量指向它的时候,才变成垃圾,但是仍然占着内存,在程序空闲的时候(没有工作线程运行,GC线程优先级最低)或者堆内存不足的时候(GC线程被触发),被垃圾回收器释放掉,由于要在运行时动态分配内存,存取速度较慢。 5、程序计数器     程序计数器的作用可以看做是当前线程所执行的字节码的行号指示。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为线程私有的内存。如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie方法,这个计数器值则为空。 二、Java内存回收     对于虚拟机栈空间,当方法调用结束后,基本类型变量、引用类型变量、形参占据的空间会被自动释放,但引用类型指向的对象在堆中,堆中的无用内存由垃圾回收线程回收,GC线程优先级最低,只有当没有工作线程存在时GC线程才会执行,或者堆空间不足时会自动触发GC线程工作。除了回收内存,GC线程还负责整理堆中的碎片。 1、四种引用类型     Java中的对象引用分为四种,强引用类型、软引用类型、弱引用类型、虚引用类型。Java中提供这四种引用类型主要有两个目的:第一是可以让程序员通过代码的方式决定某些对象的生命周期;第二是有利于JVM进行垃圾回收。使用软引用和弱引用可以有效的避免oom。软引用关联的对象,只有软引用关联时,才可回收,如果有强引用同时关联,不会回收对象占用的内存,弱引用也如此。 (1)强引用     强引用是使用最普遍的引用,类似Object obj = new Object()、String str = "hello"。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。 (2)软引用(SoftReference)     软引用是用来描述一些有用但并不是必需的对象,在Java中用java.lang.ref.SoftReference类来表示,如果内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用通常用于网页缓存、图片缓存,防止内存溢出,在内存充足的时候,缓存对象会一直存在,在内存不足的时候,缓存对象占用的内存会被垃圾收集器回收。使用示例: public void testSoftReference() { Map<String,SoftReference<Bitmap>> imagesCache = new HashMap<String,SoftReference<Bitmap>>(); Bitmap bitmap = getBitmap(); SoftReference<Bitmap> image1 = new SoftReference<Bitmap>(bitmap); imagesCache.put("image1",image1); SoftReference<Bitmap> result_SoftReference = imagesCache.get("image1"); Bitmap result_Bitmap = result_SoftReference .get(); } import java.lang.ref.SoftReference; public class Main { public static void main(String[] args) { SoftReference<String> sr = new SoftReference<String>(new String("hello")); System.out.println(sr.get()); } } (3)弱引用(WeakReference)     弱引用也是用来描述非必需对象的,但是它的强度比软引用更弱一些,在java中用java.lang.ref.WeakReference类来表示。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象,不过由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱引用可以用于:单例类持有一个activity引用时,会造成内存泄露,把activity声明为弱引用,在activity销毁后,垃圾收集器扫描到activity对象时,会回收activity对象的内存。使用示例: public class SingleTon1 { private static final SingleTon1 mInstance = null; private WeakReference<Context> mContext; private SingleTon1(WeakReference<Context> context) { mContext = context; } public static SingleTon1 getInstance(WeakReference<Context> context) { if (mInstance == null) { synchronized (SingleTon1.class) { if (mInstance == null) { mInstance = new SingleTon1(context); } } } return mInstance; } } public class MyActivity extents Activity { public void onCreate (Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); SingleTon1 singleTon1 = SingleTon1.getInstance(new WeakReference<Context>(this)); } }import java.lang.ref.WeakReference; public class Main { public static void main(String[] args) { WeakReference<String> sr = new WeakReference<String>(new String("hello")); System.out.println(sr.get()); System.gc(); //通知JVM的gc进行垃圾回收 System.out.println(sr.get()); } } 输出结果: hellonull     第二个输出结果是null,这说明只要JVM进行垃圾回收,被弱引用关联的对象必定会被回收掉。不过要注意的是,这里所说的被弱引用关联的对象是指只有弱引用与之关联,如果存在强引用同时与之关联,则进行垃圾回收时也不会回收该对象(软引用也是如此)。 (4)虚引用     虚引用和软引用、弱引用不同,它并不影响对象的生命周期,也无法通过虚引用来取得一个对象实例,在java中用java.lang.ref.PhantomReference类表示。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列(ReferenceQueue)联合使用,如下: import java.lang.ref.PhantomReference;import java.lang.ref.ReferenceQueue; public class Main { public static void main(String[] args) { ReferenceQueue<String> queue = new ReferenceQueue<String>(); PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue); System.out.println(pr.get()); } } 2、垃圾回收算法 (1)标记-清除(Mark-Sweep)    标记-清除(Mark-Sweep)算法,分为标记和清除两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。 标记-清除算法主要问题是:1、效率问题,标记和清除过程的效率很低2、空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集 (2)复制(Copying)算法     复制算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对其中的一块进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。 复制算法的主要问题是:1、复制算法将内存缩小为原来的一半,过于浪费2、对象存活率较高时就要执行较多的复制操作,造成频繁GC,效率将会变低 (3)标记-整理(Mark-Compact)     标记-整理算法的标记过程仍然与标记-清除算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存,这样连续的内存空间就比较多了。     如上图所示,所有存活的对象依次向左上角移动,(0,4)移动到(0,2),(1,0)移动到(0,3),依次类推,当所有的存活对象移动完成后,把剩余的所有空间清空,也就是清空(1,1)后的所有空间。 (4)分代回收(generational collection) 程序创建的大部分对象的生命周期都很短,只有一小部分对象的生命周期比较长,根据这样的规律,一般把Java堆分为Young Generation(新生代),Old Generation(老年代)和Permanent Generation(持久代),上面几种算法是通过分代回收混合在一起的,这样就可以根据各个年代的特点采用最适当的回收算法。 (1)新生代     在新生代中,有一个叫Eden Space的空间,主要是用来存放新生的对象,还有两个Survivor Spaces(from、to), 这两个区域大小相等,相当于copying算法中的两个区域,它们用来存放每次垃圾回收后存活下来的对象。在新生代中,垃圾回收一般用Copying的算法,速度快。     当新建对象无法放入eden区时,将触发minor collection(minorGC 是清理新生代的GC线程,eden的清理,from、to的清理都由MinorGC完成),将eden区与from区的存活对象复制到to区,经过一次垃圾回收,eden区和from区清空,to区中则紧密的存放着存活对象;当eden区再次满时,minor collection将eden区和to区的存活对象复制到from区,eden区和to区被清空,from区存放eden区和to区的存活对象,就这样from区和to区来回切换。如果进行minor collection的时候,发现to区放不下,则将eden区和from区的部分对象放入成熟代。另一方面,即使to区没有满,JVM依然会移动世代足够久远的对象到成熟代。 (2)成熟代     在成熟代中主要存放应用程序中生命周期长的内存对象,垃圾回收一般用mark-compact的算法,速度慢些,但减少内存要求。如果成熟代放满对象,无法从新生代移入新的对象,那么将触发major collection(major GC清理整合OldGen的内存空间)。 (3)永久代    在永久代中,主要用来放JVM自己的反射对象,比如类对象、方法对象、成员变量对象、构造方法对象等。     此外,垃圾回收一般是在程序空闲的时候(没有工作线程,GC线程优先级较低)或者堆内存不足的时候自动触发,也可以调用System.gc()主动的通知Java虚拟机进行垃圾回收,但这只是个建议,Java虚拟机不一定马上执行,启动时机的选择由JVM决定,并且取决于堆内存中Eden区是否可用 作者:喜六六 来源:CSDN 原文:https://blog.csdn.net/qq_29078329/article/details/78929457 版权声明:本文为博主原创文章,转载请附上博文链接!

auto_answer 2019-12-02 01:50:42 0 浏览量 回答数 0

回答

CountDownLatch 类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。

星尘linger 2020-04-12 22:07:31 0 浏览量 回答数 0

问题

Hystrix 是什么?【Java问答学堂】60期

剑曼红尘 2020-07-20 12:49:25 2 浏览量 回答数 1

回答

java中的sleep()和wait()的区别 对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。 sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。 在调用sleep()方法的过程中,线程不会释放对象锁。 而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备 获取对象锁进入运行状态。

剑曼红尘 2020-04-01 14:54:01 0 浏览量 回答数 0

回答

ThreadGroup概述在java中为了方便线程管理出现了线程组ThreadGroup的概念,每个ThreadGroup可以同时包含多个子线程和多个子线程组,在一个进程中线程组是以树形的方式存在,通常情况下根线程组是system。system线程组下是main线程组,默认情况下第一级应用自己的线程组是通过main线程组创建出来的。 public class ThreadGroupTest { public static void main(String[] args) throws InterruptedException { //主线程对应的线程组 printGroupInfo(Thread.currentThread());//线程组为main父线程组为system //新建线程,系统默认的线程组 Thread appThread = new Thread(()->{},"appThread"); printGroupInfo(appThread);//线程组为main父线程组为system //自定义线程组 ThreadGroup factoryGroup=new ThreadGroup("factory"); Thread workerThread=new Thread(factoryGroup,()->{},"worker"); printGroupInfo(workerThread);//线程组为factory,父线程组为main //设置父线程组 ThreadGroup deviceGroup=new ThreadGroup(factoryGroup,"device"); Thread pcThread=new Thread(deviceGroup,()->{},"pc"); printGroupInfo(pcThread);//线程组为device,父线程组为factory } static void printGroupInfo(Thread t) { ThreadGroup group = t.getThreadGroup(); System.out.println("thread " + t.getName() + " group name is "+ group.getName() + " max priority is " + group.getMaxPriority() + " thread count is " + group.activeCount() + " parent group is "+ (group.getParent()==null?null:group.getParent().getName())); ThreadGroup parent=group; do { ThreadGroup current = parent; parent = parent.getParent(); if (parent == null) { break; } System.out.println(current.getName() +" Group's parent group name is "+parent.getName()); } while (true); System.out.println("--------------------------"); } }ThreadGroup线程组的操作线程组信息的获取 public int activeCount(); // 获得当前线程组中线程数目, 包括可运行和不可运行的public int activeGroupCount(); //获得当前线程组中活动的子线程组的数目public int enumerate(Thread list[]); //列举当前线程组中的线程public int enumerate(ThreadGroup list[]); //列举当前线程组中的子线程组public final int getMaxPriority(); //获得当前线程组中最大优先级public final String getName(); //获得当前线程组的名字public final ThreadGroup getParent(); //获得当前线程组的父线程组public boolean parentOf(ThreadGroup g); //判断当前线程组是否为指定线程的父线程public boolean isDaemon(); //判断当前线程组中是否有监护线程public void list(); //列出当前线程组中所有线程和子线程名线程组的操作 public final void resume(); //使被挂起的当前组内的线程恢复到可运行状态public final void setDaemon (boolean daemon); //指定一个线程为当前线程组的监护线程public final void setMaxPriority(int pri); //设置当前线程组允许的最大优先级public final void stop();//终止当前线程组中所有线程public final void suspend(); //挂起当前线程组中所有线程public String toStrinng(); //将当前线程组转换为String类的对象public class ThreadGroupDemo { public static void main(String[] args) throws InterruptedException { // 创建5个线程,并入group里面进行管理 ThreadGroup threadGroup = new ThreadGroup("threadGroupTest1"); for (int i = 0; i < 5; i++) { Thread thread = new Thread(threadGroup,()->{ System.out.println("Thread Start " + Thread.currentThread().getName()); try { int value = (int)new Random((new Date()).getTime()).nextDouble()*100; System.out.printf("Thread %s doTask: %d\n", Thread.currentThread().getName(),value); TimeUnit.SECONDS.sleep(value); } catch (InterruptedException e) { System.out.printf("Thread %s: Interrupted\n", Thread.currentThread().getName()); return; } System.out.println("Thread end " + Thread.currentThread().getName()); }); thread.start(); TimeUnit.SECONDS.sleep(1); } //group信息 System.out.printf("Number of Threads: %d\n", threadGroup.activeCount()); System.out.printf("Information about the Thread Group\n"); threadGroup.list(); //复制group的thread信息 Thread[] threads = new Thread[threadGroup.activeCount()]; threadGroup.enumerate(threads); for (int i = 0; i < threadGroup.activeCount(); i++) { System.out.printf("Thread %s: %s\n", threads[i].getName(),threads[i].getState()); } //等待结束 while (threadGroup.activeCount() > 9) { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } //中断group中的线程 threadGroup.interrupt(); } }

auto_answer 2019-12-02 01:49:32 0 浏览量 回答数 0

问题

云数据库 Memcache ,服务器等待连接太多,是怎么回事呢?

customer 2019-12-01 19:44:25 1784 浏览量 回答数 3

问题

对症下药:Tomcat停机过程分析与线程处理方法

驻云科技 2019-12-01 21:08:52 43219 浏览量 回答数 3

回答

(看标签只有java和mysql的,就挑出来说了,其他方面的我也没啥可以说的...)运行时发现死锁:java进程用jstack打出堆栈看看有没有就知道有没有死锁mysql innodb的话,show engine innodb status 看看锁持有情况也能看的出来有没有死锁怎么处理:首先肯定优先恢复服务。该回滚版本的回滚版本,该杀的杀,该重启的重启。java进程:看jstack的堆栈找到阻塞的位置,然后对着代码分析mysql:show engine innodb status已经可以看的到sql以及等待什么锁 etc.,对着分析就好,看不到sql的话可以用thread id去查mysql 的bin log查到具体执行的sql。避免死锁:我是没什么好的办法,只能说所有涉及到多线程操作的地方都要提高警惕,涉及到资源竞争、加锁的地方都要提高警惕,分析清楚该逻辑会不会产生死锁。条件允许的情况下可以做并发测试。

蛮大人123 2019-12-02 01:54:16 0 浏览量 回答数 0

问题

Redis 的持久化有哪几种方式?【Java问答】35期

剑曼红尘 2020-06-11 09:27:45 4 浏览量 回答数 1

问题

用HttpClient做数据采集时的阻塞问题

蛮大人123 2019-12-01 20:02:33 1168 浏览量 回答数 1

回答

" 1.首先,明确两个问题,synchronized 一般不是跟AtomicXX类进行比较,更多的是跟ReentrantLock这个类进行比较,网上关于这2者的比较很多,可以自行google之。 2.问题中关于无锁跟有锁的疑问,测试代码b中的代码是有问题的, 对于方法a,synchronized代码块来说,锁被第一个进来的线程持有后,后续线程请求获取锁会被阻塞挂起,直到前面一个线程释放锁,后续的线程会恢复执行,由于锁的存在,20个请求类似于顺序执行,这一层由jvm调度对于方法b,cas操作是非阻塞的,方法中的while循环其实是一直在执行(不断尝试进行cas操作),而我们知道,死循环是会消耗cpu资源的,并发数越多,线程越多,此处的cas操作越多,必然导致cpu使用率飙升,方法b中的代码由jmeter测试的时候理论上来说应该一直由20个活跃的工作线程存在,cpu与线程模型是另外一个话题,线程数的调优是jvm一个比较高级的话题,感兴趣可以自行google之说说ReentrantLock与synchronized:通常情况下在高并发下,ReentrantLock比synchronized拥有更好的性能,而且ReentrantLock提供来一些synchronized并不提供的功能(锁超时自动放弃等),示例代码中可以减少sleep的时间,从而模拟更短停顿,更高的并发,500ms对于人来说很短,对于cpu来说基本就是天文数字了,基本用“慢如蜗牛”来形容也不为过,修改类一下示例代码: package com.gzs.learn.springboot; import java.util.LinkedList; import java.util.Random; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.ReentrantLock; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller @RequestMapping("/bench/") public class BenchController { private Random random = new Random(); private static Object[] lockObj; private static AtomicReference<Integer>[] locks; private static ReentrantLock[] reentrantLocks; static { lockObj = new Object[100]; for (int i = 0; i < lockObj.length; i++) { lockObj[i] = new Object(); } locks = new AtomicReference[100]; for (int i = 0; i < locks.length; i++) { locks[i] = new AtomicReference<Integer>(null); } reentrantLocks = new ReentrantLock[100]; for (int i = 0; i < reentrantLocks.length; i++) { reentrantLocks[i] = new ReentrantLock(); } } @RequestMapping("a/{id}") @ResponseBody public long a(@PathVariable("id") int id) throws Exception { long start = System.currentTimeMillis(); int index = id % 100; long inner = 0; synchronized (lockObj[index]) { inner = test(); } long result = System.currentTimeMillis() - start; System.out.println("all: " + result + " inner: " + inner); return result; } @RequestMapping("b/{id}") @ResponseBody public long b(@PathVariable("id") int id) throws Exception { long start = System.currentTimeMillis(); id = id % 100; AtomicReference<Integer> lock = locks[id]; int b = 0; while (!lock.compareAndSet(null, id)) { b = 1 + 1; } long inner = test(); boolean flag = lock.compareAndSet(id, null); long result = System.currentTimeMillis() - start; System.out.println("all: " + result + " inner: " + inner + " flag:" + flag); System.out.println(b); return result; } @RequestMapping("c/{id}") @ResponseBody public long c(@PathVariable("id") int id) throws Exception { long start = System.currentTimeMillis(); id = id % 100; ReentrantLock lock = reentrantLocks[id]; lock.lock(); long inner = test(); lock.unlock(); long result = System.currentTimeMillis() - start; System.out.println("all: " + result + " inner: " + inner); return result; } public long test() throws Exception { long innerstart = System.currentTimeMillis(); Thread.sleep(0, 100); // Thread.sleep(500); System.out.println(System.currentTimeMillis() - innerstart); return System.currentTimeMillis() - innerstart; } } 方法c是用ReentrantLock实现的,绝大多少情况下ReentrantLock比synchronized高效juc(java.util.concurrent)中的核心类Aqs(AbstractQueuedSynchronizer)是一个基于队列的 并发包,默认线程在锁竞争(自旋)超过1000纳秒的时候会被park(挂起操作),从而减少cpu频繁的线程切换,可以尝试调整方法c中的sleep的时间参数。测试方法,本机没有装jmeter,用apache ab做的测试,测试命令: ab -n 100 -c 20 http://localhost:8080/bench/a/10"

因为相信,所以看见。 2020-05-27 17:33:13 0 浏览量 回答数 0

回答

是不是发生在应用重载的时候?在实际环境中不要让tomcat重载,有修改程序重启tomcat谢谢!我仔细看了一下服务的异常,感觉是内存环节的问题于是,我在启动参数中增加了jvm的内存配置项,目前正在观察,如果不在报错,则,有可能就是内存线程缺乏有效收集而造成的线程异常。即便服务恢复正常,我也将连续观察,看是否重复出现此异常。 我没懂你的意思。 1.这是上线的服务,所以,不会发生开发环节中的重载服务。 2.没有修改服务。我不记得以前是否遇到过同样的问题,因为,时间太久,开发笔记一直都没有整理。 希望遇到同样问题的高手出来指点一下。我怀疑是jar包太旧 /--Encapsulatedexception------------\java.lang.NullPointerException    atorg.apache.catalina.loader.WebappClassLoader.findResourceInternal(WebappClassLoader.java:2892)    atorg.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2753)    atorg.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1148)    atorg.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1643)    atorg.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521)    atcom.opensymphony.xwork2.conversion.impl.XWorkConverter.lookup(XWorkConverter.java:375)    atcom.opensymphony.xwork2.conversion.impl.XWorkConverter.lookup(XWorkConverter.java:401)    atcom.opensymphony.xwork2.conversion.impl.XWorkConverter.convertValue(XWorkConverter.java:310)    atcom.opensymphony.xwork2.ognl.OgnlTypeConverterWrapper.convertValue(OgnlTypeConverterWrapper.java:39)    atognl.OgnlRuntime.getConvertedType(OgnlRuntime.java:1060)    atognl.OgnlRuntime.getConvertedTypes(OgnlRuntime.java:1077)    atognl.OgnlRuntime.getConvertedMethodAndArgs(OgnlRuntime.java:1103)    atognl.OgnlRuntime.getAppropriateMethod(OgnlRuntime.java:1189)    atognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1203)    atognl.OgnlRuntime.setMethodValue(OgnlRuntime.java:1474)    atognl.ObjectPropertyAccessor.setPossibleProperty(ObjectPropertyAccessor.java:85)    atognl.ObjectPropertyAccessor.setProperty(ObjectPropertyAccessor.java:162)    atcom.opensymphony.xwork2.ognl.accessor.ObjectAccessor.setProperty(ObjectAccessor.java:27)    atognl.OgnlRuntime.setProperty(OgnlRuntime.java:2245)    atognl.ASTProperty.setValueBody(ASTProperty.java:127)    atognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:220)    atognl.SimpleNode.setValue(SimpleNode.java:301)    atognl.ASTChain.setValueBody(ASTChain.java:227)    atognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:220)    atognl.SimpleNode.setValue(SimpleNode.java:301)    atognl.Ognl.setValue(Ognl.java:737)    atcom.opensymphony.xwork2.ognl.OgnlUtil.setValue(OgnlUtil.java:209)    atcom.opensymphony.xwork2.ognl.OgnlValueStack.trySetValue(OgnlValueStack.java:173)    atcom.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:160)    atcom.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:151)    atcom.opensymphony.xwork2.interceptor.ParametersInterceptor.setParameters(ParametersInterceptor.java:288)    atcom.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:199)    atcom.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:207)    atcom.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:190)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atorg.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atorg.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:94)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atorg.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:243)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atorg.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:270)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)    atcom.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:176)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atorg.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:190)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atorg.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)    atorg.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:498)    atorg.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)    atorg.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)    atorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)    atorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)    atorg.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)    atorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)    atorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)    atorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)    atorg.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)    atorg.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)    atorg.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:498)    atorg.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)    atorg.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)    atorg.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)    atorg.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)    atorg.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:394)    atorg.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)    atorg.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)    atorg.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)    atorg.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)    atjava.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)    atjava.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)    atjava.lang.Thread.run(Thread.java:619) 继续报错,有没有高手能帮我看看? com.opensymphony.xwork2.util.logging.commons.CommonsLoggerwarn警告:Errorsettingexpression'class['classLoader']['resources']'withvalue'[Ljava.lang.String;@1cdc866'ognl.MethodFailedException:Method"setResources"failedforobjectWebappClassLoader context:/ delegate:false repositories:  /WEB-INF/classes/---------->ParentClassloader:org.apache.catalina.loader.StandardClassLoader@1c282a1 [java.lang.NoSuchMethodException:org.apache.catalina.loader.WebappClassLoader.setResources([Ljava.lang.String;)]    atognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1285)    atognl.OgnlRuntime.setMethodValue(OgnlRuntime.java:1474)    atognl.ObjectPropertyAccessor.setPossibleProperty(ObjectPropertyAccessor.java:85)    atognl.ObjectPropertyAccessor.setProperty(ObjectPropertyAccessor.java:162)    atcom.opensymphony.xwork2.ognl.accessor.ObjectAccessor.setProperty(ObjectAccessor.java:27)    atognl.OgnlRuntime.setProperty(OgnlRuntime.java:2245)    atognl.ASTProperty.setValueBody(ASTProperty.java:127)    atognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:220)    atognl.SimpleNode.setValue(SimpleNode.java:301)    atognl.ASTChain.setValueBody(ASTChain.java:227)    atognl.SimpleNode.evaluateSetValueBody(SimpleNode.java:220)    atognl.SimpleNode.setValue(SimpleNode.java:301)    atognl.Ognl.setValue(Ognl.java:737)    atcom.opensymphony.xwork2.ognl.OgnlUtil.setValue(OgnlUtil.java:209)    atcom.opensymphony.xwork2.ognl.OgnlValueStack.trySetValue(OgnlValueStack.java:173)    atcom.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:160)    atcom.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:151)    atcom.opensymphony.xwork2.interceptor.ParametersInterceptor.setParameters(ParametersInterceptor.java:288)    atcom.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:199)    atcom.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:207)    atcom.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:190)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atorg.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atorg.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:94)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atorg.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:243)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atorg.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:270)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)    atcom.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:176)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atorg.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:190)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atcom.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)    atcom.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)    atorg.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)    atorg.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:498)    atorg.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)    atorg.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)    atorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)    atorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)    atorg.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)    atorg.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)    atorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)    atorg.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)    atorg.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)    atorg.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)    atorg.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:498)    atorg.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)    atorg.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)    atorg.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)    atorg.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)    atorg.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:394)    atorg.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)    atorg.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)    atorg.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)    atorg.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)    atjava.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)    atjava.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)    atjava.lang.Thread.run(Thread.java:619)Causedby:java.lang.NoSuchMethodException:org.apache.catalina.loader.WebappClassLoader.setResources([Ljava.lang.String;)    atognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1226)    ...75more 死锁请具体阐述 换druid试试,我之前用c3p0报过这个错误,你这个项目用的是DBCP吧回复 @netjourney:所以我还是建议不要用c3p0 @wang_liran非常感谢,是同样的bug回复 @netjourney:貌似据说这是C3p0的一个bug,http://weifly.iteye.com/blog/1227182,参考一下谢谢答复这个项目用的是c3p0。我也认为是这个连接池包造成的bug报错。后来,开打了jvm和一些辅助设置,并提高了内存设置,服务器在报c3p0异常的时候,服务并没有崩溃。所以,至少先解决了c3p0异常导致服务崩溃的情况。 连接池线程数太小吧?没错,确实是线程数太少,并且,jvm配置内存太小造成的。此问题已经从很小方面解决了。但tomcat服务还有配置问题

爱吃鱼的程序员 2020-06-20 19:30:54 0 浏览量 回答数 0

问题

对症下药:Tomcat停机过程分析与线程处理方法

驻云科技 2019-12-01 21:36:46 4001 浏览量 回答数 0

问题

了解什么是 Redis 的雪崩、穿透和击穿?Redis 崩溃之后会怎么样?【Java问答】37期

剑曼红尘 2020-06-17 13:17:18 31 浏览量 回答数 1

问题

生产环境中的 Redis 是怎么部署的?【Java问答】40期

剑曼红尘 2020-06-18 08:28:34 33 浏览量 回答数 1

问题

apache和tomcat整合问题? 报错

优选2 2020-06-04 18:05:07 3 浏览量 回答数 1

问题

apache和tomcat整合问题? 400 报错

爱吃鱼的程序员 2020-06-02 12:01:00 0 浏览量 回答数 1

问题

apache和tomcat整合问题? 400 报错

爱吃鱼的程序员 2020-05-29 17:55:50 0 浏览量 回答数 1

问题

「运维」和「研发」,谁是故障的始作俑者?

sunny夏筱 2019-12-01 21:36:00 5551 浏览量 回答数 7

问题

【教程免费下载】Redis开发与运维

知与谁同 2019-12-01 22:07:46 2741 浏览量 回答数 2

回答

转自:阿飞的博客 一、数据库技术选型的思考维度 我们做选型的时候首先要问: 谁选型?是负责采购的同学、 DBA 还是业务研发? 如果选型的是采购的同学,他们更注重成本,包括存储方式、网络需求等。 如果选型的是 DBA 同学,他们关心的: ① 运维成本 首先是运维成本,包括监控告警是否完善、是否有备份恢复机制、升级和迁移的成本是否高、社区是否稳定、是否方便调优、排障是否简易等; ② 稳定性 其次,DBA会关注稳定性,包括是否支持数据多副本、服务高可用、多写多活等; ③ 性能 第三是性能,包括延迟、QPS 以及是否支持更高级的分级存储功能等; ④ 拓展性 第四是扩展性,如果业务的需求不确定,是否容易横向扩展和纵向扩容; ⑤ 安全 最后是安全,需要符合审计要求,不容易出现 SQL 注入或拖库情况。 ⑥ 其他 除了采购和 DBA之外,后台应用研发的同学同样会关注稳定性、性能、扩展性等问题,同时也非常关注数据库接口是否便于开发,是否便于修改数据库 schema 等问题。 接下来我们来看一下爱奇艺使用的数据库类型: MySQL,互联网业务必备系统; TiDB,爱奇艺的 TiDB 实践会有另外的具体介绍; Redis,KV 数据库,互联网公司标配; Couchbase,这个在爱奇艺用得比较多,但国内互联网公司用得比较少,接下来的部分会详细说明; 其他,比如 MongoDB、图数据库、自研 KV 数据库 HiKV 等; 大数据分析相关系统,比如 Hive、Impala 等等。 可以看到爱奇艺的数据库种类还是很多的,这会造成业务开发的同学可能不太清楚在他的业务场景下应该选用哪种数据库系统。 那么,我们先对这些数据库按照接口(SQL、NoSQL)和面向的业务场景(OLTP、OLAP)这两位维度进行一个简单非严谨的分类。 下图中,左上角是面向 OLTP、支持 SQL 的这样一类系统,例如 MySQL,一般支持事务不同的隔离级别, QPS 要求比较高,延时比较低,主要用于交易信息和关键数据的存储,比如订单、VIP 信息等。 左下角是 NoSQL 数据库,是一类针对特殊场景做优化的系统,schema 一般比较简单,吞吐量较高、延迟较低,一般用作缓存或者 KV 数据库。 整个右侧都是 OLAP 的大数据分析系统,包括 Clickhouse、Impala等,一般支持SQL、不支持事务,扩展性比较好,可以通过加机器增加数据的存储量,响应延迟较长。 还有一类数据库是比较中立的,在数据量比较小的时候性能比较好,在数据量较大或复杂查询的时候性能也不差,一般通过不同的存储引擎和查询引擎来满足不同的业务需求,我们把它叫做 HTAP,TiDB 就是这样一种数据库。 二、iQIYI对数据库的优化与完善 前面我们提到了很多种的数据库,那么接下来就和大家介绍一下在爱奇艺我们是怎么使用这些数据库的。 1、MySQL在爱奇艺的使用 ① MySQL 首先是 MySQL。MySQL 基本使用方式是 master-slave + 半同步,支持每周全备+每日增量备份。我们做了一些基本功能的增强,首先是增强了数据恢复工具 Xtrabackup 的性能。 之前遇到一个情况,我们有一个全量库是 300G 数据,增量库每天 70G 数据,总数据量 700G 左右。我们当时只需要恢复一个表的数据,但该工具不支持单表恢复,且整库恢复需要 5 个小时。 针对这个情况我们具体排查了原因,发现在数据恢复的过程中需要进行多次写盘的 IO 操作并且有很多串行操作,所以我们做了一些优化。例如删减过程中的一些写盘操作,减少落盘并将数据处理并行化,优化后整库恢复耗时减少到 100 分钟,而且可以直接恢复单表数据。 然后是适配 DDL 和 DML 工具到内部系统,gh-ostt 和 oak-online-alter-table 在数据量大的时候会造成 master-slave 延时,所以我们在使用工具的时候也增加了延时上的考虑,实时探测Master-Slave 库之间延时的情况,如果延时较大会暂停工具的使用,恢复到正常水平再继续。 ② MySQL高可用 第二是 MySQL 高可用。Master-slave 加上半同步这种高可用方式不太完善,所以我们参照了 MHA 并进行了改动,采用 master + agent 的方式。Agent 在每一个物理机上部署,可以监控这个物理机上的所有实例的状态,周期性地向 master 发送心跳,Master 会实时监测各个Agent的状态。 如果 MySQL故障,会启动 Binlog 补偿机制,并切换访问域名完成 failover。考虑到数据库跨机房跨地区部署的情况,MHA 的 master 我们也做了高可用设计,众多 master 会通过 raft 组成一个 raft group,类似 TiDB 的 PD 模块。目前 MySQL failover 策略支持三种方式:同机房、同地域跨机房以及跨地域。 ③ MySQL拓展能力 第三是提高MySQL扩展能力,以提供更大容量的数据存储。扩展方式有 SDK,例如开源的 ShardingSphere,在爱奇艺的使用也比较广泛。另外就是 Proxy,开源的就更多了。但是 SDK 和 Proxy 使用的问题是支持的 SQL 语句简单,扩容难度大,依赖较多且运维复杂,所以部分业务已经迁移至 TiDB。 ④ 审计 第四是审计。我们在 MySQL 上做了一个插件获取全量 SQL 操作,后端打到 Kafka,下游再接入包括 Clickhouse 等目标端进行 SQL 统计分析。除此之外还有安全策略,包括主动探索是否有 SQL 注入及是否存在拖库情况等,并触发对应的告警。 MySQL 审计插件最大的问题是如何降低对 MySQL 性能的影响,对此我们进行了一些测试,发现使用 General Log 对性能损耗较大,有 10%~20% 的降低。 于是我们通过接口来获取 MySQL 插件里的监控项,再把监控项放到 buffer 里边,用两级的 RingBuffer 来保证数据的写入不会有锁资源竞争。在这个插件里再启动一个线程,从 RingBuffer 里读取数据并把数据打包写到 FIFO 管道里。 我们在每台 MySQL 的物理机里再启动一个 Agent,从管道里阻塞地读取数据发至 Kafka。优化后我们再次进行压测,在每台机器上有 15 万的更新、删除或插入操作下不会丢失数据,性能损耗一般情况下小于 2%。 目前已经在公司内部的集群上线了一年时间,运行比较稳定,上线和下线对业务没有影响。 ⑤ 分级存储 第五是分级存储。MySQL 里会存一些过程性的数据,即只需要读写最近一段时间存入的数据,过段时间这些数据就不需要了,需要进行定时清理。 分级存储就是在 MySQL 之上又用了其他存储方式,例如 TiDB 或其他 TokuDB,两者之间可以进行数据自动搬迁和自动归档,同时前端通过 SDK + Proxy 来做统一的访问入口。这样一来,业务的开发同学只需要将数据存入 MySQL 里,读取时可能从后端接入的任意数据库读出。这种方式目前只是过渡使用,之后会根据 TiDB 的特性进行逐步迁移。 Redis在爱奇艺的使用 接下来是 Redis。Redis 也是使用 master - slave 这种方式,由于网络的复杂性我们对 Sentinel 的部署进行了一些特殊配置,在多机房的情况下每个机房配置一定数量 Sentinel 来避免脑裂。 备份恢复方面介绍一个我们的特殊场景,虽然 Redis 是一个缓存,但我们发现不少的业务同学会把它当做一个 KVDB 来使用,在某些情况下会造成数据的丢失。 所以我们做了一个 Redis 实时备份功能,启动一个进程伪装成 Redis 的 Slave 实时获取数据,再放到后端的 KV 存储里,例如 ScyllaDB,如果要恢复就可以从 ScyllaDB 里把数据拉出来。 我们在用 Redis 时最大的痛点就是它对网络的延迟或抖动非常敏感。如有抖动造成 Redis Master 超时,会由 Sentinel 重新选出一个新的节点成为 Master,再把该节点上的数据同步到所有 Slave 上,此过程中数据会放在 Master 节点的 Buffer 里,如果写入的 QPS 很高会造成 Buffer 满溢。如果 Buffer 满后 RDB 文件还没有拷贝过去,重建过程就会失败。 基于这种情况,我们对 Redis 告警做了自动化优化,如有大量 master - slave 重建失败,我们会动态调整一些参数,例如把 Buffer 临时调大等, 此外我们还做了 Redis 集群的自动扩缩容功能。 我们在做 Redis 开发时如果是 Java 语言都会用到 Jedis。用 Jedis 访问客户端分片的 Redis 集群,如果某个分片发生了故障或者 failover,Jedis 就会对所有后端的分片重建连接。如果某一分片发生问题,整个 Redis 的访问性能和 QPS 会大幅降低。针对这个情况我们优化了 Jedis,如果某个分片发生故障,就只针对这个分片进行重建。 在业务访问 Redis 时我们会对 Master 绑定一个读写域名,多个从库绑定读域名。但如果我们进行 Master failover,会将读写域名从某旧 Master 解绑,再绑定到新 Master 节点上。 DNS 本身有一个超时时间,所以数据库做完 failover 后业务程序里没有立刻获取到新的 Master 节点的 IP的话,有可能还会连到原来的机器上,造成访问失败。 我们的解决方法是把 DNS 的 TTL 缩短,但对 DNS 服务又会造成很大的压力,所以我们在 SDK 上提供 Redis 的名字服务 RNS,RNS 从 Sentinel 里获取集群的拓扑和拓扑的变化情况,如果集群 failover,Sentinel 会接到通知,客户端就可以通过 RNS 来获取新的 Master 节点的 IP 地址。我们去掉域名,通过 IP 地址来访问整个集群,屏蔽了 DNS 的超时,缩短了故障的恢复时间。 SDK 上还做了一些功能,例如 Load Balance 以及故障检测,比如某个节点延时较高的话会被临时熔断等。 客户端分片的方式会造成 Redis 的扩容非常痛苦,如果客户端已经进行了一定量的分片,之后再增加就会非常艰难。 Redis 在 3.0 版本后会提供 Redis Cluster,因为功能受限在爱奇艺应用的不是很多,例如不支持显示跨 DC 部署和访问,读写只在主库上等。 我们某些业务场景下会使用 Redis 集群,例如数据库访问只发生在本 DC,我们会在 DC 内部进行 Cluster 部署。 但有些业务在使用的过程中还是想做 failover,如果集群故障可以切换到其他集群。根据这种情况我们做了一个 Proxy,读写都通过它来进行。写入数据时 Proxy 会做一个旁路,把新增的数据写在 Kafka 里,后台启用同步程序再把 Kafka 里的数据同步到其他集群,但存在一些限制,比如我们没有做冲突检测,所以集群间数据需要业务的同学做单元化。线上环境的Redis Cluster 集群间场景跨 DC 同步 需要 50 毫秒左右的时间。 2、Couchbase在爱奇艺的使用 Redis 虽然提供 Cluster 这种部署方式,但存在一些问题。所以数据量较大的时候(经验是 160G),就不推荐 Redis 了,而是采用另一种存储方式 Couchbase。 Couchbase 在国内互联网公司用的比较少,一开始我们是把他当做一个 Memcached 来使用的,即纯粹的缓存系统。 但其实它性能还是比较强大的,是一个分布式高性能的 KV 系统,支持多种存储引擎 (bucket)。第一种是 Memcached bucket,使用方式和 Memcached 一样为 KV 存储,不支持数据持久化也没有数据副本,如果节点故障会丢失数据; 第二种是 Couchbase bucket,支持数据持久化,使用 Json 写入,有副本,我们一般会在线上配置两个副本,如果新加节点会对数据进行 rebalance,爱奇艺使用的一般是 Couchbase bucket 这种配置。 Couchbase 数据的分布如下图,数据写入时在客户端上会先进行一次哈希运算,运算完后会定位 Key 在哪一个 vBucket (相当于数据库里的某个分片)。之后客户端会根据 Cluster Map 发送信息至对应的服务端,客户端的 Cluster Map 保存的是 vBucket 和服务器的映射关系,在服务端数据迁移的过程中客户端的 Cluster Map 映射关系会动态更新,因此客户端对于服务端的 failover 操作不需要做特殊处理,但可能在 rebalance 过程中会有短暂的超时,导致的告警对业务影响不大。 Couchbase 在爱奇艺应用比较早,2012 年还没有 Redis Cluster 的时候就开始使用了。集群管理使用 erlang 语言开发,最大功能是进行集群间的复制,提供多种复制方式:单向、双向、星型、环式、链式等。 爱奇艺从最初的 1.8 版本使用到如今的 5.0 版本,正在调研的 6.0,中间也遇到了很多坑,例如 NTP 时间配置出错会导致崩溃,如果每个集群对外 XDCR 并发过高导致不稳定,同步方向变更会导致数据丢失等等,我们通过运维和一些外部工具来进行规避。 Couchbase 的集群是独立集群,集群间的数据同步通过 XDCR,我们一般配置为双向同步。对于业务来说,如果 Cluster 1 写入, Cluster 2 不写入,正常情况下客户端会写 Cluster 1。如果 Cluster 1 有故障,我们提供了一个 Java SDK,可以在配置中心把写入更改到 Cluster 2,把原来到 Cluster 1 的连接逐步断掉再与Cluster 2 新建连接。这种集群 failover 的过程对于客户端来说是相对透明和无感的。 3、爱奇艺自研数据库HiKV的使用 Couchbase 虽然性能非常高,并且数据的存储可以超过内存。但是,如果数据量超过内存 75% 这个阈值,性能就会下降地特别快。在爱奇艺,我们会把数据量控制在可用内存的范围之内,当做内存数据库使用。但是它的成本非常高,所以我们后面又开发了一个新的数据库—— HiKV。 开发 HiKV 的目的是为了把一些对性能要求没那么高的 Couchbase 应用迁移到 HiKV 上。HiKV 基于开源系统 ScyllaDB,主要使用了其分布式数据库的管理功能,增加了单机存储引擎 HiKV。 ScyllaDB 比较吸引人的是它宣称性能高于 Cassandra 十倍,又完全兼容 Cassandra 接口,设计基本一致,可以视为 C++ 版 Cassandra 系统。 ScyllaDB 性能的提升主要是使用了一些新的技术框架,例如 C++ 异步框架 seastar,主要原理是在j每台物理机的核上会 attach 一个应用线程,每个核上有自己独立的内存、网络、IO 资源,核与核之间没有数据共享但可以通信,其最大的好处是内存访问无锁,没有冲突过程。 当一个数据读或写到达 ScyllaDB 的 server 时,会按照哈希算法来判断请求的 Key 是否是该线程需要处理的,如果是则本线程处理,否则会转发到对应线程上去。 除此之外,它还支持多副本、多数据中心、多写多活,功能比较强大。 在爱奇艺,我们基于 SSD 做了一个 KV 存储引擎。Key 放在内存里,Value 放在盘上的文件里,我们在读和写文件时,只需要在内存索引里定位,再进行一次盘的 IO 开销就可以把数据读出来,相比 ScyllaDB 原本基于 LSM Tree 的存储引擎方式对 IO 的开销较少。 索引数据全部放在内存中,如果索引长度较长会限制单机可存储的数据量,于是我们通过开发定长的内存分布器,对于比较长的 Key 做摘要缩短长度至 20 字节,采用红黑树索引,限制每条记录在内存里的索引长度至为 64 字节。内存数据要定期做 checkpoint,客户端要做限流、熔断等。 HiKV 目前在爱奇艺应用范围比较大,截至目前已经替换了 30% 的 Couchbase,有效地降低了存储成本。 4、爱奇艺的数据库运维管理 爱奇艺数据库种类较多,如何高效地运维和管理这些数据库也是经历了不同的阶段。 最初我们通过 DBA 写脚本的方式管理,如果脚本出问题就找 DBA,导致了 DBA 特别忙碌。 第二个阶段我们考虑让大家自己去查问题的答案,于是在内部构建了一个私有云,通过 Web 的方式展示数据库运行状态,让业务的同学可以自己去申请集群,一些简单的操作也可以通过自服务平台实现,解放了 DBA。一些需要人工处理的大型运维操作经常会造成一些人为故障,敲错参数造成数据丢失等。 于是在第三个阶段我们把运维操作 Web 化,通过网页点击可以进行 90% 的操作。 第四个阶段让经验丰富的 DBA 把自身经验变成一些工具,比如有业务同学说 MySQL master-slave 延时了,DBA 会通过一系列操作排查问题。现在我们把这些操作串起来形成一套工具,出问题时业务的同学可以自己通过网页上的一键诊断工具去排查,自助进行处理。 除此之外我们还会定期做预警检查,对业务集群里潜在的问题进行预警报告;开发智能客服,回答问题;通过监控的数据对实例打标签,进行削峰填谷地智能调度,提高资源利用率。 三、不同场景下数据库选型建议 1、实用数据库选型树 最后来说一些具体数据库选型建议。这是 DBA 和业务一起,通过经验得出来的一些结论。 对于关系型数据库的选型来说,可以从数据量和扩展性两个维度考虑,再根据数据库有没有冷备、要不要使用 Toku 存储引擎,要不要使用 Proxy 等等进行抉择。 NoSQL 也是什么情况下使用 master-slave,什么情况下使用客户端分片、集群、Couchbase、HiKV 等,我们内部自服务平台上都有这个选型树信息。 2、一些思考 ① 需求 我们在选型时先思考需求,判断需求是否真实。 你可以从数据量、QPS、延时等方面考虑需求,但这些都是真实需求吗?是否可以通过其他方式把这个需求消耗掉,例如在数据量大的情况下可以先做数据编码或者压缩,数据量可能就降下来了。 不要把所有需求都推到数据库层面,它其实是一个兜底的系统。 ② 选择 第二个思考的点是对于某个数据库系统或是某个技术选型我们应该考虑什么?是因为热门吗?还是因为技术上比较先进?但是不是能真正地解决你的问题?如果你数据量不是很大的话就不需要选择可以存储大数据量的系统。 ③ 放弃 第三是放弃,当你放弃一个系统时真的是因为不好用吗?还是没有用好?放弃一个东西很难,但在放弃时最好有一个充分的理由,包括实测的结果。 ④ 自研 第四是自研,在需要自己开发数据库时可以参考和使用一些成熟的产品,但不要盲目自研。 ⑤ 开源 最后是开源,要有拥抱开源的态度。

茶什i 2019-12-27 14:17:56 0 浏览量 回答数 0

回答

更换服务器~100个是单服务器最大的负荷了你用的是镶嵌式的,要选择服务器机组的那种~刀片式服务器~然后oracl数据库支持分开安装。同步处理~ 你肯定买的是架式服务器~######装ORACLE服务器是刀片式的,6核至强 24G的内存 应该不是服务器瓶颈######oracl装在独立的一台服务器上的话,只支持小形企业和地、市级企业运行 你说的情况,可以理解你的数据量非常庞大,,有可能是省、国家级的数据量了~~ 让你单位给你单独开个服务器房间,更换服务器机柜然后购买刀片式服务器做服务器阵列机组~######数据量倒不会太大,一天1G不到,问题是很多存储过程的逻辑很复杂,一条线程调用存储过程,要等待很久才会返回,直接导致工作线程速度很慢,数据进入速度太快,工作异常状态频繁出现。######必须要实时的存入数据库吗?不能先缓存到服务器,然后让服务器慢慢去处理吗?或者直接将数据记入日志,然后sqlload?######回复 @xinzaibing : 我想到一个蛋疼的方式:数据写文件,文件内容定期入库,程序定期读取数据库计算的结果缓存到内存中。不知道你具体需求,瞎琢磨一个。######回复 @asdfsx : 公司领导一致认为内存不可靠,断电、程序异常什么的...存在内存的数据就没了...真是蛋疼啊######回复 @xinzaibing : 如果数据量不大的话,还有一个方案就是都保存在内存里,然后定时把内存里的结果同步到数据库里。数据库的逻辑挪到程序里..........这个方案比较累啊。另外就是缓存可以加个优先级高低的判断。######目前要求是必须要实时入库,采取写日志文件的方法也可以。 这些数据有一个特点,在某一个时刻会有一个突然出现的峰值,然后又慢慢变少,但是这个时间是不固定的,由于只实用了一条双缓冲队列,所有需要紧急处理的数据和非紧急处理的数据都在队列里,而如果遇到非紧急数据,处理了很长的时间,就直接导致后面的紧急数据失效了...或者导致嵌入式程序判断服务端未收到数据,进而采取重发,导致一条队列里有非常多重复的数据。######我可能会使用数据写入日志文件,然后定时将日志入库的办法操作######大概意思可能是多线程对数据库表的操作导致数据表锁定,性能损失在内耗上了。。那数据表采用行级锁呢?(这样会增大系统开销)我是菜鸟,求教  ######回复 @xinzaibing : 这个应该是属于最初的设计问题,hohoho######回复 @asdfsx : 目前我也在往这方面考虑,如果数据分类处理。那就得大改结构了...唉######回复 @xinzaibing : 建议根据上传的不同数据进行不同的处理,不要一股脑的都放在缓存中,如果是心跳的话,应该立即响应,如果是要处理的数据的话,才需要进行缓存等待处理######ORACLE默认就是行级锁的应该.. 主要是数据的写入速度远远小于数据上传的速度,导致了缓存溢出,紧急数据不能得到及时处理,大量数据出现超时失效,无法对嵌入式的采集器程序作出及时的心跳相应和其他回复(因为都在队列中,无法处理,无心跳的话嵌入式采集器会误认为服务器断线)。最终导致单台服务器接入数据的嵌入式设备的数量太少,不满足需求。######去年刚毕业,由于公司小,一个人搞后台,压力太大啊...大家指指招呗~ @中山野鬼######今天到图书馆看了一本书《让Orcale跑的更快点》,上面说可以从如下几个方面优化: 数据库方面:建适当的索引,固定长度;查询条件比较尽量简化;不同的表放在不同的磁盘里…… 服务层:增大缓存,(有没有数据库连接池不知道你能用上不) 软件层:对Java使用PaperStatement 囫囵吞枣就记得这么多了。。。哭~~######非常感谢...我去看看这本书 :)######我不清楚你的数据采集的内容是什么。不过看的出,对实时性要求高。换我,基本上就一个思路。 1、做个前段服务器,什么事情都不干,只进行数据的压缩。然后所有数据库和计算操作,放到后端。 至于并发,你这种 1W=100台服务器的方式治标不治本。######@中山野鬼 是说对数据进行预处理,提取有效内容?还是就是zip?######回复 @asdfsx : 不一样的。而是数据压缩。采样数据中间,信息密度不会太大的。######老鬼的思路有点像我说的那个数据写日志文件,或者内存缓存定时入库...........都被否定了啊######@xinzaibing 还有一个建议,上传的数据加一个验证,如果上传的数据已经插入缓存,就不要再次插入了。无脑插入插到崩也不是什么好主意啊######回复 @asdfsx : 要回复的,要处理成功后才回复,存库失败或者某些异常导致服务端崩溃重启,就不进行回复,客户端会持续地进行重发,重发到一定次数后,存本地,等恢复正常后发送存本地的数据

kun坤 2020-06-09 11:56:38 0 浏览量 回答数 0

回答

作为一个javaer,我以前写过很多关于Linux的文章。但经过多年的观察,发现其实对于大部分人,有些东西压根就用不着。用的最多的,就是到线上排查个问题而已,这让人很是苦恼。那么,我们就将范围再缩小一下。 Linux生产环境上,最常用的一套“Sed“技巧 Linux生产环境上,最常用的一套“AWK“技巧 Linux生产环境上,最常用的一套“vim“技巧 Linux命令好像还真不少,根本原因就是软件多,也有像ag这样的命令想替代grep,但大多数命令古老而坚挺。不是因为这些软件设计的有多好,原因是一些软件最开始入驻了系统,时间久了,就变成了一种约定,这种习惯改变代价太大,就像把所有键盘的L和F换一下一样。 这片文章假定你已经了解大多数Linux命令,并了解操作系统的基本元素。如果你现在了解的命令还不足10个,下面的内容就不用看了。除了最基本的东西,本文列出一些对你的面试最常见的最能加分的地方,有些组合可能是你没见过的技巧。但本文仅仅是给出一个大致的轮廓和印象,为以后的专题性考察点作一个序。 本文中出现的所有命令,应该熟记并熟练使用。 几种比较典型的Linux系统 首先对目前的Linux版本有个大体的印象,大体分Desktop版和Server版,已经是百花齐放。 Ubuntu 最常见的Linux个人发行版,一位有情怀的南非富豪,有了钱你也可以这么做 CentOS 最常用Linux服务器发新版,RHEL的开放版本,因版权而生的轮子 Arch 滚动升级,海量二进制包,社区活跃,个人最爱 Gentoo 安装软件需要从源码开始编译,稳定,但用起来会很痛 LFS 从零构建Linux,跟着做一遍,Linux每根毛都看的清清楚楚 Kali 专做渗透用的,代表了发行版的一个发展路径,就是领域 首先要了解的概念 KISS Keep it Simple and Stupid,据说是哲学 一切皆文件 通常是文件的东西叫文件,进程、磁盘等也被抽象成了文件,比较离谱的管道、设备、socket等,也是文件。 这是Linux最重要的组织方式。 管道 | 分隔,前面命令的输出作为后面命令的输入,可以串联多个 重定向 < 将文件做为命令的输入 将命令的输出输出到文件 将命令的输出追加到文件 SHELL 首先确认你的shell,一般最常用的是bash,也有不少用csh,zsh等的,通过echo $SHELL可以看到当前用户的shell,对应的配置文件也要相应改变。 比如.zshrc,.bashrc 四大元素 进入linux,我们首先关注的是四个元素: 内存,cpu,存储,网络。 Linux提供了足够的命令,让你窥探它的每个角落。 接下来的命令都是些最常用的,不管精通不精通,想不起来要打屁股。 CPU 使用top查看cpu的load,使用shift+p按照cpu排序。 需要了解wa,us等都是什么意思 使用uptime查看系统启动时间和load,load是什么意思呢? 什么算是系统过载? 这是个高频问题,别怪我没告诉你 ps命令勃大茎深,除了查进程号外,你还需要知道R、S、D、T、Z、<、N状态位的含义 top和ps很多功能是相通的,比如watch "ps -mo %cpu,%mem,pid,ppid,command ax" 相当于top的进程列表; top -n 1 -bc 和ps -ef的结果相似。 有生就有死,可以用kill杀死进程。 对java来说,需要关注kill -9、kill -15、kill -3的含义,kill的信号太多了,可以用kill -l查看,搞懂大多数信号大有裨益。 如果暂时不想死,可以通过&符号在后台执行,比如tail -f a.log &。 jobs命令可以查看当前后台的列表,想恢复的话,使用fg回到幕前。 这都是终端作业,当你把term关了你的后台命令也会跟着消失,所以想让你的程序继续执行的话, 需要nohup命令,此命令需要牢记 mpstat 显示了系统中 CPU 的各种统计信 了解cpu亲和性 内存 free -m 命令,了解free、used、cached、swap各项的含义 cat /proc/meminfo 查看更详细的内存信息 细心的同学可能注意到,CPU和内存的信息,通过top等不同的命令显示的数值是一样的。 slabtop 用来显示内核缓存占用情况,比如遍历大量文件造成缓存目录项。 曾在生产环境中遇到因执行find /造成dentry_cache耗尽服务器内存。 vmstat 命令是我最喜欢也最常用的命令之一,可以以最快的速度了解系统的运行状况。 每个参数的意义都要搞懂。 swapon、swapoff 开启,关闭交换空间 sar 又一统计类轮子,一般用作采样工具 存储 使用df -h查看系统磁盘使用概况 lsblk 列出块设备信息 du 查看目录或者文件大小 网络 rsync 强大的同步工具,可以增量哦 netstat 查看Linux中网络系统状态信息,各种 ss 它能够显示更多更详细的有关TCP和连接状态的信息,而且比netstat更快速更高效。 curl、wget 模拟请求工具、下载工具。 如wget -r http://site 将下载整个站点 ab Apache服务器的性能测试工具 ifstat 统计网络接口流量状态 nslookup 查询域名DNS信息的工具,在内网根据ip查询域名是爽爆了 nc 网络工具中的瑞士军刀,不会用真是太可惜了 arp 可以显示和修改IP到MAC转换表 traceroute 显示数据包到主机间的路径,俗称几跳,跳的越少越快 tcpdump 不多说了,去下载wireshark了 wall 向当前所有打开的终端上输出信息。 使用who命令发现女神正在终端上,可以求爱 网络方面推荐安装体验一下kaliLinux,上面的工具会让你high到极点。 如何组织起来 linux的命令很有意思,除了各种stat来监控状态,也有各种trace来进行深入的跟踪,也有各种top来统计资源消耗者,也有各种ls来查看系统硬件如lsblk、lsusb、lscpi。基本上跟着你的感觉走,就能找到相应的工具,因为约定是系统中最强大的导向。 Linux有个比较另类的目录/proc,承载了每个命令的蹂躏。像sysctl命令,就是修改的/proc/sys目录下的映射项。不信看看find /proc/sys -type f | wc -l和sysctl -a| wc -l的结果是不是很像? /proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。只不过以文件系统的方式为访问系统内核数据的操作提供接口。系统的所有状态都逃不过它的火眼金睛。例如: cat /proc/vmstat 看一下,是不是和vmstat命令的输出很像? cat /proc/meminfo 是不是最全的内存信息 cat /proc/slabinfo 这不就是slabtop的信息么 cat /proc/devices 已经加载对设备们 cat /proc/loadavg load avg原来就躺在这里啊 cat /proc/stat 所有的CPU活动信息 ls /proc/$pid/fd 静静地躺着lsof的结果 一般排查问题的方法 一般排查问题也是围绕着内存cpu等几个元素去排查。下图是一张大体的排查故障或者性能问题的过程,看图,不多说。 应用场景举例 下面举例从具体应用场景来说明各种命令的组合应用,此类场景数不胜数,需要个人积累。但强烈建议将sed和awk练的熟练一些。 怎么查看某个Java进程里面占用CPU最高的一个线程具体信息? 获取进程中占用CPU最高的线程,计为n。 使用top top -H -p pid,肉眼观察之 使用ps ps -mo spid,lwp,stime,time,%cpu -p pid 将线程号转化成十六进制printf 0x%x n 使用jstack找到相应进程,打印线程后的100行信息 jstack -l pid| grep spid -A 100 统计每种网络状态的数量 netstat -ant | awk '{print $6}' | sort | uniq -c | sort -n -k 1 -r![5.jpg](https://ucc.alicdn.com/pic/developer-ecology/655b656daf0344d58dbfd798fe1460b8.jpg) 首先使用netstat查看列表,使用’awk’截取第六列,使用uniq进行统计,并对统计结果排序。当然,也可以这样。 netstat -ant | awk '{arr[$6]++}END{for(i in arr){print arr[i]" "i }}' | sort -n -k 1 -r 这和“分析apache日志,给出当日访问ip的降序列表”是一样的问题。 怎么查看哪个进程在用swap 首先要了解/proc/$pid/smaps里有我们所需要的各种信息,其中Swap字段即是我们所需要的。只要循环遍历一下即可。 for i in `cd /proc;ls |grep "^[0-9]"|awk ' $0 >100'` ;do awk '/Swap:/{a=a+$2}END{print '"$i"',a/1024"M"}' /proc/$i/smaps ;done |sort -k2nr End 软件领域有两种人才,一种是工程型的,一种是研究型的。在Linux领域里,相对于搞内核研究的来说,搞命令行的就属于工程型。工程型也有他自己的苦衷,比如,背诵命令就挺痛苦的,一般来说不太推荐背诵,第一覆盖的面不广,第二记的快忘的也快,浪费脑细胞。牛逼的记法就是用,用时间来冲淡烟云,见微知著,并体验其中的喜悦。爱她并天天抱她上床,真爱才成。 原创:小姐姐味道。

剑曼红尘 2020-04-01 11:01:13 0 浏览量 回答数 0

问题

MaxCompute百问集锦(持续更新20171011)

隐林 2019-12-01 20:19:23 38430 浏览量 回答数 18

回答

MNS配置消息队列 首先用户需要在消息服务配置队列以接收工作流发出的消息。具体操作流程如下:消息服务->队列->选择数据中心->创建队列,界面如下图。 1 新建队列必填的参数包括队列名称和当前地域,其他参数均为可选值,这些参数的意义如下: 消息接收长轮询等待时间:表示轮询等待的时间,也就是针对该队列的所有ReceiveMessage请求在Queue无消息时,都将默认进入到Polling等待状态,在等待期间一直保持无消息,则会返回MessageNotExist;如果在此期间有新的消息进入到Queue中,则会唤醒相应的ReceiveMessage请求进行返回。这里默认值为0秒,即关闭长轮询。 取出消息隐藏时长:表示消息从队列中取出后保持隐藏状态的时间。消息从队列中取出后会被从可取状态(Active)变成隐藏状态(Inactive)后,这个时间一到,消息会从隐藏恢复成Active可取状态。这里默认值为30秒。 消息最大长度:限定允许发送到该队列的消息体的最大长度,默认值为64KB,建议这里不要设置太小,因为工作流发送消息体内容较多,如果设置较小可能会导致无法接收到消息。 消息存活时间: 表示消息在本队列中最长的存活时间,从发送到该队列开始经过此参数指定的时间后,不论消息是否被取出过都将被删除,目前默认值为4天。 消息延时:表示消息可供消费的延迟时间,发送消息到本队列的所有消息默认将以本参数指定的秒数延后可被消费,默认值为0秒。 开启logging:表示将该队列中的日志推送到OSS或者SLS中。这里需要在日志管理中配置,配置方法请参考【推送日志到OSS】和【推送日志到LogService】,默认为不开启状态。 2.2 工作流配置消息模式 用户接下来需要将工作流与消息服务中的该队列相关联,在编辑工作流的输入节点时即可设置消息队列,如下图。用户设置消息类别为队列,队列名称选择之前我们设置的名称即关联完成。 2 2.3 MNS队列接收示例代码 上述流程配置完成后即执行工作流并通过MNS队列获取其中的消息。获取MNS队列中的消息可以通过MNS的API/SDK方式获取。这里以Java SDK的使用作为示例进行演示。 首先需要获取MNS相关信息,主要包括:AccessKeyId、AccessKeySecret、MNSEndpoint和队列名称。AccessKeyId和AccessKeySecret获取方法请登陆阿里云管理控制台,在下图中的按钮中获取。 3 MNS队列的名称即是我们前述创建的队列的名称,可以在MNS控制台中的队列列表中查看。而MNSEndpoint表示连接该队列的地址,可以通过MNS控制台中的“获取Endpoint”按钮获取得到,如下图中可以查看到每个账号在每个数据中心对应三个MNSEndpoint,分别是公网地址、私网地址和VPC地址。公网地址即是在有公网IP的服务器上均可使用,私网地址是指同一数据中心的阿里云经典网络的云服务器ECS上连接MNS可以使用的地址,而VPC地址即是同一数据中心的阿里云VPC网络的云服务器ECS的内网连接地址。 4 接下来即是构建Java测试环境,这里我们采用maven方式构建project。下面即是我们添加的依赖项和示例代码。 <dependency> <groupId>com.aliyun.mns</groupId> <artifactId>aliyun-sdk-mns</artifactId> <version>1.1.5</version> </dependency> public class ConsumerDemo { public static void main(String[] args) { CloudAccount account = new CloudAccount("YourAccessId", "YourAccessKey", "MNSEndpoint"); MNSClient client = account.getMNSClient(); // 在程序中,CloudAccount以及MNSClient单例实现即可,多线程安全 try{ CloudQueue queue = client.getQueueRef("TestQueue"); Message popMsg = queue.popMessage(); if (popMsg != null){ System.out.println("message handle: " + popMsg.getReceiptHandle()); System.out.println("message body: " + popMsg.getMessageBodyAsString()); System.out.println("message id: " + popMsg.getMessageId()); System.out.println("message dequeue count:" + popMsg.getDequeueCount()); //删除已经取出消费的消息 queue.deleteMessage(popMsg.getReceiptHandle()); System.out.println("delete message successfully.\n"); } else{ System.out.println("message not exist in TestQueue.\n"); } } catch (ClientException ce) { System.out.println("Something wrong with the network connection between client and MNS service." + "Please check your network and DNS availablity."); ce.printStackTrace(); } catch (ServiceException se) { se.printStackTrace(); logger.error("MNS exception requestId:" + se.getRequestId(), se); if (se.getErrorCode() != null) { if (se.getErrorCode().equals("QueueNotExist")) { System.out.println("Queue is not exist.Please create before use"); } else if (se.getErrorCode().equals("TimeExpired")) { System.out.println("The request is time expired. Please check your local machine timeclock"); } /* you can get more MNS service error code from following link: https://help.aliyun.com/document_detail/mns/api_reference/error_code/error_code.html */ } } catch (Exception e) { System.out.println("Unknown exception happened!"); e.printStackTrace(); } client.close(); } } 3. 注意事项 工作流需要配置同一数据中心的消息队列,不支持配置跨地域的消息队列。 在队列中消费消息后需要调用deleteMessage方法删除该消息,否则会导致应用端重复消费消息。

保持可爱mmm 2020-03-30 11:56:56 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站