跳到主要内容

服务图表

概述

ServiceGraph是一个控制服务启动和停止程序的强大工具。 在启动时,它根据提供的依赖关系创建一个所有需要的服务图。 该图用于同时启动和停止服务,这导致了更快的启动时间,而不会出现服务之间的相互干扰。

特点

  • 旨在与 ActiveJ InjectLauncher 结合使用,作为根据依赖关系图启动/停止应用程序服务的一种手段。
  • 它通过遵循多线程图的遍历算法来启动服务:先是叶子服务,然后依次进行
  • 它在相反的方向上停止服务
  • 服务依赖图是在 ActiveJ Inject 依赖图的基础上自动建立的,但可以通过 用户指定的依赖来定制。
  • 支持多种标准服务,如 ThreadPool, Closeables, DataSource 以及Active-specific 服务,如 eventloops, async servers 和 async services。
  • 可以通过用户提供的适配器配置来支持其他服务

为了对ServiceGraph的作用有一个基本的了解,让我们看一下一个非常简单的HTTP服务器的例子。

public final class HttpHelloWorldExample extends HttpServerLauncher {  @Provides  AsyncServlet servlet() {    return request -> HttpResponse.ok200().withPlainText("Hello World");  }
  public static void main(String[] args) throws Exception {    Launcher launcher = new HttpHelloWorldExample();    launcher.launch(args);  }}
graph LR AsyncHttpServer --> Eventloop
  • 根据这张图,服务图表首先开始 Eventloop。 依赖的 AsyncHttpServer ,然后再启动
  • 当应用程序停止时,服务将以相反的方向停止: AsyncHttpServer 首先, Eventloop 其次

实例

note

要运行例子,你需要从GitHub克隆ActiveJ

git clone https://github.com/activej/activej

并将其作为一个Maven项目导入。 查看标签 v5.4.3。 在运行这些例子之前,先建立项目。 这些例子位于 activej/examples/core/boot

简单服务示例

在这个例子中,我们创建了一个扩展Launcher的应用程序,并有一个简单的自定义服务,基本上只有 启动和停止。

public class SimpleServiceExample extends Launcher {  public static void main(String[] args) throws Exception {    SimpleServiceExample example = new SimpleServiceExample();    example.launch(args);  }
  @Inject CustomService customService;
  @Override  protected Module getModule() {    return ServiceGraphModule.create();  }
  @Inject  private static class CustomService implements Service {    @Override    public CompletableFuture<?> start() {      System.out.println("|SERVICE STARTING|");      return CompletableFuture.completedFuture(null);    }
    @Override    public CompletableFuture<?> stop() {      System.out.println("|SERVICE STOPPING|");      return CompletableFuture.completedFuture(null);    }  }
  @Override  protected void run() {    System.out.println("|RUNNING|");  }}

在GitHub上看到完整的例子

事件循环服务示例

服务图表也能够启动和停止你的自定义服务。

public class EventloopServiceExample extends Launcher {
  @Provides  Eventloop eventloop() {    return Eventloop.create();  }
  @Provides  @Eager  CustomEventloopService customEventloopService(Eventloop eventloop) {    return new CustomEventloopService(eventloop);  }
  @Override  protected Module getModule() {    return ServiceGraphModule.create();  }
  @Override  protected void run() {    System.out.println("|RUNNING|");  }
  private static final class CustomEventloopService implements EventloopService {    private final Eventloop eventloop;
    public CustomEventloopService(Eventloop eventloop) {      this.eventloop = eventloop;    }
    @Override    public @NotNull Eventloop getEventloop() {      return eventloop;    }
    @Override    public @NotNull Promise<?> start() {      System.out.println("|CUSTOM EVENTLOOP SERVICE STARTING|");      return Promises.delay(Duration.ofMillis(10))          .whenResult(() -> System.out.println("|CUSTOM EVENTLOOP SERVICE STARTED|"));    }
    @Override    public @NotNull Promise<?> stop() {      System.out.println("|CUSTOM EVENTLOOP SERVICE STOPPING|");      return Promises.delay(Duration.ofMillis(10))          .whenResult(() -> System.out.println("|CUSTOM EVENTLOOP SERVICE STOPPED|"));    }  }
  public static void main(String[] args) throws Exception {    EventloopServiceExample example = new EventloopServiceExample();    example.launch(args);  }}

在GitHub上看到完整的例子

高级服务示例

服务图谱可以管理更复杂的服务依赖关系。 例如,让我们假设我们有一个电子邮件服务 原型。 为了正常工作,它需要两个服务--一个授权服务和一个数据库服务。 授权 服务也需要一个数据库服务,以及Eventloop和Executor。 因此,我们有以下服务图。

graph LR id1(EmailService) --> id2(AuthService) id2 --> id3(DBService) id1 --> id3 id2 --> Executor id2 --> Eventloop

ServiceGraphModule 将以适当的顺序启动和停止所有这些服务。

$AuthService=== 启动应用
启动 java.util.concurrent.Executor启动 io.activej.eventloop.Eventloop启动 AdvancedServiceExample$DBService
启动 AdvancedServiceExample$AuthService
启动 AdvancedServiceExample$EmailService
 === 停止应用
停止了 AdvancedServiceExample$EmailService
停止了 AdvancedServiceExample
停止了 java.util.concurrent.Executor util.concurrent.ExecutorStopped io.activej.eventloop.EventloopStopped AdvancedServiceExample$DBService

这个应用程序看起来如下。

public class AdvancedServiceExample extends Launcher {  @Provides  @Eager  DBService dbService() {    return new DBService();  }
  @Provides  @Eager  EmailService emailService(DBService dbService, AuthService authService) {    return new EmailService(dbService, authService);  }
  @Provides  @Eager  AuthService authService(Eventloop eventloop, Executor executor, DBService dbService) {    return new AuthService(eventloop, executor, dbService);  }
  @Provides  Eventloop eventloop() {    return Eventloop.create().withCurrentThread();  }
  @Provides  Executor executor() {    return Executors.newCachedThreadPool();  }
  @Override  protected Module getModule() {    return ServiceGraphModule.create();  }
  @SuppressWarnings("FieldCanBeLocal")  private static class AuthService implements EventloopService {    private final Eventloop eventloop;    private final Executor executor;    private final DBService dbService;
    public AuthService(Eventloop eventloop, Executor executor, DBService dbService) {      this.executor = executor;      this.eventloop = eventloop;      this.dbService = dbService;    }
    @Override    public @NotNull Eventloop getEventloop() {      return eventloop;    }
    @Override    public @NotNull Promise<?> start() {      System.out.println("AuthService starting");      return Promise.ofBlocking(executor,          () -> System.out.println("AuthService started"));    }
    @Override    public @NotNull Promise<?> stop() {      return Promise.ofBlocking(executor,          () -> System.out.println("AuthService stopped"));    }  }
  private static class DBService implements Service {    @Override    public CompletableFuture<?> start() {      System.out.println("DBService is starting");      return CompletableFuture.runAsync(() -> {        try {          Thread.sleep(1000);        } catch (InterruptedException e) {          e.printStackTrace();          Thread.currentThread().interrupt();        }        System.out.println("DBService is started");      });    }
    @Override    public CompletableFuture<?> stop() {      System.out.println("DBService is stopping");      return CompletableFuture.runAsync(() -> {        try {          Thread.sleep(2000);        } catch (InterruptedException e) {          e.printStackTrace();          Thread.currentThread().interrupt();        }        System.out.println("DBService is stopped");      });    }  }
  @SuppressWarnings("FieldCanBeLocal")  private static class EmailService implements Service {    private final DBService service;    private final AuthService authService;
    public EmailService(DBService service, AuthService authService) {      this.service = service;      this.authService = authService;    }
    @Override    public CompletableFuture<?> start() {      System.out.println("EmailService is starting");      return CompletableFuture.runAsync(() -> {        try {          Thread.sleep(1000);        } catch (InterruptedException e) {          e.printStackTrace();          Thread.currentThread().interrupt();        }        System.out.println("EmailService is started");      });    }
    @Override    public CompletableFuture<?> stop() {      System.out.println("EmailService is stopping");      return CompletableFuture.runAsync(() -> System.out.println("EmailService is stopped"));    }  }
  @Override  protected void run() {  }
  public static void main(String[] args) throws Exception {    AdvancedServiceExample example = new AdvancedServiceExample();    example.launch(args);  }}

在GitHub上看到完整的例子