使用 subscriptions-transport-ws 设置 Apollo 服务器?

Posted

技术标签:

【中文标题】使用 subscriptions-transport-ws 设置 Apollo 服务器?【英文标题】:Setting Up Apollo Server with subscriptions-transport-ws? 【发布时间】:2017-02-07 11:55:24 【问题描述】:

我的服务器似乎是根据http://dev.apollodata.com/tools/apollo-server/setup.html 的 Apollo 文档设置的。在我的 server/main.js 文件中:

//SET UP APOLLO INCLUDING APOLLO PUBSUB
const executableSchema = makeExecutableSchema(
    typeDefs: Schema,
    resolvers: Resolvers,
    connectors: Connectors,
    logger: console,
);

const GRAPHQL_PORT = 8080;
const graphQLServer = express();

// `context` must be an object and can't be undefined when using connectors
graphQLServer.use('/graphql', bodyParser.json(), apolloExpress(
    schema: executableSchema,
    context: , //at least(!) an empty object
));

graphQLServer.use('/graphiql', graphiqlExpress(
    endpointURL: '/graphql',
));

graphQLServer.listen(GRAPHQL_PORT, () => console.log(
    `GraphQL Server is now running on http://localhost:$GRAPHQL_PORT/graphql`
));
//SET UP APOLLO INCLUDING APOLLO PUBSUB

它在终端日志中打印出“GraphQL Server is now running on http://localhost:8080/graphql”,表明服务器已成功初始化。

但是在我的 main_layout 组件的顶部,当我运行这段代码时:

import  Client  from 'subscriptions-transport-ws';
const wsClient = new Client('ws://localhost:8080');

...我收到此控制台消息:

到 'ws://localhost:8080/' 的 WebSocket 连接失败:在收到握手响应之前连接已关闭

我错过了什么?

【问题讨论】:

【参考方案1】:

您需要创建一个专用的 websocket 服务器。它将在不同的端口上运行,设置它的代码在 subscriptions-transport-ws 包中提供。

查看 GitHunt-API 示例中的以下代码: https://github.com/apollostack/GitHunt-API/blob/master/api/index.js#L101-L134

您还会看到此代码依赖于一个名为 SubscriptionManager 的类。它是来自 apollo 团队的 graphql-subscriptions 包中的一个类,您可以在此处找到如何使用它的示例: https://github.com/apollostack/GitHunt-API/blob/master/api/subscriptions.js

【讨论】:

您在 GitHunt-API/api/index.js 中突出显示的代码没有引用架构,Apollo 文档说在设置服务器时必须引用架构。该模式在第 66 行突出显示的代码上方引用,但这是针对不同端口上的侦听器,该端口似乎主要与 GitHub API 相关。说我需要修改 3010 端口代码以省略对 GitHub 的引用是否正确? 如果您想设置订阅(就像现在一样),您需要一个模式对象,该对象将提供给 SubscriptionManager 构造函数(我在答案的最后一部分中已经指出)和反过来,它将从 subscriptions-transport-ws 包中提供给 Server 类。它上面的参考与仅服务于突变和查询的 GraphQL POST 端点有关。完成所有这些配置后,您将在不同端口上留下两台服务器,一台用于 GraphQL 端点,另一台用于 websocket 以将事件推送到客户端。 不需要专用的 websocket 端口 - 请参阅我的答案。【参考方案2】:

这是一个关于使用 Apollo GraphQL、React 和 Hapi 的演示:https://github.com/evolastech/todo-react。它不像 GitHunt-React 和 GitHunt-API 那样不堪重负

【讨论】:

【参考方案3】:

TL;DR:您可以使用graphql-up 快速获取支持订阅并准备就绪的 GraphQL 服务器。这里有更多 detailed tutorial 将其与 Apollo 和 websocket 客户端 subscriptions-transport-ws 结合使用。

一键获取GraphQL Server

假设您要基于此GraphQL Schema in IDL syntax 构建 Twitter 克隆:

type Tweet 
  id: ID!
  title: String!
  author: User! @relation(name: "Tweets")


type User 
  id: ID!
  name: String!
  tweets: [Tweet!]! @relation(name: "Tweets")

单击此按钮接收您自己的 GraphQL API,然后打开 Playground,您可以在其中添加一些推文、查询所有推文并测试订阅。

简单易用的 API

首先,让我们创建一个用户,它将成为所有即将发布的推文的作者。在 Playground 中运行这个突变:

mutation createUser 
  createUser(name: "Tweety") 
    id # copy this id for future mutations!
  

以下是查询存储在 GraphQL 服务器上的所有推文及其作者的方法:

query allTweets 
  allTweets 
    id
    title
    createdAt
    author 
      id
      name
    
  

使用 websocket 的订阅支持

现在让我们订阅来自“Tweety”的新推文。这是语法:

subscription createdTweets 
  Message(filter: 
    mutation_in: [CREATED]
    node: 
      author: 
        name: "Tweety"
      
    
  ) 
    node 
      id
      text
      createdAt
      sentBy 
        id
        name
      
    
  

现在在 Playground 中创建一个新选项卡并创建一条新推文:

mutation createTweet 
  createTweet(
    title: "#GraphQL Subscriptions are awesome!"
    authorId: "<id-from-above>"
  ) 
    id
  

您应该会在您之前订阅的其他标签中看到一个新事件弹出。

【讨论】:

【参考方案4】:

似乎您实际上并没有制作 websocket 服务器。使用订阅服务器。请记住,正如 davidyaha 所说,您必须拥有一个专用的 websocket 端口(我也曾想过)绝对不是真的。我的普通查询和订阅都在同一个端口上。

import  createServer  from 'http';
import  SubscriptionServer  from 'subscriptions-transport-ws';
import  execute, subscribe  from 'graphql';
import  schema  from './my-schema';

// All your graphQLServer.use() etc setup goes here, MINUS the graphQLServer.listen(),
// you'll do that with websocketServer:

// Create WebSocket listener server
const websocketServer = createServer(graphQLServer);

// Bind it to port and start listening
websocketServer.listen(3000, () => console.log(
  `Server is now running on http://localhost:3000`
));

const subscriptionServer = SubscriptionServer.create(
  
    schema,
    execute,
    subscribe,
  ,
  
    server: websocketServer,
    path: '/subscriptions',
  ,
);

【讨论】:

以上是关于使用 subscriptions-transport-ws 设置 Apollo 服务器?的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)