Eagle
Eagle分布式rpc调用,借助Zookeeper实现服务注册和发现,基于AQS实现高性能连接池,支持分布式追踪、监控、过载保护等配置。提供Spring和SpringBoot插件,方便与Spring和SpringBoot集成。
Install / Use
/learn @fang-yan-peng/EagleREADME
Eagle
概要
Eagle是一个分布式的RPC框架,支持灵活的配置,支持分布式追踪,支持[Kryo][kryo]、[Hessian][hessian]、[Protobuf][protobuf] 等序列化协议,默认序列化使用kryo 。提供Spring 和SpringBoot插件,方便与Spring和SpringBoot集成。
特点
- 借助[Zookeeper][zookeeper]实现服务注册和发现。
- 分布式ID追踪,方便排查问题。
- 基于AQS实现高性能连接池。
- 提供failover和failfast两种高可用策略。
- 支持同步和异步回调两种机制。
- 提供接口方法请求时间、tps等监控信息。
- 提供和自定义服务端过载保护策略。
jmh基准测试结果
运行基准测试步骤:
- cd eagle-benchmark
- mvn clean install
- cd eagle-benchmark-server/target
- tar -zxvf eagle-benchmark-server-1.8-assembly.tar.gz
- cd eagle-benchmark-server-1.8
- bin/start.sh
- cd eagle-benchmark/eagle-benchmark-client
- 在linux上运行 sh benchmark.sh,在window上运行 benchmark.cmd
- 注(修改benchmark.sh 中的 -t 参数修改线程数)
macOs上的结果(16g内存,2.5 GHz Intel Core i7),启动16个线程。

linux上的结果(64g内存,24核),启动80个线程。

例子
内置zookeeper,仅测试使用。生产环境请更换真实zookeeper地址,使用内置zookeeper有可能会报连接警告或者异常,更换真实zk地址即可。运行要求:
- JDK 1.7 or above
- 编译工具 [Maven][maven] or [Gradle][gradle]
添加依赖
如果是spring,添加如下:
<dependency>
<groupId>org.jfaster.eagle</groupId>
<artifactId>eagle-core</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.jfaster.eagle</groupId>
<artifactId>eagle-registry-zookeeper</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.jfaster.eagle</groupId>
<artifactId>eagle-transport-netty</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.jfaster.eagle</groupId>
<artifactId>eagle-spring-support</artifactId>
<version>1.8</version>
</dependency>
如果是springBoot,添加如下:
<dependency>
<groupId>org.jfaster.eagle</groupId>
<artifactId>eagle-core</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.jfaster.eagle</groupId>
<artifactId>eagle-registry-zookeeper</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.jfaster.eagle</groupId>
<artifactId>eagle-transport-netty</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.jfaster.eagle</groupId>
<artifactId>spring-boot-starter-eagle</artifactId>
<version>1.8</version>
</dependency>
分布式调用追踪
在应用中一个接口通常会涉及到一系列服务的rpc调用,由于服务分布式部署导致出现问题排查相对困难。eagle框架在一次调用中生成的traceId是相同的,只要通过ELK等日志搜集系统把日志集中处理,那么输入traceId就可以获取整个链路的调用过程。
C
/
例如 A - B A调用B,B又调用C和D,那么在一次调用中,可以通过traceId,把整个调用串联起来。traceId是根据ip+进程号+时间戳+计数,生成的全局唯一id,如果框架内部获取的ip不准确可以通过,如-Dhost=10.110.69.17指定。
\
D
在业务代码中,当打印日志的时候,可以通过TraceContex.getOpaque()方法获取当前调用链中的traceId。打印出traceId,logger.info(TraceContex.getOpaque() + "xxxxxx")。这样就可以根据日志追踪整个调用过程。
更简单的方式是使用eagle框架提供的日志组件,配置如下:
logback的配置
- 如果当前上下文中存在traceId,logback将在输出traceId,如果不存在traceId则输出N/A。用%traceId来展示traceId。
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="eagle.jfaster.org.trace.logback.TraceIdPatternLogbackLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%traceId] [%thread] %-5level %logger{36} -%msg%n</Pattern>
</layout>
</encoder>
</appender>
log4j的配置
- 配置layout
log4j.appender.CONSOLE.layout=eagle.jfaster.org.trace.log4j.TraceIdPatternLayout
- 在layout.ConversionPattern中设置 %T来展示traceId
log4j.appender.CONSOLE.layout.ConversionPattern=%d [%T] %-5p %c{1}:%L - %m%n
分布式追踪在程序中的应用
- 在spring配置文件中,添加
<eagle:trace/>配置,springboot不用添加额外配置。然后在需要追踪的类或者方法上打上@Trace注解。
src/main/java/eagle/jfaster/org/controller/TraceController.java
package eagle.jfaster.org.controller;
import eagle.jfaster.org.config.annotation.Refer;
import eagle.jfaster.org.service.Calculate;
import eagle.jfaster.org.service.Hello;
import eagle.jfaster.org.trace.annotation.Trace;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by fangyanpeng on 2017/12/16.
*/
@RestController
@RequestMapping("/")
public class TraceController {
private static final Logger logger = LoggerFactory.getLogger(TraceController.class);
@Refer(baseRefer = "baseRefer")
private Calculate calculate;
@Refer(baseRefer = "baseRefer")
private Hello hello;
@Trace
@RequestMapping("/cal")
public String cal(@RequestParam int a, @RequestParam int b,@RequestParam int code){
//log会打印出TraceId
logger.info(hello.hello(code));
int res = calculate.add(a, b);
logger.info("calculate {}",res);
return String.valueOf(res);
}
}
同步调用
-
创建一个接口类。
src/main/java/eagle/jfaster/org/service/Calculate.javapackage eagle.jfaster.org.service; public interface Calculate { int add(int a,int b); int sub(int a,int b); } -
实现接口,并暴露服务。
src/main/java/eagle/jfaster/org/service/impl/CalculateImpl.javapackage eagle.jfaster.org.service.impl; import eagle.jfaster.org.service.Calculate; import org.springframework.stereotype.Service; @Service("calculate") public class CalculateImpl implements Calculate { public int add(int a, int b) { return a+b; } public int sub(int a, int b) { return a-b; } }src/main/resources/server.xml<?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:context="http://www.springframework.org/schema/context" xmlns:eagle="http://eagle.jfaster.org/schema/eagle" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://eagle.jfaster.org/schema/eagle http://eagle.jfaster.org/schema/eagle/eagle.xsd "> <context:component-scan base-package="eagle.jfaster.org" /> <context:annotation-config/> <!--注册中心配置可以多个--> <eagle:registry name="regCenter" protocol="zookeeper" address="127.0.0.1:4181" namespace="eagle" base-sleep-time-milliseconds="1000" max-sleep-time-milliseconds="3000" max-retries="3"/> <!--协议配置--> <eagle:protocol id="proto" name="eagle" serialization="kryo" use-default="true" max-content-length="16777216" max-server-connection="20000" core-worker-thread="20" max-worker-thread="200" worker-queue-size="10"/> <eagle:base-service id="baseService" group="eagleGroup" export="proto:9200" registry="regCenter"/> <eagle:service interface="eagle.jfaster.org.service.Calculate" ref="calculate" base-service="baseService" export="proto:9300,proto:9400" service-type="cglib"/>src/main/java/eagle/jfaster/org/Server.javapackage eagle.jfaster.org.server; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.concurrent.CountDownLatch; public class Server { public static void main(String[] args) throws InterruptedException { //启动Curator框架提供的内置zookeeper 仅供测试使用,生产环境请使用真实zookeeper地址 EmbedZookeeperServer.start(4181); ApplicationContext appCtx = new ClassPathXmlApplicationContext("server.xml"); CountDownLatch latch = new CountDownLatch(1); latch.await(); } }执行main方法,就会在9300和9400端口发布服务。同时eagle还提供了eagle.jfaster.org.container.Main类,会跟据环境变量eagle.container的设置启动不同的容器。 如果没有配置会默认启动SpringContainer,会加载classpath*:META-INF/spring/*.xml的所有spring配置文件。
-
创建和启动客户端
src/main/resources/client_sync.xml<?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:context="http://www.springframework.org/schema/context" xmlns:eagle="http://eagle.jfaster.org/schema/eagle" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://eagle.jfaster.org/schema/eagle http://eagle.jfaster.org/schema/eagle/eagle.xsd "> <context:component-scan base-package="eagle.jfaster.org" /> <context:annotation-config/> <!--注册中心配置可以多个--> <eagle:registry name="regCenter" protocol="zookeeper" address="127.0.0.1:4181" namespace="eagle" base-sleep-time-milliseconds="1000" max-sleep-time-milliseconds="3000" max-retries="3"/> <!--协议配置--> <eagle:protocol name="eagle" serialization="kryo" use-default="true" cluster="eagle" max-content-length="16777216"/> <eagle:base-refer id="baseRefer" request-timeout="300" actives="20000" actives
