服务器tomcat自动停止问题

Linux下面有个机制叫OOM killer(Out Of Memory killer,这个东西会在系统内存耗尽或者即将耗尽的情况下跳出来执行,选择性的干掉一些进程以求释放一些内存。

可能会出现的问题就是,某天tomcat无缘无故停掉了,或者是 某天机器突然登不上了,能ping通,但是ssh死活连不了。原因是tomcat/sshd进程被OOM killer干掉了。在系统的日志中通常会有下面的打印日志:Out of memory: kill process 959 (sshd) score 55 or a child。 

1.       OOM什么时候出现?

我们在用户空间申请内存时,一般使用的是malloc,是不是当malloc返回为空时,没有可以申请的内存空间了就会返回呢?答案是否定的。在关于malloc的申请内存的机制中有下面的一段描述:

By default, Linux follows an optimistic memory allocation strategy. This means that when malloc() returns non-NULL there is no guarantee that the memory really is available. This is a really bad bug. In case it turns out that the system is out of memory, one or more processes will be killed by the infamous OOM killer. In case Linux is employed under circumstances where it would be less desirable to suddenly lose some randomly picked processes, and moreover the kernel version is sufficiently recent, one can switch off this overcommitting behavior using a command like:

上面的描述中说明了在Linux中当malloc返回的是非空时,并不代表有可以使用的内存空间。Linux系统允许程序申请比系统可用内存更多的内存空间,这个特性叫做overcommit特性,这样做可能是为了系统的优化,因为不是所有的程序申请了内存就会立刻使用,当真正的使用时,系统可能已经回收了一下内存。但是,当你使用时Linux系统没有内存可以使用时,OOM Killer就会出来让一些进程退出。

Linux下有3种Overcommit的策略(参考内核文档:vm/overcommit-accounting),可以在/proc/sys/vm/overcommit_memory配置(取0,1和2三个值,默认是0)。

(1)0:启发式策略,比较严重的Overcommit将不能得逞,比如你突然申请了128TB的内存。而轻微的overcommit将被允许。另外,root能Overcommit的值比普通用户要稍微多

(2)永远允许overcommit,这种策略适合那些不能承受内存分配失败的应用,比如某些科学计算应用。

(3)永远禁止overcommit,在这个情况下,系统所能分配的内存不会超过swap+RAM*系数(/proc/sys/vm/overcmmit_ratio,默认50%,你可以调整),如果这么多资源已经用光,那么后面任何尝试申请内存的行为都会返回错误,这通常意味着此时没法运行任何新程序。

/proc/sys/vm # cat overcommit_ratio

50

当然我可以修改proc//oom_adj的值,这里的默认值为0,当我们设置为-17时,对于该进程来说,就不会触发OOM机制,被杀掉。

echo -17 > /proc/$(pidof sshd)/oom_adj

这里为什么是-17呢?这和Linux的实现有关系。在Linux内核中的oom.h文件中,可以看到下面的定义:

/* /proc//oom_adj set to -17 protects from the oom-killer */

#define OOM_DISABLE (-17)

/* inclusive */

#define OOM_ADJUST_MIN (-16)

#define OOM_ADJUST_MAX 15

这个oom_adj中的变量的范围为15到-16之间。越大越容易被kill。oom_score就是它计算出来的一个值,就是根据这个值来选择哪些进程被kill掉的。

总之,通过上面的分析可知,满足下面的条件后,就是启动OOM机制。

1) VM里面分配不出更多的page(注意linux kernel是延迟分配page策略,及用到的时候才alloc;所以malloc + memset才有效)。

2) 用户地址空间不足,这种情况在32bit机器上及user space超过了3GB,在64bit机器上不太可能发生。

2     当该机制被触发后,会让什么样的进程退出?

只要存在overcommit,就可能会有OOM killer。 Linux系统的选择策略也一直在不断的演化。我们可以通过设置一些值来影响OOM killer做出决策。Linux下每个进程都有个OOM权重,在/proc//oom_adj里面,取值是-17到+15,取值越高,越容易被干掉。  最终OOM killer是通过/proc//oom_score这个值来决定哪个进程被干掉的。这个值是系统综合进程的内存消耗量、CPU时间(utime + stime)、存活时间(uptime – start time)和oom_adj计算出的,消耗内存越多分越高,存活时间越长分越低。总之,总的策略是:损失最少的工作,释放最大的内存同时不伤及无辜的用了很大内存的进程,并且杀掉的进程数尽量少。  另外,Linux在计算进程的内存消耗的时候,会将子进程所耗内存的一半同时算到父进程中。

最后还是说一下使用需要注意的事项:

1、内存首先要足够基本进程的正常运行,以防被无缘无故kill

2、要对tomcat的设置进行优化,尤其是对内存的控制

javashop v6.2 或将移除组件的component.xml文件,采用注解代替

注解说明:移步 == 》 http://www.javamall.com.cn/blog/archives/311

首先说明一下已有组件的原理:

❤️在系统启动,spring加载时,我们判定一个即将实例化到spring容器中的对象否实现组件接口,如果实现则将其写入组件上下文(ComponentContext)的静态变量集合中,并且加载component.xml文件,生成ComponentView(组件视图)和PluginVIew(插件视图)

❤️自定义的监听器(EopContextLoaderListener)执行时,启动组件。根据ComponentView和PluginView正确生成可以正确调用插件的插件桩

修改后的逻辑

❤️在系统启动,spring加载时,我们判定一个即将实例化到spring容器中的对象否实现特定接口,如果实现 组件借口(IComponent) 则将其写入组件上下文(ComponentContext)的静态变量集合中,如果实现了插件接口(IPlugin)则将其写入插件上下文(PluginContext)

❤️自定义的监听器(EopContextLoaderListener)执行时,获取组件上下文中所有的组件,循环遍历从插件上下文中获取到组件对应的插件集合,根据每个组件和插件的注解,映射出正确的ComponentView(组件视图)和PluginVIew(插件视图)。随后,启动组件,根据ComponentView和PluginView正确生成可以正确调用插件的插件桩。

注解类讲解:

插件注解

CustomPlugin(自定义插件注解)

 插件名称 public String name() default “默认插件”;

 组件 public String component() default “组件id”;

 插件 public String plugin() default “插件id”; 

 执行优先级(保留字段 控制执行顺序) public int sort() default 10;

  插件桩集合 public String[] bundle() default “”;

CustomComponent(自定义组件注解)

 组件名称 public String name() default “默认组件”;

 组件id public String beanid() default “”;

 版本 public String version() default “1.0”;

 javashop版本 public String javashop_version() default “3.0.0”;

 作者 public String author() default “javashop”; 

描述 public String description() default “默认描述”;

属性字段基本和component.xml的配置具体参数没什么区别, 所以修改为注解的形式没有大的改动,只是更改了生成 ComponentView和PluginView的方式。

注解使用

在组件插件具体的类上,声明注解即可。

以上是对注解方式的组件的具体使用解释,接下来讲解连带的其它变更

1、组件加载

ComponentLoader(组件加载)在bean实例化之前的方法中,加入了插件上下文(PluginContext)的注册。

新增的插件上下文主要包含一个静态Map类型,key存组件的beanid,value存该组件的插件集合。

2、组件注册

ComponentContext(组件上下文)的注册组件方法中原本加载组件视图的方法被移除

3、组件启动

EopContextLoadListener(Eop上下文启动监听器)中,组件启动前,获取组件上下文中所有的组件视图,然后执行组件加载视图方法。(也就是在组件注册时的方法被延后执行)

随后执行原本的组件启动方法。

*********************************************主要修改部分************************************************

ComponentContext组件上下文核心方法loadComponent修改,为了兼容老版本的组件机制,这里对Bean是否声明了组件注解进行判定:

如果没有声明,那么按照传统的方法获取component.xml生成组件插件视图。

如果有声明,则获取注解信息进行组件和插件视图的生成。

*********************************************************************************************************

为什么组件机制使用注解实现

spring用注解的方式来管理容器中bean的关系,是所有人看的到到优点,使用注解之前,采用在xml中配置文件的繁琐程度不言而喻。使用注解唯一的缺点不外乎是管理松散,不能概括的了解组件、插件和插件桩的关系。但是只要项目结构足够合理,我相信这个问题是可以避免的。

抛开这些不说,作为一个程序员,喜欢看起来可以装X的代码,抛弃xml配置文件才用注解在个人看来是一个提升逼格的方法。哈哈哈哈

注解是什么,如何使用注解,为什么使用注解

注解是什么

注解,可以看作是对 一个 类/方法 的一个扩展的模版,每个 类/方法 按照注解类中的规则,来为 类/方法 注解不同的参数,在用到的地方可以得到不同的 类/方法 中注解的各种参数与值。

怎么使用注解

1、自定义注解类

注解类上方的注解各种含义,看这个链接http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html

2、枚举类

3、注解使用

通过注解获取到了具体的配置信息,并且打印,那么注解的功能就说完了

以上演示的是类型注解,方法注解则修改注解类中

@Target(ElementType.TYPE)  ===> @Target(ElementType.METHOD)   按照以下方法调用即可

为什么用注解

优点

配置文件

1,集中管理对象和对象之间的组合关系,易于阅读

注解

1,开发速度快

2,编译期间容易发现错误的出处

缺点

配置文件

1,开发速度相对较慢;

2,编译时很难检查出错误,运行中的错误很难定位,调试难度较大。

注解

管理分散,基本每个类上都有;


一个小特性

注解有类似继承这样的机制,A.java 实现了spring的@Component可以被注入到spring容器,但如果自定义的注解有spring的@Component注解的话,那么在具体使用这个自定义注解时候将不需要原本使用的spring注解,具体事例如下:

这是原本应该有的注解形式,一个自定义注解以及一个spring的注解

如果自定义注解 拥有spring的@component注解

那么在具体使用时,可以忽略之前的注解

以上观点为自我理解的结果,如有错误,请指正!~

关于ajax请求未完成响应直接刷新导致走ajxa error事件问题解决

问题描述

浏览器ajax请求未完成响应,就刷新页面导致ajax执行ajax的error方法,造成一些不必要的错误提示

方法1:async : false

在ajax 函数中 加入 属性 async:false,即可
属性 async 默认值为 true
当async:false为同步,在这个Ajax请求将整个浏览器锁死,
只有ajax请求多url返回响应,才可以执行其它操作。
当async: true 时,ajax请求是异步的。如果有多个请求的话,就会一起发出一起响应。

javashop 图片缩放浏览插件使用指南

一、概述

Javashop 图片缩放浏览插件是一款基于jquery插件的图片浏览插件。

可用于一张、一组或多组的图片进行缩放浏览,有如下特点:

  • 基于jquery插件的风格,只需引入一个插件脚本,其它不用关心,生成方便灵活
  • 提供丰富配置参数

效果预览:

二、使用说明

  1. 首先需要在相应的html页面引入js和css文件,如下图:
  2. 接下来用<a></a>标签包住要浏览的图片,并向<a>标签添加data-lightbox=”自定义”属性或rel=”lightbox[自定义]”属性,如下图:
  3. 如果是图片组,也是按上述步骤进行,只是需要注意的是,如果是多个图片组,我们需要保证同组的图片的所有<a>标签的data-lightbox=”自定义”属性或rel=”lightbox[自定义]”属性的自定义部分相同并和其他图片的中的不同,这样是保证在进行图片缩放浏览时可以一组一组的进行浏览。如下图:
  4. 参数配置。所有的参数组都不是必须设置的,它们都有默认值,可以根据不同的需求来进行设置:
  • albumLabel:设置显示的图片文本内容
  • alwaysShowNavOnTouchDevices:在使用支持触摸设备查看图片时(手机、iPad等),如果设置为true,也会显示左右翻页的导航箭头,默认false
  • fadeDuration:图片缩放淡出和淡入的时间,以毫秒为单位,默认500
  • fitImagesInViewport:如果设置为true,图片缩放就会基于maxWidth和maxHeight来进行缩放,否则就会按照图片原始比例进行缩放
  • maxWidth:设置显示图片弹出框的最大宽度(图片会基于此宽度按比例缩放),默认为图片原始宽度
  • maxHeight:设置显示图片弹出框的最大高度(图片会基于此高度按比例缩放),默认为图片原始高度
  • positionFromTop:设置图片缩放弹出框到屏幕顶部的距离,默认为50
  • resizeDuration:设置图片显示的加载时间(毫秒),默认为700
  • showImageNumberLabel:设置是否显示图片文本内容,默认为true
  • wrapAround:设置是否可以循环查看图片,默认为false
  • disableScrolling:禁止图片浏览框随页面上下左右滚动,true为禁止,默认为false
  • 如下图:

Javashop 图片上传插件使用指南

一、概述

Javashop 图片上传插件是一款基于WebUploader插件所封装的上传图片插件。

可用于快速生成上传图片页面,有如下特点:

  •  基于freemarker指令模式所编写,只需一个指令,并且添加相关的配置,其它不用关心,生成方便灵活
  • 多配置,灵活性较高
  • 支持拖拽排序,操作体验提升

效果预览

二、使用说明

上传图片插件会使用ajax上传图片,上传图片后生成一个的input。剩下就可以按照你自己的业务逻辑进行处理。

1.基本使用指南

1. freemarker指令,写在你想生成的html的位置

<@imageuploader/>

2. 配置

参数说明:

imageName   :   【必填】生成input的name

subFolder   :   【必填】服务器存放目录

showImgs :   【必填,数组】已有的图片作为显示用的比如www.a.com/a.png.  没有其他作用

actualImgs : 【必填,数组】已有图片实际的值,这个看你自己的逻辑,会生成input提交

fileNumLimit : 【选填】限制上传数量,不填默认20个

按照以上配置后,即可实现上传图片功能。

注:暂不支持一个页面多个上传图片空间,1.1版本考虑支持

Javashop快钱支付插件使用指南

一、生成证书

这个过程请参考快钱提供的文档

可以点击这里下载:http://pan.baidu.com/s/1jIETaM6

如果要使用沙箱,使用他的demo中的两个证书即可。

快钱Demo下载

二、配置快钱插件

下面我们以使用快钱的Demo中的证书配合快钱沙箱举例如何配置:

1.其中的URL设置为快钱沙箱的提交地址:

https://sandbox.99bill.com/gateway/recvMerchantInfoAction.htm

如果你是在正式环境,要填写为:

https://www.99bill.com/gateway/recvMerchantInfoAction.htm

2.私钥和公钥分别是demo中的:

这两个

将准备好证书(沙箱的或正式的)放在服务器上的一个位置,如:

/home/key/tester-rsa.pfx

/home/key/99bill[1].cert.rsa.20140803.cer

然后将上述地址分别配置在相应的输入框中

3.证书密码

如果是沙箱环境,证书密码是123456

如果是正式环境,证书密码是你生成证书时的密码

点击保存后,就可以使用快钱支付了。

 

 

javashop中paypal使用指南

一、开发者地址:

https://developer.paypal.com

使用在paypal上注册的账号登陆即可,

二、沙箱账号

paypay自动会为你创建两个沙箱账号,一个商家,一个买家。在accounts菜单中可以看到:

点击profile可以自行修改相应的密码

三、创建APP

登陆后,访问:https://developer.paypal.com/developer/applications/

点击”create app”

点击”Crate App” 来完成创建,成功后在列表中会出现:

四、Client ID和Secret

点击应用名字,进入应用详情:

在这里可以查看Client ID和Secret

注意:默认是沙箱的,在右上角有切换到正式环境的菜单(上图,圈红处)

五、IPN

Paypal是通过IPN来通知Javashop的付款状态的,请参考如下设置:

(以沙箱为例,正式环境界面略有不同,但菜单名称是一样的)

沙箱登陆http://www.sandbox.paypay.com/

用户名和密码就是在开发者中的account菜单中的商家账号和密码。

点击用户信息:

即时付款通知习惯设定:

点击编辑ipn设置,进入到Ipn设置页面:

点击接收付消息,然后在URL中输入以下地址:

xxxx/api/shop/s_paypalPaymentPlugin_payment-callback.do

将其中的xxx换为你的网站域名,请注意不要带Http,否则paypal不允许输入。

当用户付款完成后,Paypal会通过IPN来通知javashop,Javashop对消息进行验证成功后更改订单状态为付款状态。

所以Paypal的调试必须是在公网的域名下,否则Paypal通知不到的。

六、编码设定

IPN的消息推送要和Javashop的编码保持一致才能校验成功,请按下面进行设置:

点击用户信息->语言编码:

然后选择 “更多选项”:

然后选择UTF-8

点击保存完成编码的设置。

至此Paypal的配置已经完成,接下来在Javashop的后台中设置Paypal的相应参数:

依次点击:设置->支付方式->添加->选择Paypal插件,然后填入相应的参数:

设置相应参数后,即可使用Paypal来付款了。

值得注意的是:

在正式环境中,在中国,无法大陆为大陆付款,所以如果你要测试正式环境的话,需要在申请一个外国的账号来完成测试。

Javashop Tab页jQuery插件使用指南

一、概述

Javashop Tab页jQuery插件是一款基于jquery插件的Tab页生成器。

可用于快速生成Tab页面,有如下特点:

  •  基于jquery插件的风格,只需引入一个插件脚本和按照规格格式编写HTML,其它不用关心,生成方便灵活
  •  同个页面可生成多个Tab页,互不干扰

效果预览

 

 

二、使用说明

1.基本使用指南

1.引入选器插件:

<script type="text/javascript" 
src="/adminthemes/new/js/jquery.Tab.js"></script>

2.编写HTML:

<div id="test_tab" style="margin:20px;">
    <div class="contentTab">
        <ul class="tab">
            <li tabid="one" class="active" >第一</li>
            <li tabid="two" >第二</li>
        </ul>
    </div>

    <div class="tab-page">
        <div tabid="one" class="tab-panel" >
            <h1>我是第一个内容</h1>
        </div>
        <div tabid="two" class="tab-panel" style="display: none;" >
             <h1>我是第二个内容</h1>
        </div>
    </div>
</div>

这里需要注意的是,这个HTML格式并不是全部规定死的。只要有ul 和 class为tab-page的div,其他元素可随意增加,样式随意写。

3.调用插件生成选择器(选择需要悬浮的元素)

<script type="text/javascript">

$(function(){

    $("#test_tab").Tab();

});

</script>

如上代码在id为test_tab的div中实现了tab页。