0
点赞
收藏
分享

微信扫一扫

dremio backend webserver 简单说明

q松_松q 2023-02-28 阅读 82

dremio 的webserver 是基于jetty+jersey 开发的web server 同时也和标准的dremio 服务一样实现了service 接口方便服务的启动

具体是由DACDaemon 调用触发的启动

webserver start 服务


@Override

public void start() throws Exception {

// 使用了DremioServer 服务进行实际的启动

server.startDremioServer(

registry,

config,

credentialsServiceProvider,

uiType,

this::registerEndpoints

);

}

jetty+jersey 服务的启动

DremioServer 类中


public void startDremioServer(

SingletonRegistry registry,

DACConfig config,

Provider<CredentialsService> credentialsServiceProvider,

String uiType,

Consumer<ServletContextHandler> servletRegistrer

) throws Exception {

this.credentialsServiceProvider = credentialsServiceProvider;

try {

if (!embeddedJetty.isRunning()) {

// 创建jetty 的connector
createConnector(config);

// 添加handlers,包含了不少dremio 内部的服务

addHandlers();

}


if (config.verboseAccessLog) {

accessLogFilter = new AccessLogFilter();

// 此处servletContextHandler 是在addHandlers 中初始化的

servletContextHandler.addFilter(

new FilterHolder(accessLogFilter),

"/*",

EnumSet.of(DispatcherType.REQUEST));

}


if (config.serveUI) {

final String basePath = "rest/dremio_static/";

final String markerPath = String.format("META-INF/%s.properties", uiType);

// dremio 自己的一个servlet

final ServletHolder fallbackServletHolder = new ServletHolder("fallback-servlet", registry.lookup(DremioServlet.class));

addStaticPath(fallbackServletHolder, basePath, markerPath);

servletContextHandler.addServlet(fallbackServletHolder, "/*");

}


if (servletRegistrer != null) {

servletRegistrer.accept(servletContextHandler);

}


if (!embeddedJetty.isRunning()) {

embeddedJetty.start();

}


setPortFromConnector();

logger.info("Started on {}://localhost:" + port, config.webSSLEnabled() ? "https" : "http");


serviceStarted = true;

} catch (Exception ex) {

throw new ServerErrorException(ex);

}

}

其他api endpoint 的注册

WebServer 类中,基于了DremioServer 提供的一个函数接口,注册了不少dremio 的api 接口

使用了jetty 提供的ServletHolder 动态的servlet 注册接口,同时利用了ResourceConfig

protected void registerEndpoints(ServletContextHandler servletContextHandler) {

// security header filters

SecurityHeadersFilter securityHeadersFilter = new SecurityHeadersFilter(registry.provider(OptionManager.class));

servletContextHandler.addFilter(new FilterHolder(securityHeadersFilter), "/*", EnumSet.of(DispatcherType.REQUEST));


// Generic Response Headers filter for api responses

servletContextHandler.addFilter(GenericResponseHeadersFilter.class.getName(), "/apiv2/*", EnumSet.of(DispatcherType.REQUEST));

servletContextHandler.addFilter(GenericResponseHeadersFilter.class.getName(), "/api/*", EnumSet.of(DispatcherType.REQUEST));


// add the font mime type.

final MimeTypes mimeTypes = servletContextHandler.getMimeTypes();

mimeTypes.addMimeMapping("woff2", "application/font-woff2; charset=utf-8");

servletContextHandler.setMimeTypes(mimeTypes);


// WebSocket API

final SocketServlet servlet = new SocketServlet(registry.lookup(JobsService.class), registry.lookup(TokenManager.class),

registry.provider(OptionManager.class));

final ServletHolder wsHolder = new ServletHolder(servlet);

wsHolder.setInitOrder(1);

servletContextHandler.addServlet(wsHolder, "/apiv2/socket");


// Rest API

ResourceConfig restServer = restServerProvider.get();


restServer.property(RestServerV2.ERROR_STACKTRACE_ENABLE, config.sendStackTraceToClient);

restServer.property(RestServerV2.TEST_API_ENABLE, config.allowTestApis);

restServer.property(RestServerV2.FIRST_TIME_API_ENABLE, isInternalUS);


restServer.register(dremioBinder);

restServer.register((DynamicFeature) (resourceInfo, context) -> context.register(DremioServer.TracingFilter.class));


final ServletHolder restHolder = new ServletHolder(new ServletContainer(restServer));

restHolder.setInitOrder(2);

servletContextHandler.addServlet(restHolder, "/apiv2/*");


// Public API

ResourceConfig apiServer = apiServerProvider.get();

apiServer.register(dremioBinder);

apiServer.register((DynamicFeature) (resourceInfo, context) -> context.register(DremioServer.TracingFilter.class));


final ServletHolder apiHolder = new ServletHolder(new ServletContainer(apiServer));

apiHolder.setInitOrder(3);

servletContextHandler.addServlet(apiHolder, "/api/v3/*");

}

dremio 自己的实现

包含了APIServer以及RestServerV2


参考类图

基于了ResourceConfig 进行了动态扩展

dremio backend webserver 简单说明_ide

有一个灵活的设计是,dremio 基于了注解实现动态注册,比如api 以及rest 都包含了自己的注解扩展

protected void init(ScanResult result) {

// FILTERS

register(JSONPrettyPrintFilter.class);

register(MediaTypeFilter.class);


// RESOURCES

// 基于APIResource 注解,通过调用register 动态注册接口服务

for (Class<?> resource : result.getAnnotatedClasses(APIResource.class)) {

register(resource);

}


// FEATURES

register(DACAuthFilterFeature.class);

register(DACJacksonJaxbJsonFeature.class);

register(DACExceptionMapperFeature.class);


// EXCEPTION MAPPERS

register(JsonParseExceptionMapper.class);

register(JsonMappingExceptionMapper.class);


// PROPERTIES

property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, "true");

property(RestServerV2.TEST_API_ENABLE, "true");


final String disableMoxy = PropertiesHelper.getPropertyNameForRuntime(CommonProperties.MOXY_JSON_FEATURE_DISABLE,

getConfiguration().getRuntimeType());

property(disableMoxy, true);

}

说明

以上是一个简单的dremio webserver 服务介绍,基于此可以了解dremio api的运行机制,可以更好的进行扩展,实际上dremio 的api 部分还包含了

认证、日志以及一些其他服务,可以通过阅读源码查看学习


参考资料

dac/backend/src/main/java/com/dremio/dac/server/WebServer.java

dac/backend/src/main/java/com/dremio/dac/server/DremioServer.java

dac/backend/src/main/java/com/dremio/dac/server/DremioServlet.java

dac/backend/src/main/java/com/dremio/dac/daemon/DACDaemonModule.java

举报

相关推荐

0 条评论