dubbo + assembly 整理

本文结合网上资料整理。

Dubbo部分

Dubbo 是阿里巴巴开源一个RPC框架,核心思想是通过注册中心,实现provider和consumer之间的接口交互。可以通过多个provider实现分布式,consumer在使用时不必关心提供方。

这几天在调整dubbo provider的发布方式。之前项目使用了war的方式提供服务,这在provider过多时,需要引入许多container并带来维护成本,而且容器本身也占用系统内存。官方的demo是采用jar的方式调用,但要注意的是,如果直接在main线程注册provider而不block住,注册完马上就会注销。

网上有人采用System.in.read(); 方式来block,代码片段如下:

public class Main {
	public static void main(String[] args){
		
		// load spring、dubbo configuration
		
		try {
			System.in.read();
		} catch (IOException e) {
			e.printStackTrace();
		}
}

但是放到centos上执行不顺利,改用了线程sleep的方式。代码片段如下:

public static void main(String[] args) throws IOException {
		
		logger.info(" **** main start ****");
		
		MyThread myThread = new MyThread();
		Thread thread = new Thread(myThread, "xxx");
		thread.start();
		
		logger.info(" **** main end ****");
	}

@Override
	public void run() {
		//load spring、dubbo configurations
		context.start();
		do {
			try {
				Thread.sleep(3600000);
			} catch (InterruptedException e) {
				logger.error("",e);
			}
		} while (true);
	}
如果有业务需要,可以增加interrupt方式来终止线程。


Assembly部分

扫描二维码关注公众号,回复: 3015855 查看本文章

maven提供了maven-assembly-plugin,适用于打包。在assembly基础上配套了profie,更适用于企业多环境的部署问题。

比如一个qa profile,配置assembly文件位置

<profile>
			<id>qa</id>
			<properties>
				<assembly.ddescriptor>build/assembly/qa/assembly.xml</assembly.ddescriptor>
			</properties>
		</profile>
插件使用时即可根据profile读取正确的配置文件

			<plugin>
			    <groupId>org.apache.maven.plugins</groupId>
			    <artifactId>maven-assembly-plugin</artifactId>
			    <version>2.4</version>
			    <configuration>
			        <descriptors>
			            <descriptor>${assembly.ddescriptor}</descriptor>
			        </descriptors>
			    </configuration>
			    <executions>
			        <!-- 当执行mvn package时才会打包 -->
			        <execution>
			            <id>make-assembly</id>
			            <phase>package</phase>
			            <goals>
			                <goal>single</goal>
			            </goals>
			        </execution>
			    </executions>
			</plugin>

assembly.xml 如下,指定一些配置文件的路径。

<assembly>
    <id>bin</id>
    <formats>
        <!-- zip,tar,tar.gz,tar.bz2,jar,dir,war -->
        <format>zip</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <!-- 依赖包的输出路径 -->
        <dependencySet>
        	<useProjectArtifact>true</useProjectArtifact>
            <outputDirectory>lib</outputDirectory>
        </dependencySet>
    </dependencySets>
    <!-- 需要打包的文件集 -->
    <fileSets>
    	<fileSet>
            <directory>env/qa/conf</directory>
            <outputDirectory>/conf</outputDirectory>
            <includes>
		        <include>**/*.xml</include>
		    </includes>
        </fileSet>
        <fileSet>
            <directory>env/qa/conf</directory>
            <outputDirectory>/conf</outputDirectory>
            <includes>
		        <include>**/*.properties</include>
		    </includes>
		    <filtered>true</filtered>
        </fileSet>
        <fileSet>
            <directory>build/scripts</directory>
            <outputDirectory>/bin</outputDirectory>
            <includes>
		        <include>**</include>
		    </includes>
        </fileSet>
    </fileSets>
</assembly>

提供start.sh、stop.sh脚本

#!/bin/bash

export JAVA_HOME=xxx
export PATH=$PATH:/xxx/bin

cd `dirname $0`
BIN_DIR=`pwd`
cd ..
DEPLOY_DIR=`pwd`
CONF_DIR=$DEPLOY_DIR/conf

JAVA_MAIN_CLASS="xxx"

PIDS=`ps -f | grep java | grep "$CONF_DIR" |awk '{print $2}'`
if [ -n "$PIDS" ]; then
    echo "ERROR: The $DEPLOY_DIR already started!"
    echo "PID: $PIDS"
    exit 1
fi

LOGS_DIR=$DEPLOY_DIR/logs

if [ ! -d $LOGS_DIR ]; then
    mkdir $LOGS_DIR
fi
STDOUT_FILE=$LOGS_DIR/stdout.log

LIB_DIR=$DEPLOY_DIR/lib
LIB_JARS=`ls $LIB_DIR|grep .jar|awk '{print "'$LIB_DIR'/"$0}'|tr "\n" ":"`

JAVA_OPTS=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true "
JAVA_DEBUG_OPTS=""
if [ "$1" = "debug" ]; then
    JAVA_DEBUG_OPTS=" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n "
fi
JAVA_JMX_OPTS=""
if [ "$1" = "jmx" ]; then
    JAVA_JMX_OPTS=" -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false "
fi
JAVA_MEM_OPTS=""
BITS=`java -version 2>&1 | grep -i 64-bit`
if [ -n "$BITS" ]; then
    JAVA_MEM_OPTS=" -server -Xmx2g -Xms2g -Xmn256m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "
else
    JAVA_MEM_OPTS=" -server -Xms1g -Xmx1g -XX:PermSize=128m -XX:SurvivorRatio=2 -XX:+UseParallelGC "
fi

echo -e "Starting the $DEPLOY_DIR ...\c"
nohup java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS -Djava.ext.dirs=$LIB_DIR:$CONF_DIR $JAVA_MAIN_CLASS > $STDOUT_FILE 2>&1 &

COUNT=0
while [ $COUNT -lt 1 ]; do    
    echo -e ".\c"
    sleep 1
    COUNT=`ps -f | grep java | grep "$DEPLOY_DIR" | awk '{print $2}' | wc -l`
    if [ $COUNT -gt 0 ]; then
        break
    fi
done

echo "OK!"
PIDS=`ps -f | grep java | grep "$DEPLOY_DIR" | awk '{print $2}'`
echo "PID: $PIDS"
echo "STDOUT: $STDOUT_FILE"

#!/bin/bash
cd `dirname $0`
BIN_DIR=`pwd`
cd ..
DEPLOY_DIR=`pwd`
CONF_DIR=$DEPLOY_DIR/conf

PIDS=`ps -ef | grep java | grep "$DEPLOY_DIR" |awk '{print $2}'`
if [ -z "$PIDS" ]; then
    echo "ERROR: The $DEPLOY_DIR does not started!"
    exit 1
fi

if [ "$1" != "skip" ]; then
    $BIN_DIR/dump.sh
fi

echo -e "Stopping the $DEPLOY_DIR ...\c"
for PID in $PIDS ; do
    kill $PID > /dev/null 2>&1
done

COUNT=0
while [ $COUNT -lt 1 ]; do    
    echo -e ".\c"
    sleep 1
    COUNT=1
    for PID in $PIDS ; do
        PID_EXIST=`ps -f -p $PID | grep java`
        if [ -n "$PID_EXIST" ]; then
            COUNT=0
            break
        fi
    done
done

echo "OK!"
echo "PID: $PIDS"

dubbo服务管理部分

以上部分从使用上已经可以正常提供dubbo服务,但是为了方便管理,可以增加后台控制。这里采用java的process来操作shell脚本。

String sudo = "chmod 777 " + script;
		String cmd = "/bin/sh " + script;
		
		
		Process process = null;
		try {
			logger.info("execute command:{}",sudo);
			process = Runtime.getRuntime().exec(sudo);
			process.waitFor();
			logger.info("execute command:{}",cmd);
			Runtime.getRuntime().exec(cmd);
		} catch (Exception e) {
			logger.error("{}",e);
		}finally {
			process.destroy();
		}

chmod是考虑到权限问题。在使用java progress操作时,需要注意提供环境变量支持,如上面脚本的JAVA_HOME。

管理系统代码可以参考:Dubbo-center

********** 2015-12-23 

增加windows下bat脚本

@echo off & setlocal enabledelayedexpansion

echo begin

f:
set DEPLOY_DIR=f:\root
set LIB_JARS=""
set MAIN_CLASS=com.cherong.service.pay.init.Init
cd %DEPLOY_DIR%\lib
for %%i in (*) do set LIB_JARS=!LIB_JARS!;..\lib\%%i
cd ..\bin

if ""%1"" == ""debug"" goto debug
if ""%1"" == ""jmx"" goto jmx

echo begin java java -Xms64m -Xmx1024m -XX:MaxPermSize=64M -classpath ..\conf;%LIB_JARS% %MAIN_CLASS%
java -Xms64m -Xmx1024m -XX:MaxPermSize=64M -classpath ..\conf;%LIB_JARS% %MAIN_CLASS%
goto end

:debug
java -Xms64m -Xmx1024m -XX:MaxPermSize=64M -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n -classpath ..\conf;%LIB_JARS% %MAIN_CLASS%
goto end

:jmx
java -Xms64m -Xmx1024m -XX:MaxPermSize=64M -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -classpath ..\conf;%LIB_JARS% %MAIN_CLASS%

:end
pause

请注意windows下cmd的路径切换,比如脚本中的 f: ,否则无法正常执行。

windows下停止暂时采用JAVA实现,暂未解决脚本占用问题

package com.chinesedreamer.dubbocenter.executor.service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.chinesedreamer.dubbocenter.pid.Pid;

public class WindowsStopProcess {
	private static Logger logger = LoggerFactory.getLogger(WindowsStopProcess.class);
	
	private static String TASK_LIST = "taskList";
	private static String TASK_KILL = "TSKILL ";
	private static String PID_PATH = "wmic process where processid=<pid> get commandline"; //获取pid路径
	
	public static void stopProcess(String path) {
		Process process = null;
		List<String> pids = new ArrayList<String>();
		try {
			process = Runtime.getRuntime().exec(TASK_LIST);
			Scanner in = new Scanner(process.getInputStream(),"GBK");
			while (in.hasNextLine()) {
				String line = in.nextLine();
				if (line.startsWith("java")) {
					pids.add(line);
				}
			}
			in.close();
			List<Pid> getPidObjs = getPidObjs(pids);
			for (Pid pid : getPidObjs) {
				process = Runtime.getRuntime().exec(PID_PATH.replace("<pid>", pid.getPid()));
				in = new Scanner(process.getInputStream(),"GBK");
				while (in.hasNextLine()) {
					String commandPath = in.nextLine();
					logger.info("process path: {}" , commandPath);
					if (commandPath.trim().endsWith(path)) {
						logger.info("kill pid#{}",pid.getPid());
						Runtime.getRuntime().exec(TASK_KILL + pid.getPid());
						break;
					}
				}
			}
		} catch (IOException e) {
			logger.error("{}",e);
		}
	}
	
	private static List<Pid> getPidObjs(List<String> pids) {
		List<Pid> pidOjbs = new ArrayList<Pid>();
		
		List<String> pidObj = new ArrayList<String>();
		
		for (String pid : pids) {
			String[] pidProperties = pid.split(" ");
			pidObj.clear();
			for (String pidProperty : pidProperties) {
				if (StringUtils.isNotEmpty(pidProperty)) {
					pidObj.add(pidProperty);
				}
			}
			pidOjbs.add(generatePid(pidObj));
		}
		
		return pidOjbs;
	}
	
	private static Pid generatePid(List<String> pidObj) {
		Pid pid = new Pid();
		pid.setServiceName(pidObj.get(0));
		pid.setPid(pidObj.get(1));
		pid.setSessionName(pidObj.get(2));
		pid.setSessionNumber(pidObj.get(3));
		pid.setMemory(pidObj.get(4));
		return pid;
	}
}


猜你喜欢

转载自blog.csdn.net/u013275741/article/details/49819265