程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

透过源码分析:GraphQL在开源项目skywalking中的应用

发布于2021-06-14 09:53     阅读(251)     评论(0)     点赞(6)     收藏(1)


前置说明

Skywalking应用GraphQL源码

GraphQL依赖

初始化GraphQL

初始化方式

初始化时间

应用GraphQL实例

暴露接口,提供服务


前置说明

skywalking是国人开源的一款分布式链路追踪系统(应用性能监控工具)。本文重点关注GraphQL在项目中如何应用,其它核心特性及实现,后续有时间再进行补充。

我在前面的文章:IDEA配置skywalking开发环境提到了如何在本地配置skywalking开发环境。如果感兴趣可以对着上面这篇博客把代码clone下来,配置好,对着源码来。

或者直接看下面内容,关键代码我会贴出来。

以下针对skywalking 8.5.0版本。

Skywalking应用GraphQL源码

GraphQL依赖

依赖如下,与我前面文章及示例中使用的依赖并不完全一样:

  1. <dependency>
  2. <groupId>com.graphql-java</groupId>
  3. <artifactId>graphql-java-tools</artifactId>
  4. <version>5.2.3</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.graphql-java</groupId>
  8. <artifactId>graphql-java</artifactId>
  9. <version>8.0</version>
  10. </dependency>

初始化GraphQL

初始化方式

GraphQL实例的初始化在下面这个类里,在prepare方法里面

oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryProvider.java

关于它的初始化并没有特别多的说明,我在前面浅尝GraphQL再谈GraphQL之在spring boot项目中快速应用的示例中用的都是类似的这种方式(因为依赖不一样,所以实际使用的类是不同的,请注意区分)

  1. GraphQLSchema schema = SchemaParser.newParser()
  2. .file("query-protocol/common.graphqls")
  3. .resolvers(new Query(), new Mutation(), new HealthQuery(getManager()))
  4. .file("query-protocol/metadata.graphqls")
  5. .resolvers(new MetadataQuery(getManager()))
  6. // ...省略中间这一大堆重复代码
  7. .file("query-protocol/event.graphqls")
  8. .resolvers(new EventQuery(getManager()))
  9. .build()
  10. .makeExecutableSchema();
  11. this.graphQL = GraphQL.newGraphQL(schema).build();

初始化时间

通过debug调用栈,可以快速看到在哪里被谁调用了prepare方法初始化GraphQL:

OAPServerStartUp#main()方法和OAPServerBootstrap#start()方法都比较简单,重点看下MoudleManager#init()方法,如下:

在第一步加载所有module时,QueryMoulde初始化了GraphQL实例。

应用GraphQL实例

在前面已经初始好了GraphQL实例,需要再看下它是如何嵌套到一个Http Server里面。代码如下,还是在GraphQLProvider类里面:

start方法的调用时机就是在上面截图的第二步start那里,这个时候会调用加载的所有module的start()方法。

而GraphQLQueryHandler是一个HttpServlet的子类,GraphQL作为构造参数传递了进去:

看下GraphQLQueryHandler的代码实现,无关代码我都删除了,只留了核心代码:

  1. @RequiredArgsConstructor
  2. public class GraphQLQueryHandler extends JettyJsonHandler {
  3. @Override
  4. protected JsonElement doGet(HttpServletRequest req) {
  5. // 不支持GET请求
  6. throw new UnsupportedOperationException("GraphQL only supports POST method");
  7. }
  8. @Override
  9. protected JsonElement doPost(HttpServletRequest req) throws IOException {
  10. BufferedReader reader = new BufferedReader(new InputStreamReader(req.getInputStream()));
  11. String line;
  12. StringBuilder request = new StringBuilder();
  13. while ((line = reader.readLine()) != null) {
  14. request.append(line);
  15. }
  16. JsonObject requestJson = gson.fromJson(request.toString(), JsonObject.class);
  17. // 参数解析完毕,进行实际调用
  18. return execute(requestJson.get(QUERY)
  19. .getAsString(), gson.fromJson(requestJson.get(VARIABLES), mapOfStringObjectType));
  20. }
  21. private JsonObject execute(String request, Map<String, Object> variables) {
  22. try {
  23. ExecutionInput executionInput = ExecutionInput.newExecutionInput()
  24. .query(request)
  25. .variables(variables)
  26. .build();
  27. ExecutionResult executionResult = graphQL.execute(executionInput);
  28. LOGGER.debug("Execution result is {}", executionResult);
  29. Object data = executionResult.getData();
  30. List<GraphQLError> errors = executionResult.getErrors();
  31. JsonObject jsonObject = new JsonObject();
  32. if (data != null) {
  33. // 调用结果
  34. jsonObject.add(DATA, gson.fromJson(gson.toJson(data), JsonObject.class));
  35. }
  36. // 异常处理
  37. if (CollectionUtils.isNotEmpty(errors)) {
  38. JsonArray errorArray = new JsonArray();
  39. errors.forEach(error -> {
  40. JsonObject errorJson = new JsonObject();
  41. errorJson.addProperty(MESSAGE, error.getMessage());
  42. errorArray.add(errorJson);
  43. });
  44. jsonObject.add(ERRORS, errorArray);
  45. }
  46. return jsonObject;
  47. } catch (final Throwable e) {
  48. // 异常处理的代码,删除了
  49. return jsonObject;
  50. }
  51. }
  52. }

可以看到,Get请求不支持, Post请求来的时候,解析参数,进行调用,返回结果。

在调用截图中的service.addHandler(...)方法,便会注册这个servert,调用栈如下:

这个JettyServer是skywalking自己实现的:

暴露接口,提供服务

最后看下skywalking是在什么时间启动这个Http Server,再来看下debug栈:

正好是在我们前面截图中的第三步:notifyAfterCompleted(),这时会调用所有加载module的notifyAfterCompleted方法,而这个是属于CoreModuleProvider,如下:

至此,整个流程便已经串联起来了。



所属网站分类: 技术文章 > 博客

作者:怎么没有鱼儿上钩呢

链接:http://www.javaheidong.com/blog/article/222649/0e64419f68a314af3c34/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

6 0
收藏该文
已收藏

评论内容:(最多支持255个字符)