Spring boot 部署服务

Spring Boot 出来之后,大家都振臂高呼,一些反应慢的还有些摸不着头脑,剩下的一群喷子……算了不说了

就说spring boot 有什么用吧,随着越来越多的人不停的嘲讽Java是如何的落后,如何的缓慢,就像一个老态龙钟的老人,弄的好多从业Javaer人心惶惶,这里还是不扯淡了,有一件事能做好也能做好另一件事,大家都不用纠结了。

先说Spring boot 有什么好处,首先它构建在spring 上,开发建立在spring上面,减少了很多配置,可以自己集成容器启动,这个在业界不停的讨论是否还需要容器来运行程序这个论调上算是Spring帮java扳回一城。

那么接下来就是如何玩了,当你在eclipse+maven的环境中开发完你的微服务,接下来部署开始打jar包,我推荐把依赖copy到单独的文件夹,这样在你的MANIFEST.MF 已经帮你搞定MainClass和classpath的问题,剩下就是自己指定所需要的配置文件位置

一个简单的启动参考: java -jar easyzhxSwap.jar –spring.config.location=/Users/72/Desktop/application.properties

如何优化?你猜?你再猜!

Jfinal中事务测试

昨天跟波总了解了下事务的处理,今天写个Test备忘一下。

在控制层中使用事务,简单的代码展示

@Before({POST.class , Tx.class})
public void saveWxSetting(){
log.info("saveWxSetting");
SysConfig sys1 = new SysConfig();
sys1.setId(PKUtil.getPK());
sys1.setKey("1");
sys1.setVal("1");
sys1.save();
SysConfig sys2 = new SysConfig();
sys2.setId(PKUtil.getPK());
sys2.setKey("1");
sys2.setVal("1");
sys2.save();
renderText("");
}

其中key为唯一所以,事务生效。
后来探讨了下static方法是用与测试,代码有些变化:
在业务层增加:

public static boolean test(SysConfig sys){
return sys.save();
}

控制层:

@Before({POST.class , Tx.class})
	public void saveWxSetting(){
		log.info("saveWxSetting");
		SysConfig sys1 = new SysConfig();
		sys1.setId(PKUtil.getPK());
		sys1.setKey("1");
		sys1.setVal("1");
		SysConfig.test(sys1);
		SysConfig sys2 = new SysConfig();
		sys2.setId(PKUtil.getPK());
		sys2.setKey("1");
		sys2.setVal("1");
		SysConfig.test(sys2);
		renderText("");
	}

测试依旧OK:)
后台回到业务层,意味着取消控制层的事务

@Before(POST.class)
	public void saveWxSetting(){
		log.info("saveWxSetting");
		SysConfig sys1 = new SysConfig();
		sys1.setId(PKUtil.getPK());
		sys1.setKey("1");
		sys1.setVal("1");
		SysConfig sys2 = new SysConfig();
		sys2.setId(PKUtil.getPK());
		sys2.setKey("1");
		sys2.setVal("1");
		SysConfig.test(sys1,sys2);
		renderText("");
	}
///
@Before(Tx.class)
	public static boolean test(SysConfig sys1,SysConfig sys2){
		return sys1.save()&&sys2.save();
	}

显然是失败了:( 因为:你这是业务层 aop 实现的事务,注意要用一下 Duang.duang(…) 去触发

如果在业务层中调用,代码变为:

@Before({POST.class})
	public void saveWxSetting(){
		log.info("saveWxSetting");
		SysConfig sys1 = new SysConfig();
		sys1.setId(PKUtil.getPK());
		sys1.setKey("1");
		sys1.setVal("1");
		SysConfig sys2 = new SysConfig();
		sys2.setId(PKUtil.getPK());
		sys2.setKey("1");
		sys2.setVal("1");
		SysConfig sys = Duang.duang(SysConfig.class);
		sys.test(sys1, sys2);
		renderText("");
	}
 
@Before(Tx.class)
	public boolean test(SysConfig sys1,SysConfig sys2){
		return sys1.save()&&sys2.save();
	}
 
测试下来  Dung 和 Enhancer 效果一样:)

yum 安装mysql5.7

曾经mysql落入oracle之手,原作者开创了MariaDB,此后不久各大Linux厂商纷纷转投MariaDB阵营(oracle可见多不得人心)。

随着Oracle发布mysql5.7开始支持原生json,大家又开始蠢蠢欲动了,因为之前的源都已经指向mariaDB,所以不得不采用rpm来安装,但是门槛相对傻瓜式的yum复杂一些,好在mysql提供源方便安装了

环境:centos 6.5 64bit

源地址:http://dev.mysql.com/downloads/repo/yum/

接下来不说了,继续吧

centos 安装memcached

官方的教程很简单

Debian/Ubuntu: apt-get install libevent-dev Redhat/Centos: yum install libevent-devel

wget http://memcached.org/latest
tar -zxvf memcached-1.x.x.tar.gz
cd memcached-1.x.x
./configure && make && make test && sudo make install

不过必要的准备还是的有的吧

yum -y install gcc
yum -y install gcc-c++ libstdc++-devel
yum -y install zlib-devel

然后按照官方搞定吧

启动参数
-p 设置TCP端口号(默认不设置为: 11211)
-U UDP监听端口(默认: 11211, 0 时关闭)
-l 绑定地址(默认:所有都允许,无论内外网或者本机更换IP,有安全隐患,若设置为127.0.0.1就只能本机访问)
-d 以daemon方式运行
-u 绑定使用指定用于运行进程
-m 允许最大内存用量,单位M (默认: 64 MB)
-P 将PID写入文件,这样可以使得后边进行快速进程终止, 需要与-d 一起使用

启动命令:例如:memcached -d -u root

使用jodd发送邮件设置发件人问题

使用odd mail的好处就是不用自己实现各种协议,还可以轻松搞定问题,发送邮件就是一件小事儿了,但是有时候需要设置一下发件人,生的人家都是 各种公司CEO的,到我们这都是 devp@sxnuoyun.com  之类的low掉渣渣。

无奈E文差,网速更差,jodd mail 说的蛮简单,以至于没找见怎么设置发件人字段了,干脆去猜吧,看着哪个像点哪个

Email email = new Email();

email.setFrom(new MailAddress(FROMEMAIL));

65E26EA5-7591-4B7B-B622-50DBD2440DEC

手感不错,猜的蛮准, 使用xxxx <email> 格式自动截取发件人:)

iterm2免密码登录Linux

用惯了Win的xshell,忽然到了mac下面就忽然茫然了,后来厚着脸问人家用什么工具,人家说用 iterm2+证书登录,恍然大悟,

os x 不也就是linux吗?

那就简单了,在iterm2 中输入ssh-keygen 一路回车

然后在~/.ssh 产生了id_rsa.pub和id_rsa 文件,将pub公钥上传到服务器的~/.ssh/authorized_keys ,然后修改配置

修改sshd配置文件(/etc/ssh/sshd_config).
找到以下内容,并去掉注释符”#“
=========================
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile  .ssh/authorized_keys
=========================

 

然后重启ssh,这下在iterm2 中配置下连接指令,搞定。

关于Chrome调试中.min.js.map 404的问题

前端在Chrmo F12模式下调试的时候,经常会遇到js.map文件找不到的情况,例如:

http://domain/AngularJS/v1.3.11/angular.min.js.map 404 (Not Found)

关于这个问题其实大可不比过分的纠集,一般只会在你引用了压缩的min.js 文件,chrome浏览器中才会出现

实际并不影响页面的执行效果。这里简单说下原理:

map文件是js文件压缩后,文件的变量名替换对应、变量所在位置等元信息数据文件,一般这种文件和min.js主文件放在同一个目录下。

使开发者可以用未压缩前的代码来调试,这样就不会出现这个问题了,但是往往想使用min文件,而且还有强迫症的患者是非常难受的,那么取掉这个小x也很简单
打开chrome的F12界面,然后点击“设置”,去掉 Sources里面的 Enable JavaScript source maps

EG:

min.js.map - 副本

Java常见内存溢出异常分析(OutOfMemoryError)

1.背景知识

1).JVM体系结构

162853_WIxX_820500

2).JVM运行时数据区

162109_yFNI_820500

2.堆溢出(OutOfMemoryError:java heap space)

堆(Heap)是Java存放对象实例的地方。

堆溢出可以分为以下两种情况,这两种情况都会抛出OutOfMemoryError:java heap space异常:

1)内存泄漏

内存泄漏是指对象实例在新建和使用完毕后,仍然被引用,没能被垃圾回收释放,一直积累,直到没有剩余内存可用。

如果内存泄露,我们要找出泄露的对象是怎么被GC ROOT引用起来,然后通过引用链来具体分析泄露的原因。

分析内存泄漏的工具有:Jprofiler,visualvm等。

2)内存溢出

内存溢出是指当我们新建一个实力对象时,实例对象所需占用的内存空间大于堆的可用空间。

如果出现了内存溢出问题,这往往是程序本生需要的内存大于了我们给虚拟机配置的内存,这种情况下,我们可以采用调大-Xmx来解决这种问题。

示例:

package com.demo3;

import java.util.ArrayList;
import java.util.List;

public class OOMTest {

public static void main(String[] args) {
List<byte[]> buffer = new ArrayList<byte[]>();
buffer.add(new byte[10 * 1024 * 1024]);
}
}

通过如下命令运行程序:

java -verbose:gc -Xmn10M -Xms20M -Xmx20M -XX:+PrintGC OOMTest

输出结果:

[GC 836K->568K(19456K), 0.0234380 secs]
[GC 568K->536K(19456K), 0.0009309 secs]
[Full GC 536K->463K(19456K), 0.0085383 secs]
[GC 463K->463K(19456K), 0.0003160 secs]
[Full GC 463K->452K(19456K), 0.0062013 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.demo3.OOMTest.main(OOMTest.java:10)

3.持久带溢出(OutOfMemoryError: PermGen space)

持久带(PermGen space)是JVM实现方法区的地方,因此该异常主要设计到方法区和方法区中的常量池。

1).方法区

方法区(Method Area)不仅包含常量池,而且还保存了所有已加载类的元信息。当加载的类过多,方法区放不下所有已加载的元信息时,就会抛出OutOfMemoryError: PermGen space异常。主要有以下场景:

  • 使用一些应用服务器的热部署的时候,我们就会遇到热部署几次以后发现内存溢出了,这种情况就是因为每次热部署的后,原来的class没有被卸载掉。
  • 如果应用程序本身比较大,涉及的类库比较多,但是我们分配给持久带的内存(通过-XX:PermSize和-XX:MaxPermSize来设置)比较小的时候也可能出现此种问题。

2).常量池

常量池(Runtime Constrant Pool)专门放置源代码中的符号信息。常量池中除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值外,还包含一些以文本形式出现的符号引用,比如:类和接口的全限定名;字段的名称和描述符;方法的名称和描述符等。

当常量池需要的空间大于常量池的实际空间时,也会抛出OutOfMemoryError: PermGen space异常。

例如,Java中字符串常量是放在常量池中的,String.intern()这个方法运行的时候,会检查常量池中是否存和本字符串相等的对象,如果存在直接返回对常量池中对象的引用,不存在的话,先把此字符串加入常量池,然后再返回字符串的引用。那么可以通过String.intern方法来模拟一下运行时常量区的溢出.

示例:

package com.demo3;
 
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
 
public class OOMTest {
 
    public static void main(String[] args) {
        List list = new ArrayList();
        while (true) {
            list.add(UUID.randomUUID().toString().intern());
        }
    }
}

通过以下命令运行:

java -verbose:gc -Xmn5M -Xms10M -Xmx10M -XX:MaxPermSize=1M -XX:+PrintGC OOMTest

最后的运行结果:

Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
        at java.lang.String.intern(Native Method)
        at OOMTest.main(OOMTest.java:8)

4.线程栈

栈(JVM Stack)存放主要是栈帧( 局部变量表, 操作数栈 , 动态链接 , 方法出口信息 )的地方。注意区分栈和栈帧:栈里包含栈帧。

与线程栈相关的内存异常有两个:

  • StackOverflowError(方法调用层次太深,内存不够新建栈帧)
  • OutOfMemoryError(线程太多,内存不够新建线程)

1).java.lang.StackOverflowError

栈溢出抛出java.lang.StackOverflowError错误,出现此种情况是因为方法运行的时候,请求新建栈帧时,栈所剩空间小于战帧所需空间。

例如,通过递归调用方法,不停的产生栈帧,一直把栈空间堆满,直到抛出异常 :

package com.demo3;
 
public class OOMTest {
    public void stackOverFlowMethod() {
        stackOverFlowMethod();
    }
 
    public static void main(String... args) {
        OOMTest oom = new OOMTest();
        oom.stackOverFlowMethod();
    }
}

运行结果:

Exception in thread "main" java.lang.StackOverflowError
    at com.demo3.OOMTest.stackOverFlowMethod(OOMTest.java:5)
    at com.demo3.OOMTest.stackOverFlowMethod(OOMTest.java:5)
    at com.demo3.OOMTest.stackOverFlowMethod(OOMTest.java:5)
    at com.demo3.OOMTest.stackOverFlowMethod(OOMTest.java:5)
    at com.demo3.OOMTest.stackOverFlowMethod(OOMTest.java:5)
    at com.demo3.OOMTest.stackOverFlowMethod(OOMTest.java:5)
    at com.demo3.OOMTest.stackOverFlowMethod(OOMTest.java:5)
    at com.demo3.OOMTest.stackOverFlowMethod(OOMTest.java:5)
    .....

2).java.lang.OutOfMemoryError:unable to create new native thread 

因为虚拟机会提供一些参数来保证堆以及方法区的分配,剩下的内存基本都由栈来占有,而且每个线程都有自己独立的栈空间(堆,方法区为线程共有)。所以:

  • 如果你把虚拟机参数Xss调大了,每个线程的占用的栈空间也就变大了,那么可以建立的线程数量必然减少
  • 公式:线程栈总可用内存=JVM总内存-(-Xmx的值)- (-XX:MaxPermSize的值)- 程序计数器占用的内存

如果-Xmx或者-XX:MaxPermSize太大,那么留给线程栈可用的空间就越小,在-Xss参数配置的栈容量不变的情况下,可以创建的线程数也就越小。

上述两种情况都会导致:当创建的线程数太多时,栈内存不够用来创建新的线程,那么就会抛出java.lang.OutOfMemoryError:unable to create new native thread 异常。

PS:由于在window平台的虚拟机中,java的线程是隐射到操作系统的内核线程上的,所以运行一下产生该异常的代码时,可能会导致操作系统假死。

 

[FROM:http://my.oschina.net/sunchp/blog/369412]

CentOS6.5升级Kernel

阿里云上的6.5CentOS模版还是2.6的内核,对Docker来说就有些低版本了(Docker推荐3.8 :)),于是着手升级

lsb_release -a
LSB Version:	:base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch
Distributor ID:	CentOS
Description:	CentOS release 6.5 (Final)
Release:	6.5
Codename:	Final

uname -a
Linux iZ289l79vfqZ 2.6.32-431.23.3.el6.x86_64 #1 SMP Thu Jul 31 17:20:51 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

为了配合Docker,使用YUM中的long-term 源升级

rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
yum --enablerepo=elrepo-kernel install kernel-lt -y

升级完成后,修改启动内核,修改default=0 (新安装的内核在第一个)

default=0
timeout=5
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
hiddenmenu
title CentOS (3.10.63-1.el6.elrepo.x86_64)
        root (hd0,0)
        kernel /boot/vmlinuz-3.10.63-1.el6.elrepo.x86_64 ro root=UUID=94e4e384-0ace-437f-bc96-057dd64f42ee rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
        initrd /boot/initramfs-3.10.63-1.el6.elrepo.x86_64.img
title CentOS (2.6.32-431.23.3.el6.x86_64)
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.32-431.23.3.el6.x86_64 ro root=UUID=94e4e384-0ace-437f-bc96-057dd64f42ee rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
        initrd /boot/initramfs-2.6.32-431.23.3.el6.x86_64.img

重启,然后uname -a 查看。

CentOS 7 中Nginx proxy 502的问题

环境 CentOS Linux release 7.0.1406 (Core)     Nginx    tomcat

使用nginx做前端,proxy后端tomcat 8080 端口,浏览器死活502 ,⊙︿⊙。

stackoverflow 上发现同样有人遇到此问题,

http://stackoverflow.com/questions/23948527/13-permission-denied-while-connecting-to-upstreamnginx

翻阅了Nginx的blog

http://nginx.com/blog/nginx-se-linux-changes-upgrading-rhel-6-6/

此问题在6.6以上就出现了,sudo cat /var/log/audit/audit.log | grep nginx | grep denied

查阅SELinux 日志,发现问题

type=AVC msg=audit(1420460715.553:594): avc:  denied  { name_connect } for  pid=3425 comm=”nginx” dest=8080 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:http_cache_port_t:s0 tclass=tcp_socket

 

执行命令(yum -y install policycoreutils-python)

sudo cat /var/log/audit/audit.log | grep nginx | grep denied | audit2allow -M mynginx
sudo semodule -i mynginx.pp

搞定,502请滚粗……