SkillAgentSearch skills...

Eagle

Eagle分布式rpc调用,借助Zookeeper实现服务注册和发现,基于AQS实现高性能连接池,支持分布式追踪、监控、过载保护等配置。提供Spring和SpringBoot插件,方便与Spring和SpringBoot集成。

Install / Use

/learn @fang-yan-peng/Eagle
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

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个线程。

Image text

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

Image text

例子

内置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);
        }
    }

同步调用

  1. 创建一个接口类。

    src/main/java/eagle/jfaster/org/service/Calculate.java

    package eagle.jfaster.org.service;
    
    public interface Calculate {
    
        int add(int a,int b);
    
        int sub(int a,int b);
    }
    
    
  2. 实现接口,并暴露服务。

    src/main/java/eagle/jfaster/org/service/impl/CalculateImpl.java

    package 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.java

    
    package 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配置文件。

  3. 创建和启动客户端

    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
    
View on GitHub
GitHub Stars77
CategoryDevelopment
Updated14d ago
Forks22

Languages

Java

Security Score

100/100

Audited on Mar 15, 2026

No findings