yangyoupeng

åmicroservice first commit on gitlab

Showing 477 changed files with 4829 additions and 0 deletions
<?xml version="1.0" encoding="UTF-8"?>
<?PowerDesigner signature="Workspace" version="15.1.0.2850"?>
<!-- do not edit this file -->
<Workspace>
<Local Expanded="Yes">
<Model Expanded="Yes" ID="{881D9969-7DB9-4618-861B-480185720066}" Loaded="No" Name="microservice" Selected="Yes" Type="{FF4B6538-9856-42CF-B9B9-304ED370CEAA}" URL="microservice/microservice.prj"/>
<Model Expanded="Yes" ID="{31D61ADA-B480-44B8-8192-DECA45413B95}" Name="enginerich-mysql" Type="{CDE44E21-9669-11D1-9914-006097355D9B}" URL="/yangyoupeng/工作/project/stareasy/enginerich-mysql.pdm"/>
</Local>
<BrowserModule Name="Repository"/>
</Workspace>
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
.settings
.project
microservice-configuration/.settings
microservice-configuration/target
microservice-configuration/.classpath
microservice-configuration/.project
microservice-framework-core/.settings
microservice-framework-core/target
microservice-framework-core/.classpath
microservice-framework-core/.project
microservice-framework-monitor/.settings
microservice-framework-monitor/target
microservice-framework-monitor/.classpath
microservice-framework-monitor/.project
microservice-framework-aaa/.settings
microservice-framework-aaa/target
microservice-framework-aaa/.classpath
microservice-framework-aaa/.project
microservice-msq/.settings
microservice-msq/target
microservice-msq/.classpath
microservice-msq/.project
microservice-cache-es/.settings
microservice-cache-es/target
microservice-cache-es/.classpath
microservice-cache-es/.project
microservice-runtime/.settings
mircoservice-runtime/target
microservice-runtime/.classpath
microservice-runtime/.project
microservice-redis/.settings
microservice-redis/target
microservice-redis/.classpath
microservice-redis/.project
support-gateway/.settings
support-gateway/target
support-gateway/.classpath
support-gateway/.project
support-gateway/bin
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.zhaoonline</groupId>
<artifactId>microservice-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>microservice-cache-es</artifactId>
<name>microservice-cache-es</name>
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>delete-by-query</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<!-- logback-access for Servlet containers -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
</dependency>
<!-- logback-classic for Log4J or SLF4j -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<!-- logback-core is the underline,it is the groundwork for the access
and classic module -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.zhaoonline.es.cache;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import org.elasticsearch.action.deletebyquery.DeleteByQueryResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhaoonline.es.core.CacheException;
import com.zhaoonline.es.core.ESClient;
public class ESCache implements Cache {
private Logger logger= LoggerFactory.getLogger(ESCache.class);
private final ESClient esClient;
private String cacheName;
private static ObjectMapper mapper = new ObjectMapper();
private ESCacheMeta cachemMeta=null;
public ESCache(String cacheName,ESClient esClient){
this.cacheName=cacheName;
this.esClient=esClient;
cachemMeta= new ESCacheMeta(cacheName);
}
@Override
public String getName() {
return this.cacheName;
}
/**
* @Override
* @see org.springframework.cache.Cache#getNativeCache() <BR>
* Method name: getNativeCache <BR>
* Description:返回ESClient<BR>
* Remark: <BR>
* @return <BR>
*/
@Override
public Object getNativeCache() {
return esClient;
}
/**
* @Override
* @see org.springframework.cache.Cache#get(java.lang.Object) <BR>
* Method name: get <BR>
* Description: 返回值包含的Map<String, Object>内部调用get方法<BR>
* Remark: <BR>
* @param key
* @return <BR>
*/
@Override
public ValueWrapper get(Object key) {
ESCacheKey cacheKey=null;
if(key instanceof ESCacheKey){
cacheKey=(ESCacheKey) key;
}else{
cacheKey=new ESCacheKey(cachemMeta.getIdName(),key);
}
Map<String, Object> docMap=esClient.get(cachemMeta.getIndex(),cachemMeta.getType(),cacheKey.getKeyAsString());
return docMap ==null?null:new ESCacheElement(cacheKey, docMap);
}
@Override
public <T> T get(Object key, Class<T> type) {
ValueWrapper value = get(key);
Object valueObject=value.get();
String jsonString;
try {
//我们先将对象转换为Json,然后在转换为对象。也许我们可以考虑使用dozer。
jsonString = mapper.writeValueAsString(valueObject);
return mapper.readValue(jsonString,type);
} catch (JsonProcessingException e) {
logger.error("fail to get cache item with key:{},because of JsonProcessingException:{}",key,e.getMessage());
throw new CacheException(String.format("fail to get cache item with key:[%s]",key),e.getCause());
} catch (IOException e) {
logger.error("fail to get cache item with key:{},because of IOException exception:{},can not convert to the class type:{}",key,e.getMessage(),type.getName());
throw new CacheException(String.format("fail to get cache item with key:[%s],because of IOException exception:[%s],can not convert to the class type:[%s]",key,e.getMessage(),type.getName()),e.getCause());
}
}
@Override
public void put(Object key, Object value) {
ESCacheKey cacheKey=new ESCacheKey(cachemMeta.getIdName(),key);
putToES(cacheKey,value);
}
public void put(ESCacheKey cacheKey, Object value) {
putToES(cacheKey,value);
}
public Map<String, Object> getRawCacheData(ESCacheKey cacheKey){
Object cacheValue=get(cacheKey).get();
return cacheValue == null ? null:(Map<String, Object>) cacheValue;
}
@Override
public ValueWrapper putIfAbsent(Object key, Object value) {
Object wrapperedValue =get(key).get();
if(wrapperedValue == null){
ESCacheKey cacheKey=new ESCacheKey(cachemMeta.getIdName(),key);
IndexResponse reponse =putToES(cacheKey,value);
reponse.getId();
reponse.getIndex();
reponse.getType();
reponse.getVersion();
ESCacheReponse putValue=new ESCacheReponse();
putValue.setId(reponse.getId());
putValue.setIndex(reponse.getIndex());
putValue.setType(reponse.getType());
putValue.setVersion(reponse.getVersion());
putValue.setCreated(reponse.isCreated());
ESCacheElement cacheElement=new ESCacheElement(cacheKey, putValue);
return cacheElement;
}
return null;
}
private IndexResponse putToES(ESCacheKey cacheKey, Object value){
String jsonString;
try {
jsonString = mapper.writeValueAsString(value);
IndexResponse reponse=esClient.addDoc(cachemMeta.getIndex(),cachemMeta.getType(),cacheKey,jsonString);
return reponse;
} catch (JsonProcessingException e) {
logger.error("error to put a cache item to cacheName:{}",getName());
throw new CacheException(String.format("fail to put cache key:[%s] ,value:[%s] into the cache %s,because %s",cacheKey.getKeyAsString(),value,getName(),e.getMessage()));
}
}
@Override
public void evict(Object key) {
ESCacheKey cacheKey=null;
if(key instanceof ESCacheKey){
cacheKey=(ESCacheKey) key;
}else{
cacheKey=new ESCacheKey(cachemMeta.getIdName(),key);
}
try {
boolean result=esClient.deleteDocByKey(cachemMeta.getIndex(),cachemMeta.getType(),cacheKey);
if(!result){
logger.error("failed to evict the cache item with key:{}",key);
throw new CacheException(String.format("failed to evict the cache item with key:[%s]",key));
}
} catch (InterruptedException | ExecutionException e) {
logger.error("failed to evict the cache item with key:{}",key);
throw new CacheException(String.format("failed to evict the cache item with key:[%s]",key),e);
}
}
@Override
public void clear() {
try {
DeleteByQueryResponse cleanType=esClient.deleteType(cachemMeta.getIndex(),cachemMeta.getType());
if(cleanType.getTotalFailed()>0){
throw new CacheException(String.format("failed to clear all the cache %s",cacheName));
}
} catch (InterruptedException | ExecutionException e) {
logger.error("failed to clear all the cache {}",cacheName);
throw new CacheException(String.format("failed to clear all the cache %s",cacheName),e);
}
}
static class ESCacheMeta{
private String index;
private String type;
private static String defualtIndexName="cache";
private String idName;
public ESCacheMeta(String type){
this(defualtIndexName,type);
}
/**
* Method name: ESCacheMeta<BR>
* Description: <BR>
* Remark: <BR>
* @param index index 必须是小写的
* @param type <BR>
*/
public ESCacheMeta(String index,String type){
this.index=index.toLowerCase();
this.type=type;
this.idName="id";
}
public String getIndex() {
return index;
}
public void setIndex(String index) {
this.index = index;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getIdName() {
return idName;
}
public void setIdName(String idName) {
this.idName = idName;
}
}
@Override
public <T> T get(Object arg0, Callable<T> arg1) {
return null;
}
}
package com.zhaoonline.es.cache;
import org.springframework.cache.support.SimpleValueWrapper;
public class ESCacheElement extends SimpleValueWrapper {
private final ESCacheKey cacheKey;
private long timeToLive;
public ESCacheElement(ESCacheKey cacheKey,Object value) {
super(value);
this.cacheKey=cacheKey;
}
public void setTimeToLive(long timeToLive) {
this.timeToLive = timeToLive;
}
public long getTimeToLive() {
return timeToLive;
}
public ESCacheKey getCacheKey() {
return cacheKey;
}
public boolean isEternal() {
return 0 == timeToLive;
}
public ESCacheElement expireAfter(long seconds) {
setTimeToLive(seconds);
return this;
}
}
package com.zhaoonline.es.cache;
public class ESCacheKey {
private final Object keyElement;
private final String keyName;
private String defualtId="id";
public ESCacheKey(String keyName,Object key) {
this.keyName=keyName;
this.keyElement=key;
}
public String getKeyAsString(){
return String.valueOf(keyElement);
}
public String getKeyName() {
return keyName;
}
public boolean autoGenId(){
return !keyName.equalsIgnoreCase(defualtId);
}
}
package com.zhaoonline.es.cache;
import java.util.Collection;
import java.util.Collections;
import org.springframework.cache.Cache;
import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager;
import org.springframework.cache.transaction.TransactionAwareCacheDecorator;
import com.zhaoonline.es.core.ESClient;
/**
* class name:ESCacheManager <BR>
* class description: ESCacheManager的作用是为了将Cache交给Spring来管理 <BR>
* Remark: <BR>
* @version 1.00 2016年8月23日
* @author zhaoonline)yangyoupeng
*/
public class ESCacheManager extends AbstractTransactionSupportingCacheManager {
private ESClient client=null;
public ESCacheManager(ESClient client) {
this.client=client;
}
@Override
public Cache getCache(String name) {
Cache cache = super.getCache(name);
if (cache == null ) {
return createAndAddCache(name);
}
return cache;
}
@SuppressWarnings("deprecation")
private Cache createAndAddCache(String cacheName) {
addCache(createCache(cacheName));
return super.getCache(cacheName);
}
protected ESCache createCache(String cacheName) {
return new ESCache(cacheName,client);
}
/**
* @Override
* @see org.springframework.cache.support.AbstractCacheManager#loadCaches() <BR>
* Method name: loadCaches <BR>
* Description:这里我们创建一个emptyList <BR>
* Remark: <BR>
* @return <BR>
*/
@Override
protected Collection<? extends Cache> loadCaches() {
return Collections.<Cache> emptyList();
}
/* (non-Javadoc)
* @see
org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager#decorateCache(org.springframework.cache.Cache)
*/
@Override
protected Cache decorateCache(Cache cache) {
if (isCacheAlreadyDecorated(cache)) {
return cache;
}
return super.decorateCache(cache);
}
protected boolean isCacheAlreadyDecorated(Cache cache) {
return isTransactionAware() && cache instanceof TransactionAwareCacheDecorator;
}
}
package com.zhaoonline.es.cache;
public class ESCacheReponse {
private String index;
private String id;
private String type;
private long version;
private boolean created;
public String getIndex() {
return index;
}
public void setIndex(String index) {
this.index = index;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
public boolean isCreated() {
return created;
}
public void setCreated(boolean created) {
this.created = created;
}
}
package com.zhaoonline.es.core;
public class CacheException extends RuntimeException {
/**
* serialVersionUID:TODO
*/
private static final long serialVersionUID = 1L;
public CacheException() {
super();
}
public CacheException(String s) {
super(s);
}
public CacheException(String s, Throwable throwable) {
super(s, throwable);
}
public CacheException(Throwable throwable) {
super(throwable);
}
}
package com.zhaoonline.es.core;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.deletebyquery.DeleteByQueryAction;
import org.elasticsearch.action.deletebyquery.DeleteByQueryRequestBuilder;
import org.elasticsearch.action.deletebyquery.DeleteByQueryResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import com.zhaoonline.es.cache.ESCacheKey;
public class ESClient {
private TransportClient client;
public ESClient(TransportClient client) {
this.client = client;
}
/**
* Method name: search <BR>
* Description: 根绝cache的key来查询doc。这里的key为为唯一键 <BR>
* Remark: <BR>
*
* @param index
* @param type
* @param keyName
* @param keyValue
* void<BR>
*/
public Map<String, Object> search(String index, String type, ESCacheKey cacheKey) {
SearchResponse searchRes = client.prepareSearch(index).setTypes(type)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(QueryBuilders.boolQuery()
.filter(QueryBuilders.termQuery(cacheKey.getKeyName(), cacheKey.getKeyAsString())))
.setFrom(0).setSize(1).execute().actionGet();
SearchHits hits = searchRes.getHits();
if (hits.getTotalHits() != 0) {
SearchHit hit = hits.getAt(0);
Map<String, Object> doc = hit.getSource();
return doc;
}
return null;
}
/**
* Method name: get <BR>
* Description: index、type、id查询doc <BR>
* Remark: <BR>
* @param index
* @param type
* @param id
* @return Map<String,Object><BR>
*/
public Map<String, Object> get(String index, String type,String id){
GetResponse searchRes = client.prepareGet(index, type, id).get();
return searchRes.getSource();
}
public IndexResponse addDoc(String index, String type, ESCacheKey cacheKey, String value) {
IndexResponse indexRespone =null;
if(cacheKey.autoGenId()){
indexRespone=client.prepareIndex(index, type).setSource(value).get();
}else{
indexRespone=client.prepareIndex(index, type).setId(cacheKey.getKeyAsString()).setSource(value).get();
}
return indexRespone;
}
public boolean deleteDocByKey(String index, String type, ESCacheKey cacheKey) throws InterruptedException, ExecutionException {
if(!cacheKey.autoGenId()){
DeleteResponse response=client.prepareDelete(index, type, cacheKey.getKeyAsString()).get();
}else{
DeleteByQueryResponse deleteByQueryResponse= new DeleteByQueryRequestBuilder(client, DeleteByQueryAction.INSTANCE)
.setIndices(index).setTypes(type)
.setQuery(QueryBuilders.termQuery(cacheKey.getKeyName(), cacheKey.getKeyAsString())).execute()
.get();
long failedCount=deleteByQueryResponse.getTotalFailed();
if(failedCount >0){
return false;
}
}
return true;
}
public DeleteByQueryResponse deleteType(String index, String type) throws InterruptedException, ExecutionException {
DeleteByQueryResponse response = new DeleteByQueryRequestBuilder(client, DeleteByQueryAction.INSTANCE)
.setIndices(index).setTypes(type)
.setQuery(QueryBuilders.matchAllQuery()).execute()
.actionGet();
return response;
}
public void close(){
if(client !=null){
client.close();
}
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: ElasticClient.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.es
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月10日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.es.core;
import java.net.InetSocketAddress;
import java.util.Map;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.plugin.deletebyquery.DeleteByQueryPlugin;
/**
* class name:ElasticClient <BR>
* class description: ElasticClient 工厂 <BR>
* Remark: <BR>
* @version 1.00 2016年8月10日
* @author zhaoonline)yangyoupeng
*/
public class ElasticClientFactory {
public static TransportClient createClient(ElasticConfiguration config){
Settings settings =Settings.settingsBuilder().put(ElasticConfiguration.KEY_CLINET_TRANSPORT_SNIFF,config.isClienttransportsniff())
.put(ElasticConfiguration.KEY_CLUSTER_NAME,config.getClusterName())
.build();
TransportClient client = TransportClient.builder().addPlugin(DeleteByQueryPlugin.class).settings(settings).build();
for(Map.Entry<String, Integer> hostPort:config.getHostPorts().entrySet()){
client.addTransportAddress(new InetSocketTransportAddress(new InetSocketAddress(hostPort.getKey(),hostPort.getValue())));
}
return client;
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: ElasticConfiguration.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.es
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月10日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.es.core;
import java.util.Map;
/**
* class name:ElasticConfiguration <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月10日
* @author zhaoonline)yangyoupeng
*/
public class ElasticConfiguration {
public static final String KEY_CLINET_TRANSPORT_SNIFF="client.transport.sniff";
public static final String KEY_CLUSTER_NAME="cluster.name";
private boolean clienttransportsniff;
private String clusterName;
private Map<String,Integer> hostPorts;
/**
* Method name: isClienttransportsniff <BR>
* Description: please write your description <BR>
* @return boolean <BR>
*/
public boolean isClienttransportsniff() {
return clienttransportsniff;
}
/**
* Method name: setClienttransportsniff <BR>
* Description: please write your description <BR>
* @param clienttransportsniff boolean <BR>
*/
public void setClienttransportsniff(boolean clienttransportsniff) {
this.clienttransportsniff = clienttransportsniff;
}
/**
* Method name: getClusterName <BR>
* Description: please write your description <BR>
* @return String <BR>
*/
public String getClusterName() {
return clusterName;
}
/**
* Method name: setClusterName <BR>
* Description: please write your description <BR>
* @param clusterName String <BR>
*/
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
/**
* Method name: getHostPorts <BR>
* Description: please write your description <BR>
* @return Map<String,Integer> <BR>
*/
public Map<String, Integer> getHostPorts() {
return hostPorts;
}
/**
* Method name: setHostPorts <BR>
* Description: please write your description <BR>
* @param hostPorts Map<String,Integer> <BR>
*/
public void setHostPorts(Map<String, Integer> hostPorts) {
this.hostPorts = hostPorts;
}
}
package com.zhaoonline.es.cache;
import org.elasticsearch.client.transport.TransportClient;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
import com.zhaoonline.es.core.ESClient;
import com.zhaoonline.es.core.ElasticClientFactory;
import com.zhaoonline.es.core.ElasticConfiguration;
import static org.junit.Assert.*;
import java.util.HashMap;
import java.util.Map;
public class TestESCache {
ESCache cache=null;
ESClient esClient=null;
@Before
public void before(){
//TransportClient的端口必须是Discovery的端口
ElasticConfiguration config=new ElasticConfiguration();
config.setClusterName("zhaoonline");
Map<String, Integer> hostPorts=new HashMap<String, Integer>();
hostPorts.put("127.0.0.1", 9300);
config.setHostPorts(hostPorts);
TransportClient client=ElasticClientFactory.createClient(config);
esClient=new ESClient(client);
String testCache="test";
cache=new ESCache(testCache, esClient);
}
/**
* Method name: testPutAndGet <BR>
* Description: 需要在本地启动一个ElasticSearch的实例 <BR>
* Remark: <BR> void<BR>
*/
@Test
public void testPutAndGet(){
TestUser user=new TestUser();
user.setId("1");
user.setName("hello world");
String key="2";
cache.put(key, user);
ValueWrapper cachedValue=cache.get(key);
Map<String, Object> valueStr=(Map<String, Object>) cachedValue.get();
assertEquals("hello world", valueStr.get("name").toString());
cache.evict(key);
}
@Test
public void testPutAndGetAsType(){
TestUser user=new TestUser();
user.setId("1");
user.setName("hello world");
String key="2";
cache.put(key, user);
TestUser user2=cache.get(key, TestUser.class);
assertEquals("hello world", user2.getName());
cache.evict(key);
}
@Test
public void testPutIfAbsent(){
testClear();
TestUser user=new TestUser();
user.setId("2");
user.setName("hello world");
String key="1";
cache.putIfAbsent(key, user);
ValueWrapper cachedValue=cache.get(key);
Map<String, Object> valueStr=(Map<String, Object>) cachedValue.get();
assertEquals("hello world", valueStr.get("name").toString());
cache.evict(key);
ValueWrapper value=cache.get(key);
assertNull(value);
}
@Test
public void testClear(){
cache.clear();
String key="1";
ValueWrapper value=cache.get(key);
assertNull(value);
}
@After
public void after(){
esClient.close();
}
}
package com.zhaoonline.es.cache;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import static org.mockito.Mockito.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.AfterTransaction;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;
import com.zhaoonline.es.cache.TestESCacheManagerBase.BarRepository;
import com.zhaoonline.es.cache.TestESCacheManagerBase.FooService;
import com.zhaoonline.es.core.ESClient;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@Transactional(transactionManager = "transactionManager")
public class TestESCacheManager {
protected @Autowired FooService transactionalService;
protected @Autowired ESClient esClient;
@Configuration
@EnableCaching
public static class Config {
@Bean
public PlatformTransactionManager transactionManager() throws SQLException {
DataSourceTransactionManager txmgr = new DataSourceTransactionManager();
txmgr.setDataSource(dataSource());
txmgr.afterPropertiesSet();
return txmgr;
}
@Bean
public DataSource dataSource() throws SQLException {
DataSource dataSourceMock = mock(DataSource.class);
when(dataSourceMock.getConnection()).thenReturn(mock(Connection.class));
return dataSourceMock;
}
@Bean
public CacheManager cacheManager() {
ESCacheManager cacheManager = new ESCacheManager(esClient());
cacheManager.setTransactionAware(true);
return cacheManager;
}
@SuppressWarnings({ "rawtypes" })
@Bean
public ESClient esClient() {
ESClient client = mock(ESClient.class);
Map<String,Object> cacheItem=new HashMap<String,Object>();
when(client.get(any(String.class), any(String.class),any(String.class))).thenReturn(null);
return client;
}
@Bean
public FooService fooService() {
return new FooService();
}
@Bean
public BarRepository barRepository() {
return new BarRepository();
}
}
@AfterTransaction
public void assertThatValuesNeverAddedToES() {
verify(esClient, times(0)).addDoc(any(String.class), any(String.class), any(ESCacheKey.class), any(String.class));
}
@Rollback(true)
@Test
public void tesValuesNotAddedToCacheWhenTransactionIsRolledBack() {
transactionalService.foo();
}
}
package com.zhaoonline.es.cache;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;
public abstract class TestESCacheManagerBase {
static class FooService {
private @Autowired BarRepository repo;
@Transactional
public String foo() {
Map barMap=repo.bar();
return "foo" + barMap.get("bar");
}
}
static class BarRepository {
@Cacheable(cacheNames="bar",key="1")
public Map<String, Object> bar() {
Map<String, Object> map=new HashMap<>();
map.put("bar", 1);
return map;
}
}
}
package com.zhaoonline.es.cache;
public class TestUser {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.zhaoonline.es.cache;
import static org.hamcrest.core.Is.*;
import static org.hamcrest.core.IsNull.*;
import static org.hamcrest.core.IsSame.*;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.cache.Cache;
import org.springframework.cache.transaction.TransactionAwareCacheDecorator;
import com.zhaoonline.es.core.ESClient;
@RunWith(MockitoJUnitRunner.class)
public class UnitTestESCacheManager {
private @Mock ESClient client;
private ESCacheManager cacheManager;
@Before
public void setUp() {
cacheManager = new ESCacheManager(client);
}
@Test
public void testGetCacheReturnsNewCacheWhenRequestedCacheIsNotAvailable() {
Cache cache = cacheManager.getCache("not-available");
assertThat(cache, notNullValue());
}
@Test
public void testGetCacheReturnsExistingCacheWhenRequested() {
Cache cache = cacheManager.getCache("cache");
assertThat(cacheManager.getCache("cache"), sameInstance(cache));
}
@Test
public void testTransactionAwareDecorator(){
cacheManager.setTransactionAware(true);
Cache cache = cacheManager.getCache("cache");
boolean isTransactionAwareDecorator=false;
if(cache instanceof TransactionAwareCacheDecorator){
isTransactionAwareDecorator=true;
}
assertThat(isTransactionAwareDecorator, is(true));
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.zhaoonline</groupId>
<artifactId>microservice-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.zhaoonline</groupId>
<artifactId>microservice-configuration</artifactId>
</project>
\ No newline at end of file
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.zhaoonline</groupId>
<artifactId>microservice-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>mircoservice-framework-aaa</artifactId>
</project>
\ No newline at end of file
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.zhaoonline</groupId>
<artifactId>microservice-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>microservice-framework-core</artifactId>
<name>microservice-framework-core</name>
<dependencies>
<dependency>
<groupId>com.zhaoonline</groupId>
<artifactId>alpaca-config-zookeeper</artifactId>
</dependency>
<dependency>
<groupId>com.esotericsoftware.kryo</groupId>
<artifactId>kryo</artifactId>
</dependency>
<dependency>
<groupId>de.javakaffee</groupId>
<artifactId>kryo-serializers</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<distributionManagement>
<repository>
<id>releases</id>
<url>http://192.168.0.205:8081/nexus/content/repositories/releases</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<url>http://192.168.0.205:8081/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<attach>true</attach>
</configuration>
<executions>
<execution>
<id>attach-sources</id>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: Application.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.annotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月29日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* class name:DuddoSerivce <BR>
* class description:为消费端装备的注解<BR>
* Remark: <BR>
* @version 1.00 2016年8月1日
* @author zhaoonline)yangyoupeng
*/
@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DuddoSerivce {
/**
* Method name: name <BR>
* Description: Application 的名称 <BR>
* Remark: <BR>
* @return String<BR>
*/
String name() default "";
String consumerId();
/**
* Method name: serviceInt <BR>
* Description: service的接口的名称 <BR>
* Remark: <BR>
* @return Class<BR>
*/
Class<?> consumerService() ;
String registryId() default "defaultRegistry";
String version() default "";
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: AnnotationProcessor.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.annotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月1日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
/**
* class name:AnnotationProcessor <BR>
* class
* description:Annotation处理器,主要对annotation进行处理,生成对象,并将对象交还给applicationContext
* <BR>
* Remark: <BR>
*
* @version 1.00 2016年8月1日
* @author zhaoonline)yangyoupeng
*/
@Component
public class DuddoSerivceAnnotationProcessor
implements DisposableBean, BeanFactoryPostProcessor, BeanPostProcessor, ApplicationContextAware {
private static final Logger logger = LoggerFactory.getLogger(Logger.class);
private final ConcurrentMap<String, ReferenceConfig<?>> referenceConfigs = new ConcurrentHashMap<String, ReferenceConfig<?>>();
private final ConcurrentMap<String, RegistryConfig> registryConfigs = new ConcurrentHashMap<String, RegistryConfig>();
private ApplicationContext applicationContext;
private String applicationName = null;
/**
* @Override
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
* <BR>
* Method name: setApplicationContext <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param applicationContext
* @throws BeansException
* <BR>
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* @Override
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object,
* java.lang.String) <BR>
* Method name: postProcessBeforeInitialization <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param bean
* @param beanName
* @return
* @throws BeansException
* <BR>
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Class<?> clazz = bean.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
DuddoSerivce application = field.getAnnotation(DuddoSerivce.class);
if (application != null) {
Object value = refer(application, field.getType());
if (value != null) {
// 获得到的对象注入到field中去
field.set(bean, value);
}
}
} catch (Exception e) {
throw new BeanInitializationException("Failed to init remote service reference at filed "
+ field.getName() + " in class " + bean.getClass().getName(), e);
}
}
return bean;
}
/**
* Method name: refer <BR>
* Description: 根据Application中生成reference对象<BR>
* Remark: <BR>
*
* @param application
* @param type
* @return Object<BR>
*/
private Object refer(DuddoSerivce application, Class<?> type) {
String appName = application.name();
if (this.applicationName != null && !applicationName.equalsIgnoreCase(appName)) {
throw new IllegalStateException("Duplicate Application Name " + appName
+ ",the already existed applicationName is " + applicationName);
} else if (this.applicationName == null) {
applicationName = appName;
}
Class<?> consumerInterface = application.consumerService();
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName(appName);
String key = application.consumerId();
ReferenceConfig<?> referenceConfig = referenceConfigs.get(key);
if (referenceConfig == null) {
ReferenceConfig<?> reference = new ReferenceConfig<Object>(); // 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
reference.setApplication(applicationConfig);
// 获取registrybean。
RegistryConfig registry = (RegistryConfig) applicationContext.getBean(application.registryId());
registryConfigs.putIfAbsent(application.registryId(), registry);
reference.setRegistry(registry);
reference.setInterface(consumerInterface);
if(application.version() !=null && !application.version().isEmpty()){
reference.setVersion(application.version());
}
referenceConfigs.putIfAbsent(key, reference);
referenceConfig = referenceConfigs.get(key);
}
//referenceConfig.get()会和注册中心交互获取service信息
return referenceConfig.get();
}
/**
* @Override
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object,
* java.lang.String) <BR>
* Method name: postProcessAfterInitialization <BR>
* Description: 暂时不做任何事情 <BR>
* Remark: <BR>
* @param bean
* @param beanName
* @return
* @throws BeansException
* <BR>
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/**
* @Override
* @see org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory)
* <BR>
* Method name: postProcessBeanFactory <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param beanFactory
* @throws BeansException
* <BR>
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
/**
* @Override
* @see org.springframework.beans.factory.DisposableBean#destroy() <BR>
* Method name: destroy <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @throws Exception
* <BR>
*/
@Override
public void destroy() throws Exception {
for (ReferenceConfig<?> referenceConfig : referenceConfigs.values()) {
try {
referenceConfig.destroy();
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
for (RegistryConfig referenceConfig : registryConfigs.values()) {
try {
referenceConfig.destroyAll();
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
ProtocolConfig.destroyAll();
}
public String getApplicationName() {
return applicationName;
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: InjectOpID.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.annotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月10日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* class name:InjectOpID <BR>
* class description: 对于Controller中各个方法中在调用的时候对调用的Request进行诸如一个唯一的RequestID <BR>
* Remark: <BR>
* @version 1.00 2016年8月10日
* @author zhaoonline)yangyoupeng
*/
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface InjectRequestID {
/**
* Method name: prefix <BR>
* Description: RequestID的前缀, RequestID的模式就是prefix+UUID<BR>
* Remark: <BR>
* @return String<BR>
*/
String prefix() default "zhaoonline";
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: InjectOpIDAdvisor.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.annotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月10日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.annotation;
import java.lang.reflect.Method;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* class name:InjectOpIDAdvisor <BR>
* class description: please write your description <BR>
* Remark: <BR>
*
* @version 1.00 2016年8月10日
* @author zhaoonline)yangyoupeng
*/
@Component
public class InjectRequestIDAdvisor extends AbstractPointcutAdvisor {
private static final long serialVersionUID = 1L;
private final StaticMethodMatcherPointcut pointcut = new StaticMethodMatcherPointcut() {
@Override
public boolean matches(Method method, Class<?> targetClass) {
return method.isAnnotationPresent(InjectRequestID.class);
}
};
@Autowired
private InjectRequestIDMethodInterceptor interceptor;
/**
* @Override
* @see org.springframework.aop.PointcutAdvisor#getPointcut() <BR>
* Method name: getPointcut <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @return <BR>
*/
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
/**
* @Override
* @see org.springframework.aop.Advisor#getAdvice() <BR>
* Method name: getAdvice <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @return <BR>
*/
@Override
public Advice getAdvice() {
return this.interceptor;
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: InjectOpIDMethodInterceptor.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.annotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月10日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.annotation;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.zhaoonline.microservice.framework.common.RequestUtils;
import com.zhaoonline.microservice.framework.support.ThreadContext;
/**
* class name:InjectOpIDMethodInterceptor <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月10日
* @author zhaoonline)yangyoupeng
*/
@Component
public class InjectRequestIDMethodInterceptor implements MethodInterceptor {
private static final Logger log = LoggerFactory.getLogger(InjectRequestIDMethodInterceptor.class);
/**
* @Override
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation) <BR>
* Method name: invoke <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param invocation
* @return
* @throws Throwable <BR>
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
InjectRequestID injectOpIDAnno= invocation.getMethod().getAnnotation(InjectRequestID.class);
if(injectOpIDAnno != null){
genThreadContextBeforeInvoker(injectOpIDAnno);
}
try{
return invocation.proceed();
}finally{
ThreadContext.removeContext();
}
}
/**
* Method name: genThreadContextBeforeInvoker <BR>
* Description: 创建与线程绑定的变量 <BR>
* Remark: <BR>
* @param injectOpIDAnno void<BR>
*/
private void genThreadContextBeforeInvoker(InjectRequestID injectOpIDAnno) {
if(ThreadContext.getContext().getRequestID() != null ){
return;
}
String prefix=injectOpIDAnno.prefix();
String uniqueRequestID=RequestUtils.nextUniqueRequestID(prefix);
ThreadContext.getContext().setRequestID(uniqueRequestID);
log.debug("Success set ThreadContext with requestID:{}",uniqueRequestID);
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: RequestUtils.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.support
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月10日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.common;
import java.util.UUID;
/**
* class name:RequestUtils <BR>
* class description: 对于 <BR>
* Remark: <BR>
* @version 1.00 2016年8月10日
* @author zhaoonline)yangyoupeng
*/
public class RequestUtils {
public static String nextUniqueRequestID(String prefix){
return prefix+nextUniqueRequestID();
}
public static String nextUniqueRequestID(){
UUID randomUUID=UUID.randomUUID();
return randomUUID.toString().replace("-", "");
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: LogCongfiguration.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.config
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月9日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.config;
/**
* class name:LogCongfiguration <BR>
* class description:该类主要供spring boot获取logsystem。我们只需要给System.property中设置Log配置文件 <BR>
* Remark: <BR>
* @version 1.00 2016年8月9日
* @author zhaoonline)yangyoupeng
*/
public class LogCongfiguration {
/**
* Method name: setLogConfigFile <BR>
* Description: setLogConfigFile 通过网System.property中设置,Log配置文件<BR>
* Remark:比如"classpath:META/log/logback.xml" <BR>
* @param key
* @param logfilelocation void<BR>
*/
public static void setLogConfigFile(String logfilelocation){
System.setProperty("logging.config", logfilelocation);
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: ServiceConfiguration.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.config
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月27日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.config;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.annotation.Configuration;
import com.alibaba.dubbo.common.utils.StringUtils;
/**
* class name:ServiceConfiguration <BR>
* class description: 依赖于spring的configuration工具<BR>
* Remark: <BR>
*
* @version 1.00 2016年7月27日
* @author zhaoonline)yangyoupeng
*/
public class ServiceConfiguration extends PropertyPlaceholderConfigurer {
private static Map<String, String> config = new HashMap<String, String>();
public static boolean getBoolean(String key, boolean defaultvalue) {
String value = config.get(key);
if (StringUtils.isNotEmpty(value)) {
return Boolean.parseBoolean(value);
}
return defaultvalue;
}
private int springSystemPropertiesMode = SYSTEM_PROPERTIES_MODE_FALLBACK;
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
throws BeansException {
super.processProperties(beanFactory, props);
for (Object key : props.keySet()) {
String keyStr = key.toString();
String valueStr = resolvePlaceholder(keyStr, props, springSystemPropertiesMode);
config.put(keyStr, valueStr);
}
}
public static Map<String, Object> getAllConfig() {
Map<String, Object> clone = new HashMap<String, Object>();
clone.putAll(config);
return clone;
}
public static void setConfig(String key, String value) {
config.put(key, value);
}
public static String delConfig(String key) {
return config.remove(key);
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: ServiceConstants.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.config
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月27日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.config;
/**
* class name:ServiceConstants <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年7月27日
* @author zhaoonline)yangyoupeng
*/
public class ServiceConstants {
/**
* APPLICATION_TYPE_WEB:TODO
*/
public static final String APPLICATION_TYPE_WEB = "isWeb";
}
package com.zhaoonline.microservice.framework.core;
import java.io.Serializable;
public class CommonRequest implements Serializable{
private static final long serialVersionUID = -1539895495785744783L;
private Context context;
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
}
package com.zhaoonline.microservice.framework.core;
import java.io.Serializable;
public class CommonRespone<T> implements Serializable{
/**
* serialVersionUID:TODO
*/
private static final long serialVersionUID = 5880594090487587787L;
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getCodeDesc() {
return codeDesc;
}
public void setCodeDesc(String codeDesc) {
this.codeDesc = codeDesc;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
private Context context;
private int code;
private String codeDesc;
private T data;
}
package com.zhaoonline.microservice.framework.core;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
public class Context implements Serializable{
/**
* serialVersionUID:TODO
*/
private static final long serialVersionUID = 8530925882829812005L;
private Map<Object,Object> map=new HashMap<>();
public Map<Object, Object> getMap() {
return map;
}
public void setMap(Map<Object, Object> map) {
this.map = map;
}
public void setProperty(Object key,Object pro){
map.put(key, pro);
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: ServiceApplication.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.core
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月27日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.core;
import java.util.concurrent.CountDownLatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.Banner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import com.zhaoonline.alpaca.config.bootstrap.AlpacaApplication;
import com.zhaoonline.microservice.framework.config.ServiceConfiguration;
import com.zhaoonline.microservice.framework.config.ServiceConstants;
/**
* class name:ServiceApplication <BR>
* class description:ServiceApplication是所有应用程序的入口<BR>
* Remark: <BR>
*
* @version 1.00 2016年7月27日
* @author zhaoonline)yangyoupeng
*/
@SpringBootApplication
public class ServiceApplication {
/**
* Method name: closeLatch <BR>
* Description: 用来作为阻塞SpringApplication关闭。程序就能持续提供服务了 <BR>
* Remark: <BR>
*
* @return CountDownLatch<BR>
*/
@Bean
public CountDownLatch closeLatch() {
return new CountDownLatch(1);
}
private static final Logger logger = LoggerFactory.getLogger(ServiceApplication.class);
public static void runAndExit(String[] args) {
boolean webEnvironment = ServiceConfiguration.getBoolean(ServiceConstants.APPLICATION_TYPE_WEB, false);
SpringApplicationBuilder builder= new SpringApplicationBuilder().sources(ServiceApplication.class).bannerMode(Banner.Mode.OFF).web(webEnvironment);
builder.registerShutdownHook(true);
ConfigurableApplicationContext context = AlpacaApplication.run(builder, args);
context.close();
System.exit(0);
}
public static void runAsDeamon(String[] args) throws InterruptedException {
boolean webEnvironment = ServiceConfiguration.getBoolean(ServiceConstants.APPLICATION_TYPE_WEB, false);
// 对于非web应用,如我们的rpc调用,此时对于服务方要设置WebEnvironmen=false;对于web应用,在加载了spring
// mvc之后,spring boot能
// 保持deamon状态持续运行。
SpringApplicationBuilder builder= new SpringApplicationBuilder().sources(ServiceApplication.class).bannerMode(Banner.Mode.OFF).web(webEnvironment);
builder.registerShutdownHook(true);
ConfigurableApplicationContext context = AlpacaApplication.run(builder, args);
CountDownLatch closeLatch = context.getBean(CountDownLatch.class);
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
closeLatch.countDown();
}
}));
closeLatch.await();
context.close();
System.exit(0);
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: Kyro.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.serialization
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月3日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.serialization;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import com.alibaba.dubbo.common.serialize.support.kryo.KryoObjectInput;
import com.alibaba.dubbo.common.serialize.support.kryo.KryoObjectOutput;
/**
* class name:Kyro <BR>
* class description:利用Kyro进行序列化操作,这里的Kyro是使用dubbox提供的Kryo <BR>
* Remark: 线程安全<BR>
* @version 1.00 2016年8月3日
* @author zhaoonline)yangyoupeng
*/
public class KryoSerialize implements ZhaoSerialize {
/**
* @Override
* @see com.zhaoonline.microservice.framework.serialization.ZhaoSerialize#serialize(java.lang.Object) <BR>
* Method name: serialize <BR>
* Description: 序列化 <BR>
* Remark: <BR>
* @param object
* @return <BR>
* @throws IOException
*/
@Override
public byte[] serialize(Object object) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
KryoObjectOutput output= new KryoObjectOutput(byteArrayOutputStream);
output.writeObject(object);
output.flushBuffer();
byte[] ser = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
return ser;
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.serialization.ZhaoSerialize#deserialize(byte[], java.lang.Class) <BR>
* Method name: deserialize <BR>
* Description: 反序列化 <BR>
* Remark: <BR>
* @param bytes
* @param clazz
* @return <BR>
* @throws IOException
* @throws ClassNotFoundException
*/
@Override
public <T> T deserialize(byte[] bytes, Class<T> clazz) throws ClassNotFoundException, IOException {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
KryoObjectInput kin = new KryoObjectInput(byteArrayInputStream);
T object= kin.readObject(clazz);
byteArrayInputStream.close();
return object;
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: ZhaoSerialize.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.serialization
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月3日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.serialization;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* class name:ZhaoSerialize <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月3日
* @author zhaoonline)yangyoupeng
*/
public interface ZhaoSerialize {
public byte[] serialize(Object object) throws IOException;
public <T> T deserialize(byte[] bytes, Class<T> clazz) throws ClassNotFoundException, IOException;
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: ThreadContext.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.support
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月10日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.support;
/**
* class name:ThreadContext <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月10日
* @author zhaoonline)yangyoupeng
*/
public class ThreadContext {
public static final ThreadLocal<ThreadContext> local=new ThreadLocal<ThreadContext>(){
@Override
protected ThreadContext initialValue() {
return new ThreadContext();
}
};
private String requestID;
/**
* Method name: getRequestID <BR>
* Description: please write your description <BR>
* @return String <BR>
*/
public String getRequestID() {
return requestID;
}
/**
* Method name: setRequestID <BR>
* Description: please write your description <BR>
* @param requestID String <BR>
*/
public void setRequestID(String requestID) {
this.requestID = requestID;
}
public static void set(ThreadContext context){
local.set(context);
}
public static ThreadContext getContext(){
return local.get();
}
/**
* Method name: removeContext <BR>
* Description: removeContext <BR>
* Remark: <BR> void<BR>
*/
public static void removeContext() {
local.remove();
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: RequestUtils.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.support
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月10日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.common;
import org.junit.Test;
import com.zhaoonline.microservice.framework.common.RequestUtils;
import org.hamcrest.core.IsEqual;
import static org.hamcrest.MatcherAssert.*;
/**
* class name:RequestUtils <BR>
* class description: 对于 <BR>
* Remark: <BR>
* @version 1.00 2016年8月10日
* @author zhaoonline)yangyoupeng
*/
public class TestRequestUtils {
@Test
public void testGenRequestID(){
String requestID=RequestUtils.nextUniqueRequestID();
System.out.println(requestID);
}
@Test
public void testGenRequestIDWithPrefix(){
String requestID=RequestUtils.nextUniqueRequestID("zhaoonline");
boolean haseprefix= requestID.startsWith("zhaoonline");
assertThat(haseprefix,IsEqual.equalTo(true));
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: TestCommand.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.core
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月2日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.core;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import com.zhaoonline.microservice.framework.annotation.DuddoSerivce;
import com.zhaoonline.microservice.framework.testannotation.DemoInterface;
/**
* class name:TestCommand <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月2日
* @author zhaoonline)yangyoupeng
*/
@Component
public class TestCommand implements CommandLineRunner,ApplicationContextAware{
ApplicationContext applicationContext=null;
@Value("${spring.application.name}")
private String applicationName;
@DuddoSerivce(name="demo",consumerId="1",consumerService=com.zhaoonline.microservice.framework.testannotation.DemoInterface.class)
private DemoInterface demo;
/**
* @Override
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) <BR>
* Method name: setApplicationContext <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param applicationContext
* @throws BeansException <BR>
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* @Override
* @see org.springframework.boot.CommandLineRunner#run(java.lang.String[]) <BR>
* Method name: run <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param args
* @throws Exception <BR>
*/
@Override
public void run(String... args) throws Exception {
System.out.println("print applicationName:"+applicationName);
System.out.println("------begin to invoke demon service");
String hello=demo.sayHello();
System.out.println("------succeed to invoke demon service,return:"+hello);
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: TestConsumerInterface.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.core
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月1日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.core;
/**
* class name:TestConsumerInterface <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月1日
* @author zhaoonline)yangyoupeng
*/
public interface TestConsumerInterface {
public String sayHello();
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: TestServiceApplication.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.core
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月2日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.core;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
/**
* class name:TestServiceApplication <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月2日
* @author zhaoonline)yangyoupeng
*/
@Configuration
@ImportResource("classpath:TestDubboServiceSpring.xml")
public class TestServiceApplication {
public static void main(String[] args) throws InterruptedException {
ServiceApplication.runAndExit(args);
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: TestServiceProvider.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.core
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月2日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.core;
import java.io.IOException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* class name:TestServiceProvider <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月2日
* @author zhaoonline)yangyoupeng
*/
public class TestServiceProvider {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"classpath:remote-provider.xml"});
context.start();
System.in.read(); // 按任意键退出
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: KyroTestObject.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.serialization
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月3日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.serialization;
/**
* class name:KyroTestObject <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月3日
* @author zhaoonline)yangyoupeng
*/
public class KyroTestObject {
private int id;
private String name;
/**
* Method name: getId <BR>
* Description: please write your description <BR>
* @return int <BR>
*/
public int getId() {
return id;
}
/**
* Method name: setId <BR>
* Description: please write your description <BR>
* @param id int <BR>
*/
public void setId(int id) {
this.id = id;
}
/**
* Method name: getName <BR>
* Description: please write your description <BR>
* @return String <BR>
*/
public String getName() {
return name;
}
/**
* Method name: setName <BR>
* Description: please write your description <BR>
* @param name String <BR>
*/
public void setName(String name) {
this.name = name;
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: Kyro.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.serialization
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月3日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.serialization;
import static org.hamcrest.MatcherAssert.assertThat;
import java.io.IOException;
import org.hamcrest.core.IsEqual;
import org.junit.Test;
/**
* class name:Kyro <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月3日
* @author zhaoonline)yangyoupeng
*/
public class TestKryoSerialize {
@Test
public void testKryoSerialize() throws IOException, ClassNotFoundException{
KryoSerialize serialize = new KryoSerialize();
KyroTestObject o = new KyroTestObject();
o.setId(1);
o.setName("Kyro Hello");
byte[] bytes=serialize.serialize(o);
KyroTestObject desr= serialize.deserialize(bytes, KyroTestObject.class);
assertThat(desr.getId(), IsEqual.equalTo(o.getId()));
}
@Test
public void testStringKryo() throws ClassNotFoundException, IOException{
KryoSerialize serialize = new KryoSerialize();
byte[] bytes =serialize.serialize("this is a test");
String actual= serialize.deserialize(bytes, String.class);
assertThat(actual, IsEqual.equalTo("this is a test"));
}
@Test
public void testBytesKryo() throws ClassNotFoundException, IOException{
KryoSerialize serialize = new KryoSerialize();
byte[] bytes =serialize.serialize("this is a test".getBytes());
byte[] actual= serialize.deserialize(bytes, byte[].class);
String actualString=new String(actual,"UTF-8");
assertThat(actualString, IsEqual.equalTo("this is a test"));
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: AnnotationDemo.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.annotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月29日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.testannotation;
import com.zhaoonline.microservice.framework.annotation.DuddoSerivce;
/**
* class name:AnnotationDemo <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年7月29日
* @author zhaoonline)yangyoupeng
*/
public class AnnotationDemo {
@DuddoSerivce(name="demo",consumerId="1",consumerService=com.zhaoonline.microservice.framework.testannotation.DemoInterface.class)
private DemoInterface demo;
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: DemoInterface.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.annotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月29日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.testannotation;
/**
* class name:DemoInterface <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年7月29日
* @author zhaoonline)yangyoupeng
*/
public interface DemoInterface {
public String sayHello();
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: DemoInterfaceImpl.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.testannotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月2日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.testannotation;
/**
* class name:DemoInterfaceImpl <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月2日
* @author zhaoonline)yangyoupeng
*/
public class DemoInterfaceImpl implements DemoInterface {
/**
* @Override
* @see com.zhaoonline.microservice.framework.testannotation.DemoInterface#sayHello() <BR>
* Method name: sayHello <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @return <BR>
*/
@Override
public String sayHello() {
return "hello wold";
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: InjectOpDemo.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.testannotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月10日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.testannotation;
import org.springframework.beans.factory.annotation.Autowired;
import com.zhaoonline.microservice.framework.annotation.InjectRequestID;
import com.zhaoonline.microservice.framework.support.ThreadContext;
/**
* class name:InjectOpDemo <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月10日
* @author zhaoonline)yangyoupeng
*/
public class InjectOpDemo {
public final static String prefix="demotest";
private String requestID;
@Autowired
private InjectOpDemo demo2;
@InjectRequestID(prefix=prefix)
public String demo(){
String request2=ThreadContext.getContext().getRequestID();
return request2;
}
/**
* Method name: getRequestID <BR>
* Description: please write your description <BR>
* @return String <BR>
*/
public String getRequestID() {
return requestID;
}
/**
* Method name: setRequestID <BR>
* Description: please write your description <BR>
* @param requestID String <BR>
*/
public void setRequestID(String requestID) {
this.requestID = requestID;
}
/**
* Method name: getDemo2 <BR>
* Description: please write your description <BR>
* @return InjectOpDemo <BR>
*/
public InjectOpDemo getDemo2() {
return demo2;
}
/**
* Method name: setDemo2 <BR>
* Description: please write your description <BR>
* @param demo2 InjectOpDemo <BR>
*/
public void setDemo2(InjectOpDemo demo2) {
this.demo2 = demo2;
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: Application.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.annotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月29日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.testannotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import static org.hamcrest.MatcherAssert.assertThat;
import org.hamcrest.core.IsInstanceOf;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.zhaoonline.microservice.framework.annotation.DuddoSerivce;
import static org.hamcrest.CoreMatchers.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations ={"classpath:testremote-consumer.xml"})
public class TestApplication implements ApplicationContextAware {
private ApplicationContext context;
@Test
public void testParseAnnotation() throws NoSuchFieldException, SecurityException{
Field[] fields =AnnotationDemo.class.getDeclaredFields();
for(Field field:fields){
Annotation annotation = field.getAnnotation(DuddoSerivce.class);
assertThat("the annotation is not null",annotation,IsInstanceOf.instanceOf(DuddoSerivce.class));
DuddoSerivce appAnn= (DuddoSerivce)annotation;
assertThat("Application annotation name ",appAnn.name(),is("demo"));
assertThat("Application annotation serivceInt ",appAnn.consumerService().getTypeName(),is(DemoInterface.class.getTypeName()));
}
}
@Test
public void testInjectConsumerServiceFromDubbo() throws IllegalArgumentException, IllegalAccessException{
RegistryConfig registry =(RegistryConfig) context.getBean("testregistry");
System.out.println(registry.getAddress());
Field[] fields =AnnotationDemo.class.getDeclaredFields();
Field theField = fields[0];
Annotation annotation = theField.getAnnotation(DuddoSerivce.class);
DuddoSerivce appAnn= (DuddoSerivce)annotation;
String applicationName= appAnn.name();
ApplicationConfig application = new ApplicationConfig();
application.setName(applicationName);
Class<?> clazz =appAnn.consumerService();
ReferenceConfig<?> reference = new ReferenceConfig<Object>(); // 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
reference.setApplication(application);
reference.setRegistry(registry); // 多个注册中心可以用setRegistries()
reference.setInterface(clazz);
reference.setVersion("1.0.0");
theField.set(new AnnotationDemo(), reference.get());
}
/**
* @Override
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) <BR>
* Method name: setApplicationContext <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param applicationContext
* @throws BeansException <BR>
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: Test.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.annotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月1日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.testannotation;
import org.springframework.context.annotation.ComponentScan;
/**
* class TestConfiguration <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月1日
* @author zhaoonline)yangyoupeng
*/
@ComponentScan("com.zhaoonline.microservice.framework.annotation")
public class TestConfiguration {
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: TestApplicationAnnotationProcessor.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.annotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月1日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.testannotation;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.ContextHierarchy;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.zhaoonline.microservice.framework.annotation.DuddoSerivce;
/**
* class name:TestApplicationAnnotationProcessor <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月1日
* @author zhaoonline)yangyoupeng
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextHierarchy({
@ContextConfiguration(classes={TestConfiguration.class}),
@ContextConfiguration(locations ={"classpath:testremote-consumer.xml"}),
})
public class TestDubboServiceAnnotationProcessor implements ApplicationContextAware {
private final String applicationName="demo";
@DuddoSerivce(name=applicationName,consumerId="1",consumerService=com.zhaoonline.microservice.framework.testannotation.DemoInterface.class)
private DemoInterface demo;
@Test
public void testGetApplicationName(){
demo.sayHello();
}
/**
* @Override
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) <BR>
* Method name: setApplicationContext <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param applicationContext
* @throws BeansException <BR>
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: TestApplicationAnnotationProcessorWithXML.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.testannotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月1日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.testannotation;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.ContextHierarchy;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.zhaoonline.microservice.framework.annotation.DuddoSerivce;
/**
* class name:TestApplicationAnnotationProcessorWithXML <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月1日
* @author zhaoonline)yangyoupeng
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextHierarchy({
@ContextConfiguration(locations ={"classpath:TestDubboServiceSpring.xml"}),
})
public class TestDubboServiceAnnotationProcessorWithXML {
private final String applicationName="demo";
//这个过程获取reference中,若service尚未就绪,那么就会抛出异常
@DuddoSerivce(name=applicationName,consumerId="1",consumerService=com.zhaoonline.microservice.framework.testannotation.DemoInterface.class)
private DemoInterface demo;
@Test
public void testGetApplicationName(){
// assertThat(demo, IsNull.notNullValue());
String hello=demo.sayHello();
System.out.println("------succeed to invoke demon service,return:"+hello);
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: TestInjectOpID.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.testannotation
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月10日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.testannotation;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.zhaoonline.microservice.framework.annotation.InjectRequestID;
import com.zhaoonline.microservice.framework.annotation.InjectRequestIDAdvisor;
import com.zhaoonline.microservice.framework.annotation.InjectRequestIDMethodInterceptor;
import com.zhaoonline.microservice.framework.support.ThreadContext;
/**
* class name:TestInjectOpID <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月10日
* @author zhaoonline)yangyoupeng
*/
@Configuration
@EnableAspectJAutoProxy
@EnableAutoConfiguration
@ComponentScan(basePackageClasses={InjectRequestID.class,InjectRequestIDAdvisor.class,InjectRequestIDMethodInterceptor.class,TestInjectOpID.class,InjectOpDemo.class})
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-test.xml")
public class TestInjectOpID {
@Bean
public InjectOpDemo demo(){
return new InjectOpDemo();
}
@Bean
public InjectOpDemo demo2(){
return new InjectOpDemo();
}
InjectOpDemo demoRef=null;
@Before
public void prepare(){
SpringApplication app = new SpringApplication(TestInjectOpID.class);
app.setRegisterShutdownHook(false);
app.setWebEnvironment(false);
ConfigurableApplicationContext context= app.run("aa","aaa");
demoRef= (InjectOpDemo) context.getBean("demo");
Assert.assertNotNull(demoRef);
}
@Test
public void testGetThreadContext(){
//该调用之前会有进入InjectOpIDMethodInterceptor的
String requestID =demoRef.demo();
boolean requestMatches=requestID.startsWith(InjectOpDemo.prefix);
Assert.assertEquals(true, requestMatches);
}
@Test
public void testContextDestoryAfterInvoker(){
//该调用之前会有进入InjectOpIDMethodInterceptor的
String requestID =demoRef.demo();
boolean requestMatches=requestID.startsWith(InjectOpDemo.prefix);
Assert.assertEquals(true, requestMatches);
ThreadContext threadContext=ThreadContext.getContext();
Assert.assertNull(threadContext);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<import resource="classpath:testremote-consumer.xml"/>
<context:component-scan base-package="com.zhaoonline.microservice.framework.annotation">
</context:component-scan>
</beans>
\ No newline at end of file
spring.application.name=mircoservice
zhao.cloud.zookeeper.connectString=192.168.0.205:2181
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
">
<dubbo:application name="demo" />
<dubbo:registry address="multicast://224.5.6.7:1234" />
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:service interface="com.zhaoonline.microservice.framework.testannotation.DemoInterface" ref="helloworld" token="123456"/>
<bean id="helloworld" class="com.zhaoonline.microservice.framework.testannotation.DemoInterfaceImpl" />
</beans>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--
<context:component-scan base-package="com.zhaoonline.message.queue" />
-->
</beans>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:registry id="defaultRegistry" address="multicast://224.5.6.7:1234" />
<dubbo:registry id="testregistry" address="multicast://224.5.6.7:1234" />
</beans>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<fileset-config file-format-version="1.2.0" simple-config="false" sync-formatter="false">
<local-check-config name="maven-checkstyle-plugin checkstyle" location="file:/D:/yangyoupeng/工作/micro/finance/src/microservice-parent/microservice-framework-monitor/src/test/resources/codequality/checkstyle.xml" type="remote" description="maven-checkstyle-plugin configuration checkstyle">
<property name="checkstyle.cache.file" value="${project_loc}/target/checkstyle-cachefile"/>
<property name="checkstyle.header.file" value="D:\workspaces\work1\.metadata\.plugins\org.eclipse.core.resources\.projects\microservice-framework-monitor\com.basistech.m2e.code.quality.checkstyleConfigurator\checkstyle-header-checkstyle.txt"/>
</local-check-config>
<fileset name="java-sources-checkstyle" enabled="true" check-config-name="maven-checkstyle-plugin checkstyle" local="true">
<file-match-pattern match-pattern="^src/main/java/.*\.java" include-pattern="true"/>
<file-match-pattern match-pattern="^src/main/resources/.*\.properties" include-pattern="true"/>
<file-match-pattern match-pattern="^src/test/resources/.*\.properties" include-pattern="true"/>
</fileset>
</fileset-config>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.zhaoonline</groupId>
<artifactId>microservice-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>microservice-framework-monitor</artifactId>
<dependencies>
<dependency>
<groupId>com.zhaoonline</groupId>
<artifactId>microservice-framework-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<!-- logback-access for Servlet containers -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
</dependency>
<!-- logback-classic for Log4J or SLF4j -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<!-- logback-core is the underline,it is the groundwork for the access
and classic module -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.17</version>
<configuration>
<configLocation>src/test/resources/codequality/checkstyle.xml</configLocation>
</configuration>
<executions>
<execution>
<id>checkstyle</id>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<!--failOnViolation设置违背checkstyle时候是否要 build false.若设置为true的时候就会build fail -->
<failOnViolation>false</failOnViolation>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: TraceFilter.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.dubbo
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月28日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.dubbo;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.remoting.TimeoutException;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.RpcInvocation;
import com.zhaoonline.microservice.framework.monitor.trace.BinaryAnnotation;
import com.zhaoonline.microservice.framework.monitor.trace.Endpoint;
import com.zhaoonline.microservice.framework.monitor.trace.Span;
import com.zhaoonline.microservice.framework.monitor.trace.Tracer;
import com.zhaoonline.microservice.framework.monitor.trace.TracerUtils;
/**
* class name:TraceFilter <BR>
* class description:完成服务跟踪的Filter <BR>
* Remark: <BR>
* @version 1.00 2016年7月28日
* @author zhaoonline)yangyoupeng
*/
@Activate(group = {Constants.PROVIDER, Constants.CONSUMER})
public class ZhaotraceFilter implements Filter{
//这里的Tracer是通过SpringIOC来注入的
private Tracer tracer = null;
/**
* @Override
* @see com.alibaba.dubbo.rpc.Filter#invoke(com.alibaba.dubbo.rpc.Invoker, com.alibaba.dubbo.rpc.Invocation) <BR>
* Method name: invoke <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param invoker
* @param invocation
* @return
* @throws RpcException <BR>
*/
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
//异步获取serviceId,没获取到不进行采样
String serviceInterface=RpcContext.getContext().getUrl().getServiceInterface();
String serviceId= tracer.getServiceId(serviceInterface);
if (serviceId == null) {
Tracer.startTraceWork();
return invoker.invoke(invocation);
}
long start = System.currentTimeMillis();
RpcContext context = RpcContext.getContext();
boolean isConsumerSide = context.isConsumerSide();
Span span = null;
Endpoint endpoint = null;
try {
endpoint = tracer.newEndPoint();
// endpoint.setServiceName(serviceId);
endpoint.setIp(context.getLocalAddressString());
endpoint.setPort(context.getLocalPort());
if (context.isConsumerSide()) { //是否是消费者
Span span1 = tracer.getParentSpan();
if (span1 == null) { //为rootSpan
span = tracer.newSpan(context.getMethodName(), endpoint, serviceId);//生成root Span
} else {
span = tracer.genSpan(span1.getTraceId(), span1.getId(), tracer.genSpanId(), context.getMethodName(), span1.isSample(), null,span1.getRequestid(),span1.getStepSeq());
}
} else if (context.isProviderSide()) {
Long traceId, parentId, spanId;
traceId = TracerUtils.getAttachmentLong(invocation.getAttachment(TracerUtils.TID));
parentId = TracerUtils.getAttachmentLong(invocation.getAttachment(TracerUtils.PID));
spanId = TracerUtils.getAttachmentLong(invocation.getAttachment(TracerUtils.SID));
String requestID = TracerUtils.getAttachmentString(invocation.getAttachment(TracerUtils.REQID));
int stepSeq = TracerUtils.getAttachmentInt(invocation.getAttachment(TracerUtils.STEPSEQ));
boolean isSample = (traceId != null);
span = tracer.genSpan(traceId, parentId, spanId, context.getMethodName(), isSample, serviceId,requestID,stepSeq);
}
invokerBefore(invocation, span, endpoint, start);//记录annotation
RpcInvocation invocation1 = (RpcInvocation) invocation;
setAttachment(span, invocation1);//设置需要向下游传递的参数
Result result = invoker.invoke(invocation);
if (result.getException() != null){
catchException(result.getException(), endpoint);
}
return result;
}catch (RpcException e) {
if (e.getCause() != null && e.getCause() instanceof TimeoutException){
catchTimeoutException(e, endpoint);
}else {
catchException(e, endpoint);
}
throw e;
}finally {
if (span != null) {
long end = System.currentTimeMillis();
invokerAfter(invocation, endpoint, span, end, isConsumerSide);//调用后记录annotation
}
}
}
private void catchTimeoutException(RpcException e, Endpoint endpoint) {
BinaryAnnotation exAnnotation = new BinaryAnnotation();
exAnnotation.setKey(TracerUtils.EXCEPTION);
exAnnotation.setValue(e.getMessage());
exAnnotation.setType("exTimeout");
exAnnotation.setHost(endpoint);
tracer.addBinaryAnntation(exAnnotation);
}
private void catchException(Throwable e, Endpoint endpoint) {
BinaryAnnotation exAnnotation = new BinaryAnnotation();
exAnnotation.setKey(TracerUtils.EXCEPTION);
exAnnotation.setValue(e.getMessage());
exAnnotation.setType("ex");
exAnnotation.setHost(endpoint);
tracer.addBinaryAnntation(exAnnotation);
}
private void setAttachment(Span span, RpcInvocation invocation) {
if (span.isSample()) {
invocation.setAttachment(TracerUtils.PID, span.getParentId() != null ? String.valueOf(span.getParentId()) : null);
invocation.setAttachment(TracerUtils.SID, span.getId() != null ? String.valueOf(span.getId()) : null);
invocation.setAttachment(TracerUtils.TID, span.getTraceId() != null ? String.valueOf(span.getTraceId()) : null);
invocation.setAttachment(TracerUtils.REQID, span.getRequestid());
invocation.setAttachment(TracerUtils.STEPSEQ,String.valueOf(span.getStepSeq()));
}
}
private void invokerAfter(Invocation invocation, Endpoint endpoint, Span span, long end, boolean isConsumerSide) {
if (isConsumerSide && span.isSample()) {
tracer.clientReceiveRecord(span, endpoint, end);
} else {
if (span.isSample()) {
tracer.serverSendRecord(span, endpoint, end);
}
tracer.removeParentSpan();
}
}
private void invokerBefore(Invocation invocation, Span span, Endpoint endpoint, long start) {
RpcContext context = RpcContext.getContext();
if (context.isConsumerSide() && span.isSample()) {
tracer.clientSendRecord(span, endpoint, start);
} else if (context.isProviderSide()) {
if (span.isSample()) {
//对于stepSeq的递增的操作放在provider端ServerReceiver之后接收到调用请求之后。
incrementStepSeq(span);
tracer.serverReceiveRecord(span, endpoint, start);
}
tracer.setParentSpan(span);
}
}
/**
* Method name: incrementStepSeq <BR>
* Description: incrementStepSeq <BR>
* Remark: <BR>
* @param span void<BR>
*/
private void incrementStepSeq(Span span) {
int incrementStepSeq=span.getStepSeq()+1;
span.setStepSeq(incrementStepSeq);
}
public Tracer getTracer() {
return tracer;
}
public void setTracer(Tracer tracer) {
this.tracer = tracer;
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: ElasticClient.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.es
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月10日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.es;
import java.net.InetSocketAddress;
import java.util.Map;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
/**
* class name:ElasticClient <BR>
* class description: ElasticClient 工厂 <BR>
* Remark: <BR>
* @version 1.00 2016年8月10日
* @author zhaoonline)yangyoupeng
*/
public final class ElasticClientFactory {
/**
* Method name: ElasticClientFactory<BR>
* Description: Utility classes should not have a public or default constructor<BR>
* Remark: <BR> <BR>
*/
private ElasticClientFactory(){
}
/**
* Method name: createClient <BR>
* Description: 根据configuration来创建client <BR>
* Remark: <BR>
* @param config
* @return TransportClient<BR>
*/
public static TransportClient createClient(ElasticConfiguration config){
Settings settings =Settings.settingsBuilder().put(ElasticConfiguration.KEY_CLINET_TRANSPORT_SNIFF,config.isClienttransportsniff())
.put(ElasticConfiguration.KEY_CLUSTER_NAME,config.getClusterName())
.build();
TransportClient client = TransportClient.builder().settings(settings).build();
for(Map.Entry<String, Integer> hostPort:config.getHostPorts().entrySet()){
client.addTransportAddress(new InetSocketTransportAddress(new InetSocketAddress(hostPort.getKey(),hostPort.getValue())));
}
return client;
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: ElasticConfiguration.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.es
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年8月10日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.es;
import java.util.Map;
/**
* class name:ElasticConfiguration <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年8月10日
* @author zhaoonline)yangyoupeng
*/
public class ElasticConfiguration {
public static final String KEY_CLINET_TRANSPORT_SNIFF="client.transport.sniff";
public static final String KEY_CLUSTER_NAME="cluster.name";
private boolean clienttransportsniff=false;
private String clusterName;
private Map<String,Integer> hostPorts;
/**
* Method name: isClienttransportsniff <BR>
* Description: please write your description <BR>
* @return boolean <BR>
*/
public boolean isClienttransportsniff() {
return clienttransportsniff;
}
/**
* Method name: setClienttransportsniff <BR>
* Description: please write your description <BR>
* @param clienttransportsniff boolean <BR>
*/
public void setClienttransportsniff(boolean clienttransportsniff) {
this.clienttransportsniff = clienttransportsniff;
}
/**
* Method name: getClusterName <BR>
* Description: please write your description <BR>
* @return String <BR>
*/
public String getClusterName() {
return clusterName;
}
/**
* Method name: setClusterName <BR>
* Description: please write your description <BR>
* @param clusterName String <BR>
*/
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
/**
* Method name: getHostPorts <BR>
* Description: please write your description <BR>
* @return Map<String,Integer> <BR>
*/
public Map<String, Integer> getHostPorts() {
return hostPorts;
}
/**
* Method name: setHostPorts <BR>
* Description: please write your description <BR>
* @param hostPorts Map<String,Integer> <BR>
*/
public void setHostPorts(Map<String, Integer> hostPorts) {
this.hostPorts = hostPorts;
}
}
package com.zhaoonline.microservice.framework.monitor.repo;
import java.util.List;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* class name:AppServiceRepo <BR>
* class descriptionn:再ES中的appService的索引存储格式: { "appId":****, "appName":****
* "serviceId":****, "serviceName":**** }
* <BR>
* Remark: <BR>
*
* @version 1.00 2016年8月12日
* @author zhaoonline)yangyoupeng
*/
public class AppServiceRepo {
private static final Logger LOGGER = LoggerFactory.getLogger(AppServiceRepo.class);
public static final String APPSERVICE_INDEX = "monitor";
public static final String APPSERVICE_APPSERVICE_TYPE = "appservice";
public static final String KEY_APPSERVICES_SERVICENAME = "serviceName";
public static final String KEY_APPSERVICES_SERVICEID = "serviceId";
public static final String KEY_APP_ID = "appId";
public static final String KEY_APP_NAME = "appName";
private TransportClient client;
public TransportClient getClient() {
return client;
}
public void setClient(TransportClient client) {
this.client = client;
}
/**
* Method name: getAppId <BR>
* Description: 根据AppName查询ES获取对应AppID <BR>
* Remark: <BR>
*
* @param appName
* @return String<BR>
*/
public String getAppId(String appName) {
SearchResponse searchRes = client.prepareSearch(APPSERVICE_INDEX).setTypes(APPSERVICE_APPSERVICE_TYPE)
.addFields(KEY_APP_ID, KEY_APP_NAME).setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
// .setQuery(QueryBuilders.matchAllQuery())
// 我们不需要query,只需要进行term过滤
.setPostFilter(QueryBuilders.termQuery(KEY_APP_NAME, appName)).setFrom(0).setSize(1).execute()
.actionGet();
SearchHits hits = searchRes.getHits();
if (hits.getTotalHits() != 0) {
SearchHit hit = hits.getAt(0);
Object serviceID=getFirstValue(KEY_APP_ID,hit);
return String.valueOf(serviceID);
}
return null;
}
/**
* Method name: getServiceId <BR>
* Description: 一个App下面有多个Service,根据appName和ServiceName来查询ServiceID <BR>
* Remark: <BR>
*
* @param serviceName
* @return String<BR>
*/
public String getServiceId(String serviceName, String appName) {
SearchResponse searchRes = client.prepareSearch(APPSERVICE_INDEX).setTypes(APPSERVICE_APPSERVICE_TYPE)
.addFields(KEY_APPSERVICES_SERVICEID, KEY_APPSERVICES_SERVICENAME)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setPostFilter(QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery(KEY_APPSERVICES_SERVICENAME, serviceName))
.must(QueryBuilders.termQuery(KEY_APP_NAME, appName))
)
.setFrom(0).setSize(1).execute().actionGet();
SearchHits hits = searchRes.getHits();
if (hits.getTotalHits() != 0) {
SearchHit hit = hits.getAt(0);
Object serviceID=getFirstValue(KEY_APPSERVICES_SERVICEID,hit);
return String.valueOf(serviceID);
}
return null;
}
private Object getFirstValue(String fieldName,SearchHit hit){
List<Object> seedValFiedlist=hit.getFields().get(fieldName).getValues();
if(seedValFiedlist!=null && seedValFiedlist.size()!=0){
return seedValFiedlist.get(0);
}
return seedValFiedlist;
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: ESMetaInfoRepositoryService.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.repo
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月28日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.repo;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* class name:ESMetaInfoRepositoryService <BR>
* class description:ES作为最终元数据信息存储的仓库,该类要作为dubbox服务来封装起来<BR>
* Remark: <BR>
* @version 1.00 2016年7月28日
* @author zhaoonline)yangyoupeng
*/
public class ESMetaInfoRepositoryService implements MetaInfoRepositoryService {
private SeedRepo seedRep;
private AppServiceRepo appserRepo;
public SeedRepo getSeedRep() {
return seedRep;
}
public void setSeedRep(SeedRepo seedRep) {
this.seedRep = seedRep;
}
public AppServiceRepo getAppserRepo() {
return appserRepo;
}
public void setAppserRepo(AppServiceRepo appserRepo) {
this.appserRepo = appserRepo;
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.repo.MetaInfoRepositoryService#registerClient(java.lang.String, java.util.List) <BR>
* Method name: registerClient <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param appname
* @param services
* @return <BR>
*/
public Map<String, String> registerClient(String appname, List<String> services) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("seed", seedRep.searchSead().toString());
map.put(appname, appserRepo.getAppId(appname));
for (String serviceName : services) {
map.put("serviceName", appserRepo.getServiceId(serviceName, appname));
}
return map;
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.repo.MetaInfoRepositoryService#registerClient(java.lang.String, java.lang.String) <BR>
* Method name: registerClient <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param appName
* @param serviceName
* @return <BR>
*/
public String registerClient(String appName, String serviceName) {
// TODO Auto-generated method stub
return appserRepo.getServiceId(serviceName, appName);
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: ESSpanInfoRepositoryService.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.repo
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月28日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.repo;
import java.util.List;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhaoonline.microservice.framework.monitor.trace.Absannotation;
import com.zhaoonline.microservice.framework.monitor.trace.Annotation;
import com.zhaoonline.microservice.framework.monitor.trace.BinaryAnnotation;
import com.zhaoonline.microservice.framework.monitor.trace.Span;
import com.zhaoonline.microservice.framework.monitor.trace.Trace;
/**
* class name:ESSpanInfoRepositoryService <BR>
* class description: 将Span info写入到Elasticsearch当中 <BR>
* Remark: <BR>
* @version 1.00 2016年7月28日
* @author zhaoonline)yangyoupeng
*/
public class ESSpanInfoRepositoryService implements SpanInfoRepositoryService{
private static Logger logger = LoggerFactory.getLogger(ESSpanInfoRepositoryService.class);
private TransportClient client;
private static final String INDEX="monitor";
private static final String SPAN_TYPE="span";
private static final String TRACE_TYPE="trace";
private static final String ANNOTATION_TYPE="annotation";
private static ObjectMapper mapper = new ObjectMapper();
public TransportClient getClient() {
return client;
}
public void setClient(TransportClient client) {
this.client = client;
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.repo.SpanInfoRepositoryService#push(java.util.List) <BR>
* Method name: push <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param spanList <BR>
*/
public void push(List<Span> spanList) {
for (Span s : spanList) {
addSpan(s);
addTrace(s);
addAnnotation(s);
}
}
private void addSpan(Span span) {
if (span.getServiceId() != null) {
if (!Utils.isRoot(span) || Utils.isRoot(span) && Utils.isTopAnntation(span)) {
logger.info("Span[name:{},traceId:{},parentId:{},spanId:{},service:{}]", span.getSpanName(),
span.getTraceId(), span.getParentId(), span.getId(), span.getServiceId());
try {
byte[] json = mapper.writeValueAsBytes(span);
IndexResponse response= client.prepareIndex(INDEX, SPAN_TYPE).setSource(json).get();
} catch (JsonProcessingException e) {
logger.error("fail to write span:{} ",span);
e.printStackTrace();
}
}
}
}
private void addTrace(Span span) {
if (Utils.isTopAnntation(span) && Utils.isRoot(span)) {
Annotation annotation = Utils.getCrAnnotation(span.getAnnotations());
Annotation annotation1 = Utils.getCsAnnotation(span.getAnnotations());
Trace t = new Trace();
t.setTraceId(span.getTraceId());
t.setDuration((int) (annotation.getTimestamp() - annotation1.getTimestamp()));
t.setService(span.getServiceId());
t.setTime(annotation1.getTimestamp());
logger.info("Trace:[time:{},traceId:{},duration:{},service:{}]", t.getTime(), t.getTraceId(),
t.getDuration(), t.getService());
try {
byte[] json= mapper.writeValueAsBytes(t);
IndexResponse response= client.prepareIndex(INDEX, TRACE_TYPE).setSource(json).get();
} catch (JsonProcessingException e) {
logger.error("fail to write trace:{} of spanId:{}",t,span.getId());
e.printStackTrace();
}
}
}
private void addAnnotation(Span span) {
for (Annotation a : span.getAnnotations()) {
Absannotation aa = new Absannotation(a, span);
logger.info(
"Annotation:[key:{},value:{},ip:{},port:{},timestamp:{},duration:{},spanId:{},traceId:{},service:{}]",
aa.getKey(), aa.getValue(), aa.getIp(), aa.getPort(), aa.getTimestamp(), aa.getDuration(),
aa.getSpanId(), aa.getTraceId(), aa.getService());
try {
byte[] json = mapper.writeValueAsBytes(aa);
IndexResponse response= client.prepareIndex(INDEX, ANNOTATION_TYPE).setSource(json).get();
} catch (JsonProcessingException e) {
e.printStackTrace();
logger.error("fail to write annotition of span:{}",span);
}
}
for (BinaryAnnotation b : span.getBinaryAnnotations()) {
Absannotation bb = new Absannotation(b, span);
logger.info(
"BinaryAnnotation:[key:{},value:{},ip:{},port:{},timestamp:{},duration:{},spanId:{},traceId:{},service:{}]",
bb.getKey(), bb.getValue(), bb.getIp(), bb.getPort(), bb.getTimestamp(), bb.getDuration(),
bb.getSpanId(), bb.getTraceId(), bb.getService());
try {
byte[] json = mapper.writeValueAsBytes(bb);
IndexResponse response= client.prepareIndex(INDEX, ANNOTATION_TYPE).setSource(json).get();
} catch (JsonProcessingException e) {
logger.error("fail to write binaryAnnotition of span:{}",span);
e.printStackTrace();
}
}
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: LogSpanInfoRepositoryService.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.repo
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月28日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.repo;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zhaoonline.microservice.framework.monitor.trace.Absannotation;
import com.zhaoonline.microservice.framework.monitor.trace.Annotation;
import com.zhaoonline.microservice.framework.monitor.trace.BinaryAnnotation;
import com.zhaoonline.microservice.framework.monitor.trace.Span;
import com.zhaoonline.microservice.framework.monitor.trace.Trace;
/**
* class name:LogSpanInfoRepositoryService <BR>
* class description:Span的Log输出 <BR>
* Remark: <BR>
*
* @version 1.00 2016年7月28日
* @author zhaoonline)yangyoupeng
*/
public class LogSpanInfoRepositoryService implements SpanInfoRepositoryService {
private static Logger LOGGER = LoggerFactory.getLogger(LogSpanInfoRepositoryService.class);
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.repo.SpanInfoRepositoryService#push(java.util.List)
* <BR>
* Method name: push <BR>
* Description: <BR>
* Remark: <BR>
* @param spanList
* <BR>
*/
public void push(List<Span> spanList) {
for (Span s : spanList) {
addSpan(s);
addTrace(s);
addAnnotation(s);
}
}
private void addSpan(Span span) {
if (span.getServiceId() != null) {
if (!Utils.isRoot(span) || Utils.isRoot(span) && Utils.isTopAnntation(span)) {
LOGGER.info("Span[name:{},traceId:{},parentId:{},spanId:{},service:{}]", span.getSpanName(),
span.getTraceId(), span.getParentId(), span.getId(), span.getServiceId());
}
}
}
private void addTrace(Span span) {
if (Utils.isTopAnntation(span) && Utils.isRoot(span)) {
Annotation annotation = Utils.getCrAnnotation(span.getAnnotations());
Annotation annotation1 = Utils.getCsAnnotation(span.getAnnotations());
Trace t = new Trace();
t.setTraceId(span.getTraceId());
t.setDuration((int) (annotation.getTimestamp() - annotation1.getTimestamp()));
t.setService(span.getServiceId());
t.setTime(annotation1.getTimestamp());
LOGGER.info("Trace:[time:{},traceId:{},duration:{},service:{}]", t.getTime(), t.getTraceId(),
t.getDuration(), t.getService());
}
}
private void addAnnotation(Span span) {
for (Annotation a : span.getAnnotations()) {
Absannotation aa = new Absannotation(a, span);
LOGGER.info(
"Annotation:[key:{},value:{},ip:{},port:{},timestamp:{},duration:{},spanId:{},traceId:{},service:{}]",
aa.getKey(), aa.getValue(), aa.getIp(), aa.getPort(), aa.getTimestamp(), aa.getDuration(),
aa.getSpanId(), aa.getTraceId(), aa.getService());
}
for (BinaryAnnotation b : span.getBinaryAnnotations()) {
Absannotation bb = new Absannotation(b, span);
LOGGER.info(
"BinaryAnnotation:[key:{},value:{},ip:{},port:{},timestamp:{},duration:{},spanId:{},traceId:{},service:{}]",
bb.getKey(), bb.getValue(), bb.getIp(), bb.getPort(), bb.getTimestamp(), bb.getDuration(),
bb.getSpanId(), bb.getTraceId(), bb.getService());
}
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: RegisterInfoService.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.service
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月28日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.repo;
import java.util.List;
import java.util.Map;
/**
* class MetaInfoRepositoryService <BR>
* class description: 这是一个查询所有注册信息的service。根据appName对应的所有serviceName信息来获取到serviceID <BR>
* Remark: <BR>
* @version 1.00 2016年7月28日
* @author zhaoonline)yangyoupeng
*/
public interface MetaInfoRepositoryService {
/**
* Method name: registerClient <BR>
* Description: registerClient <BR>
* Remark: <BR>
* @param name
* @param services
* @return Map<String,String><BR>
*/
Map<String, String> registerClient(String appname, List<String> services);
/**
* Method name: registerClient <BR>
* Description: registerClient <BR>
* Remark: <BR>
* @param appName
* @param serviceName
* @return String<BR>
*/
String registerClient(String appName, String serviceName);
}
package com.zhaoonline.microservice.framework.monitor.repo;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* class name:SeedRepo <BR>
* class description: 所谓seed的就是在创建每一个traceid或者spanid的时候,都需要一个seed来初始化相应的id,这样就避免了id重复 <BR>
* Remark: <BR>
* @version 1.00 2016年8月26日
* @author zhaoonline)yangyoupeng
*/
public class SeedRepo {
private static final Logger LOGGER = LoggerFactory.getLogger(SeedRepo.class);
private static final Long DEFAULT_SEED_VALUE=100L;
public static final String SEED_INDEX="monitor";
public static final String SEED_TYPE="seed";
public static final String SEED_ID="seedId";
public static final String SEED_VALUE="seedVal";
private TransportClient client;
public TransportClient getClient() {
return client;
}
public void setClient(TransportClient client) {
this.client = client;
}
/**
* Method name: searchSead <BR>
* Description: 查询获取seed,这里是去查询Elasticsearch中查询index=monitor,type=seed的最大seedVal值 <BR>
* Remark: <BR>
* @return Long<BR>
*/
public Long searchSead(){
Long seedValue=-1L;
SearchResponse searchRes=client.prepareSearch(SEED_INDEX).setTypes(SEED_TYPE).addFields(SEED_ID,SEED_VALUE)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(QueryBuilders.matchAllQuery()).addSort(SEED_VALUE,SortOrder.DESC)
.setFrom(0).setSize(1)
.execute()
.actionGet();
SearchHits hits = searchRes.getHits();
if(hits.getTotalHits()!=0){
SearchHit hit= hits.getAt(0);
List<Object> seedValFiedlist=hit.getFields().get(SEED_VALUE).getValues();
if(seedValFiedlist!=null && seedValFiedlist.size()!=0){
Object seedVal=seedValFiedlist.get(0);
seedValue = Long.valueOf(""+seedVal);
}
}
if(seedValue ==-1){
//返回默认值
seedValue = DEFAULT_SEED_VALUE;
}
//seadValue进行递增后再插入到ES中去
Long plusedValue = seedValue + 1;
Map<String,Object> object=new HashMap<>();
object.put(SEED_VALUE, plusedValue);
// object.put(SEED_ID, 你设定的ID);ID的值由Elasticsearch自动创建,ES自动创建的ID是一个UUID,目前没有自增的ID?
try {
IndexResponse response= client.prepareIndex(SEED_INDEX, SEED_TYPE).setSource(object).execute().get();
} catch (InterruptedException | ExecutionException e) {
LOGGER.error("fail to index need seed info into es,because {}",e.getMessage());
e.printStackTrace();
}
return seedValue;
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: SpanRepositoryService.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.service
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月28日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.repo;
import java.util.List;
import com.zhaoonline.microservice.framework.monitor.trace.Span;
/**
* class name:SpanRepositoryService <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年7月28日
* @author zhaoonline)yangyoupeng
*/
public interface SpanInfoRepositoryService {
/**
* Method name: push <BR>
* Description: push <BR>
* Remark: <BR>
* @param spanList void<BR>
*/
public void push(List<Span> spanList);
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: Utils.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.repo
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月28日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.repo;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import com.zhaoonline.microservice.framework.monitor.trace.Annotation;
import com.zhaoonline.microservice.framework.monitor.trace.Span;
/**
* class name:Utils <BR>
* class description: cs、cr、ss、sr分别表示:client send,clinet receive,server send,server receive <BR>
* Remark: <BR>
*
* @version 1.00 2016年7月28日
* @author zhaoonline)yangyoupeng
*/
public final class Utils {
private Utils() {
}
/**
* Method name: isTopAnntation <BR>
* Description: isTopAnntation <BR>
* Remark: <BR>
* @param span
* @return boolean<BR>
*/
public static boolean isTopAnntation(Span span) {
List<Annotation> alist = span.getAnnotations();
boolean isfirst = false;
for (Annotation a : alist) {
if (StringUtils.endsWithIgnoreCase("cs", a.getValue())) {
isfirst = true;
}
}
return isfirst;
}
/**
* Method name: getCsAnnotation <BR>
* Description: getCsAnnotation <BR>
* Remark: <BR>
* @param alist
* @return Annotation<BR>
*/
public static Annotation getCsAnnotation(List<Annotation> alist) {
for (Annotation a : alist) {
if (StringUtils.endsWithIgnoreCase("cs", a.getValue())) {
return a;
}
}
return null;
}
/**
* Method name: getCrAnnotation <BR>
* Description: getCrAnnotation <BR>
* Remark: <BR>
* @param alist
* @return Annotation<BR>
*/
public static Annotation getCrAnnotation(List<Annotation> alist) {
for (Annotation a : alist) {
if (StringUtils.endsWithIgnoreCase("cr", a.getValue())) {
return a;
}
}
return null;
}
/**
* Method name: isRoot <BR>
* Description: 判断是否是root Span <BR>
* Remark: <BR>
* @param span
* @return boolean<BR>
*/
public static boolean isRoot(Span span) {
return span.getParentId() == null;
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: CollectorService.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.service
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月28日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.service;
import java.util.List;
import com.zhaoonline.microservice.framework.monitor.trace.Span;
/**
* class name:CollectorService <BR>
* class description:这是collectservice结构 <BR>
* Remark: <BR>
* @version 1.00 2016年7月28日
* @author zhaoonline)yangyoupeng
*/
public interface CollectorService {
/**
* Method name: sendSpan <BR>
* Description: 发送span <BR>
* Remark: <BR>
* @param spanList void<BR>
*/
public void sendSpan(List<Span> spanList);
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: Configuration.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.service
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月28日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.service;
import java.util.ArrayList;
import java.util.List;
/**
* class name:Configuration <BR>
* class description: 配置类 <BR>
* Remark: <BR>
* @version 1.00 2016年7月28日
* @author zhaoonline)yangyoupeng
*/
public class Configuration {
private String applicationName;
private List<String> services;
private Long delayTime; //保留字段,延迟多久发送一批到收集端
private Long flushSize;//保留字段,一批发送多少条消息到收集端,需要对flushsize和queuesize进行一下比较吧。
private Integer queueSize;//缓冲队列大小,可以访问量设置。
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public List<String> getServices() {
return services;
}
/**
* Method name: addService <BR>
* Description: 添加service名称 <BR>
* Remark: <BR>
* @param serviceName void<BR>
*/
public void addService(String serviceName){
if(services == null){
services = new ArrayList<String>();
}
services.add(serviceName);
}
public void setServices(List<String> services) {
this.services = services;
}
public Long getDelayTime() {
return delayTime;
}
public void setDelayTime(Long delayTime) {
this.delayTime = delayTime;
}
public Long getFlushSize() {
return flushSize;
}
public void setFlushSize(Long flushSize) {
this.flushSize = flushSize;
}
public Integer getQueueSize() {
return queueSize;
}
public void setQueueSize(Integer queueSize) {
this.queueSize = queueSize;
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: DefaultSyncTransfer.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.service
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月28日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.zhaoonline.microservice.framework.monitor.trace.Span;
/**
* class name:DefaultSyncTransfer <BR>
* class description: please write your description <BR>
* Remark: <BR>
*
* @version 1.00 2016年7月28日
* @author zhaoonline)yangyoupeng
*/
public class DefaultSyncTransfer implements SyncTransfer {
private static Logger logger = LoggerFactory.getLogger(DefaultSyncTransfer.class);
private TraceService traceService;
private Long waitTime;
private ArrayBlockingQueue<Span> queue;
private List<Span> spansCache;
// serviceName isReady
private volatile boolean isReady = false; // 是否获得种子等全局注册信息
private ConcurrentHashMap<String, Boolean> isServiceReady = new ConcurrentHashMap<String, Boolean>();
private TransferTask task;
private Long flushSize;
private GenerateTraceId generateTraceId = new GenerateTraceId(0L);
private String appName;
/**
* Method name: DefaultSyncTransfer<BR>
* Description:DefaultSyncTransfer的构造函数,根据传入的configuration初始化参数 <BR>
* Remark: <BR>
* @param c <BR>
*/
public DefaultSyncTransfer(Configuration c) {
this.flushSize = c.getFlushSize() == null ? 1024L : c.getFlushSize();
this.waitTime = c.getDelayTime() == null ? 60000L : c.getDelayTime();
this.appName = StringUtils.isEmpty(c.getApplicationName()) ?"test":c.getApplicationName();
this.queue = new ArrayBlockingQueue<Span>(c.getQueueSize()==null ? 1000 :c.getQueueSize());
this.spansCache = new ArrayList<Span>();
this.task = new TransferTask();
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.service.SyncTransfer#getTraceId()
* <BR>
* Method name: getTraceId <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @return <BR>
*/
public Long getTraceId() {
return generateTraceId.getTraceId();
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.service.SyncTransfer#getSpanId()
* <BR>
* Method name: getSpanId <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @return <BR>
*/
public Long getSpanId() {
return generateTraceId.getTraceId();
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.service.SyncTransfer#isReady()
* <BR>
* Method name: isReady <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @return <BR>
*/
public boolean isReady() {
return isReady;
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.service.SyncTransfer#isServiceReady(java.lang.String)
* <BR>
* Method name: isServiceReady <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param serviceName
* @return <BR>
*/
public boolean isServiceReady(String serviceName) {
if (serviceName != null && isServiceReady.containsKey(serviceName)){
return isServiceReady.get(serviceName);
}else{
return false;
}
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.service.SyncTransfer#start()
* <BR>
* Method name: start <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @throws Exception
* <BR>
*/
public void start() throws Exception {
if (traceService != null && !task.isAlive()) {
task.start();
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
cancel();
}
});
} else if (traceService == null) {
throw new Exception("TraceServie is null.can't starting SyncTransfer");
}
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.service.SyncTransfer#getServiceId(java.lang.String)
* <BR>
* Method name: getServiceId <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param name
* @return <BR>
*/
public String getServiceId(String name) {
String serviceId =traceService.getServiceId(name);
// 可能是未注册的服务
if (null == serviceId) {
isServiceReady.putIfAbsent(name, false);// 设置未注册标志,交给task去注册
}
return serviceId;
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.service.SyncTransfer#cancel()
* <BR>
* Method name: cancel <BR>
* Description: please write your description <BR>
* Remark: <BR>
* <BR>
*/
public void cancel() {
task.interrupt();
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.service.SyncTransfer#syncSend(com.zhaoonline.microservice.framework.monitor.trace.Span)
* <BR>
* Method name: syncSend <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param span
* <BR>
*/
public void syncSend(Span span) {
try {
queue.add(span);
} catch (Exception e) {
logger.info(" span : ignore ..");
}
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.service.SyncTransfer#setTraceService(com.zhaoonline.microservice.framework.monitor.service.TraceService)
* <BR>
* Method name: setTraceService <BR>
* Description: please write your description <BR>
* Remark: <BR>
* @param traceService
* <BR>
*/
public void setTraceService(TraceService traceService) {
this.traceService = traceService;
}
/**
* @Override
* @see com.zhaoonline.microservice.framework.monitor.service.SyncTransfer#appName()
* <BR>
* Method name: appName <BR>
* Description: 这是app的name <BR>
* Remark: <BR>
* @return <BR>
*/
public String appName() {
return this.appName;
}
private class TransferTask extends Thread {
TransferTask() {
this.setName("TransferTask-Thread");
}
@Override
public void run() {
for (;;) {
try {
if (!isReady()) {// 重试直到注册成功
// 全局信息网络注册,输入流:应用名 @ 输出流:包含种子的Map对象
boolean r = traceService.registerService(appName(), new ArrayList<String>());
if (r) {
generateTraceId = new GenerateTraceId(traceService.getSeed());
isReady = true;
} else {
synchronized (this) {
this.wait(waitTime);
}
}
} else {
while (!task.isInterrupted()) {
// 检查是否有未注册服务,先注册
Set<Entry<String, Boolean>> entrySet=isServiceReady.entrySet();
for (Map.Entry<String, Boolean> entry : entrySet) {
if (!entry.getValue()) {// 没有注册,先注册
boolean r = traceService.registerService(appName(), entry.getKey());
if (r) {
entry.setValue(true);
}
}
}
// ----------------------------- queue.take()阻塞-------
Span first = queue.take();
spansCache.add(first);
queue.drainTo(spansCache,flushSize.intValue());
traceService.sendSpan(spansCache);
spansCache.clear();
}
}
} catch (Throwable e) {
e.printStackTrace();
logger.info(e.getMessage());
}
}
}
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: GenerateTraceId.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.service
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月28日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.service;
import java.util.concurrent.atomic.AtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* class name:GenerateTraceId <BR>
* class description: 创建traceId <BR>
* Remark: <BR>
*
* @version 1.00 2016年7月28日
* @author zhaoonline)yangyoupeng
*/
public class GenerateTraceId {
private static Logger logger = LoggerFactory.getLogger(GenerateTraceId.class);
private Long seed;
private static Long MAX_STEP = 0xffffffL;
private AtomicLong plusId = new AtomicLong(0L);
/**
* Method name: GenerateTraceId<BR>
* Description: 构造函数<BR>
* Remark: <BR>
* @param seed <BR>
*/
public GenerateTraceId(Long seed) {
this.seed = seed;
}
public Long getTraceId() {
return (seed << 40) | getPlusId();
}
private long getPlusId() {
if (plusId.get() >= MAX_STEP) {
plusId.set(0L);
}
return plusId.incrementAndGet();
}
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: RegisterService.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.service
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月28日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.service;
import java.util.List;
/**
* class name:RegisterService <BR>
* class description: please write your description <BR>
* Remark: <BR>
* @version 1.00 2016年7月28日
* @author zhaoonline)yangyoupeng
*/
public interface RegisterService {
/**
* Method name: registerService <BR>
* Description: registerService <BR>
* Remark: <BR>
* @param name
* @param services
* @return boolean<BR>
*/
public boolean registerService(String name,List<String> services);
/**
* Method name: registerService <BR>
* Description: 根据appName和serviceName更新注册信息 <BR>
* Remark: <BR>
* @param appName
* @param serviceName
* @return boolean<BR>
*/
boolean registerService(String appName, String serviceName);
}
/*
* All rights Reserved, Copyright (C) ZhaoOnline LIMITED 2016
* FileName: SyncTransfer.java
* Version: $Revision$
* Package Name:com.zhaoonline.microservice.framework.monitor.service
* Modify record:
* NO. | Date | Name | Content
* 1 | 2016年7月28日 | zhaoonline)yangyoupeng | original version
*/
package com.zhaoonline.microservice.framework.monitor.service;
import com.zhaoonline.microservice.framework.monitor.trace.Span;
/**
* class name:SyncTransfer <BR>
* class description: 同步发送<BR>
* Remark: <BR>
* @version 1.00 2016年7月28日
* @author zhaoonline)yangyoupeng
*/
public interface SyncTransfer {
/**
* Method name: getTraceId <BR>
* Description: getTraceId <BR>
* Remark: <BR>
* @return Long<BR>
*/
public Long getTraceId();
/**
* Method name: getSpanId <BR>
* Description: getSpanId <BR>
* Remark: <BR>
* @return Long<BR>
*/
public Long getSpanId();
/**
* Method name: isReady <BR>
* Description: isReady <BR>
* Remark: <BR>
* @return boolean<BR>
*/
/**
* Method name: isReady <BR>
* Description: isReady <BR>
* Remark: <BR>
* @return boolean<BR>
*/
public boolean isReady();
/**
* Method name: isServiceReady <BR>
* Description: isServiceReady <BR>
* Remark: <BR>
* @param serviceName
* @return boolean<BR>
*/
public boolean isServiceReady(String serviceName);
/**
* Method name: start <BR>
* Description: start <BR>
* Remark: <BR>
* @throws Exception void<BR>
*/
public void start() throws Exception;
/**
* Method name: getServiceId <BR>
* Description: getServiceId <BR>
* Remark: <BR>
* @param name
* @return String<BR>
*/
public String getServiceId(String name);
/**
* Method name: cancel <BR>
* Description: cancel <BR>
* Remark: <BR> void<BR>
*/
public void cancel();
/**
* Method name: syncSend <BR>
* Description: syncSend <BR>
* Remark: <BR>
* @param span void<BR>
*/
public void syncSend(Span span);
/**
* Method name: setTraceService <BR>
* Description: setTraceService <BR>
* Remark: <BR>
* @param traceService void<BR>
*/
public void setTraceService(TraceService traceService);
/**
* Method name: appName <BR>
* Description: appName <BR>
* Remark: <BR>
* @return String<BR>
*/
public String appName();
}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.