아폴로 연맹과 게이트웨이 입문
28436 단어 apollojavascriptgraphql
Apollo Federation(Apollo Federation)은 과거에 GraphQL API를 모드 결합으로 연결한 적이 있는데, 그것이 제공하는 성명식, 크게 놀랄 필요가 없는 방법은 신선한 공기이다.사실 이 라이브러리가 발표되었을 때, 나는 막 시작했을 때 writing a book about GraphQL, 아폴로 연맹을 사용하기 위해 첫 부분을 신속하게 다시 썼다.
지난 10개월 동안 저는 이 도서관을 탐색해 왔습니다. 저는 이곳에서 일련의 블로그 글을 쓰고 학습 과정에서 배운 기교를 공유할 것이라고 생각합니다.
첫 번째 글은 Apollo Federation을 사용하여 단독 서비스에 두 개의 '연합 모드' 를 설정하고 Apollo Gateway를 사용하여GraphQL API를 조합하는 방법을 간략하게 소개할 것이다.네트워크 인터페이스 API를 시작하고 다시 불러오기 위한 npm 스크립트 설정과 두 가지 서비스를 실현하는 최선의 방법도 공유할 것입니다.
TL;박사: 찾을 수 있어요the complete code here.
첫 번째 단계는 프로젝트 디렉토리를 만드는 것입니다.
mkdir basic-apollo-federation-demo && cd basic-apollo-federation-demo
그런 다음 새 디렉토리npm init
--yes
플래그 생성package.json
파일을 실행하고 질문하지 않습니다.npm init --yes
그런 다음 필요한 모든 패키지를 설치합니다.npm i [email protected] @apollo/[email protected] @apollo/[email protected] \
[email protected] [email protected] [email protected] [email protected] [email protected]
다음은 위 패키지의 용도 설명입니다.apollo-server
: 게이트웨이 API와 우리가 만든 모든 서비스에 사용되는 ApolloServer
의 실례가 필요합니다.@apollo/federation
: 이 가방은 우리가 서비스의 모델을 조합할 수 있도록 허락할 것입니다.@apollo/gateway
: 이 패키지는 전송된GraphQL API 요청을 하부 서비스에 나누어 줍니다.graphql
: 아폴로는 이 라이브러리를 대등한 의존으로 필요로 한다.esm
: 이 가방은'무바베타, 무묶음의 ECMAScript 모듈 마운트기'로 노드에서 사용할 수 있습니다import
와export
.아무런 번거로움도 없다.nodemon
: 프로젝트 디렉터리에 있는 파일이 변경되면 Nodemon은 자동으로 프로그램을 다시 불러옵니다.concurrently
: 우리는 이 패키지를 사용하여 여러 명령을 동시에 실행할 수 있습니다.또한 와일드카드를 사용하여 단축 명령을 지원합니다.wait-on
: 게이트웨이 API를 시작하기 전에 서비스의 포트를 사용할 수 있도록 기다리고 확보하는 것이 좋습니다. 따라서 이 패키지를 사용할 것입니다.실천에서, 이것은 우리가 하나의 서비스 모델에서 하나의 유형을 정의하고, 접근할 수 있으며, 심지어는 다른 모델에서 다른 필드를 사용하여 그것을 확장할 수 있다는 것을 의미한다.이 기능을 사용하면 제품 영역 논리에 따라 API를 쉽게 구분할 수 있습니다.
우리는 단독'영화'와'인물'서비스를 통해 데이터에 대한 접근을 관리할 것이다.모든 서비스는 연방 모델이 있습니다. 우리는 이 두 모델을 네트워크 인터페이스급 API에 통합할 것입니다. 이렇게 하면 클라이언트는 하나의 API에서 데이터를 조회할 수 있고 이 두 개의 하부 서비스에 직접 관심을 가질 필요가 없습니다.
이제 각 서비스에 대한 디렉토리를 추가합니다.
mkdir films people
또한 파일index.js
을 추가하여 두 개의 서비스 및 게이트웨이 코드를 포함합니다.touch index.js films/index.js people/index.js
마지막으로 API를 통해 질의하려면 시뮬레이션 데이터가 필요합니다.또한 data.js
파일을 추가합니다.touch data.js
다음 코드를 추가합니다.export const people = [
{ id: "1", name: "Steven Spielberg" },
{ id: "2", name: "Richard Dreyfuss" },
{ id: "3", name: "Harrison Ford" },
];
export const films = [
{
id: "1",
title: "Jaws",
actors: ["2"],
director: "1",
},
{
id: "2",
title: "Close Encounters of the Third Kind",
actors: ["2"],
director: "1",
},
{
id: "3",
title: "Raiders of the Lost Ark",
actors: ["3"],
director: "1",
},
];
우리는 인원 설정 서비스부터 시작할 것이다.다음 코드를 people/index.js
에 추가합니다.import { ApolloServer, gql } from "apollo-server";
import { buildFederatedSchema } from "@apollo/federation";
import { people } from "../data.js";
const port = 4001;
const typeDefs = gql`
type Person @key(fields: "id") {
id: ID!
name: String
}
extend type Query {
person(id: ID!): Person
people: [Person]
}
`;
위에서 우리는 API의 aPerson
를 설명하는 기본적인 유형 정의를 가지고 있다.APerson
배우일 수도 있고 감독일 수도 있지만 앞으로 영화 서비스 부문에서 구분하도록 하겠습니다.@key
명령이 Person
형식 정의에 추가된 것을 볼 수 있습니다. 이 특수 명령은 Person
를 하나의 실체로 만들었습니다. 이것이 바로 Apollo에게 이 유형은 다른 서비스에 인용되고 확장될 수 있다는 것을 알려 줍니다. (다른 서비스가 id
필드에 표시된 값으로 한 사람을 식별할 수 있다면.)이 서류에는 두 가지 주의해야 할 일이 있다.우선, 우리는
buildFederatedSchema
에서 @apollo/federation
를 가져와서, 잠시 후에 모델 연합을 준비할 수 있도록 합니다.둘째, 우리는 extend
앞에서 type Query
키워드를 사용한다. Query
와 Mutation
유형은 게이트웨이 단계에서 기원되기 때문에 Apollo 문서에 의하면 모든 실현 서비스는 어떠한 추가 조작을 통해 이런 유형을 확장해야 한다고 한다.다음은
people/index.js
의 유형에 대한 파서를 추가합니다.// ...
const resolvers = {
Person: {
__resolveReference(object) {
return people.find((person) => person.id === object.id);
}
},
Query: {
person(_, { id }) {
return people.find((person) => person.id === id);
},
people() {
return people;
}
}
};
Query
의 해석기는 우리가 바라는 것이지만 Person
와 __referenceResolver
에서 재미있는 것을 만났다.이 참고 해석기는 우리가 다른 서비스에 인용되었을 때, 그 @key
필드 (즉 id
를 통해person 실체를 얻는 방법을 인터페이스에 설명하는 것입니다.마지막으로, Dell은
ApolloServer
하단에서 명시적으로 전달people/index.js
및 buildFederatedSchema
옵션이 아닌 서버의 schema
반환 값을 사용하여 새 typeDefs
를 시작합니다.// ...
const server = new ApolloServer({
schema: buildFederatedSchema([{ typeDefs, resolvers }]),
});
server.listen({ port }).then(({ url }) => {
console.log(`People service ready at ${url}`);
});
이것이 바로 우리 직원 서비스에 필요한 모든 코드다.영화 서비스에 초점을 맞추기 전에resolvers
에 게이트웨이 API를 설치합니다.import { ApolloGateway } from "@apollo/gateway";
import { ApolloServer } from "apollo-server";
const port = 4000;
const gateway = new ApolloGateway({
serviceList: [
{ name: "people", url: "http://localhost:4001" }
]
});
const server = new ApolloServer({
gateway,
subscriptions: false
});
server.listen({ port }).then(({ url }) => {
console.log(`Server ready at ${url}`);
});
게이트웨이 단계에서 우리는 다시 index.js
을 실례화했지만 이번에는 모드가 아닌 ApolloServer
를 가져오고 실례화했다.ApolloGateway
구조 함수에 ApolloServer
대상 수조를 전달하는데 그 중에서 각 대상은 우리가 인터페이스로 구성하고자 하는 연방 모델을 설명한다.마지막으로, 우리는 이 ApolloGateway
에서 serviceList
를 subscriptions
로 설정합니다. 왜냐하면 Apollo Gateway는 구독을 지원하지 않기 때문입니다.현재 코드가 있으면 GraphQL API를 처음 시작할 수 있습니다.이를 위해서는 세 개의 새 스크립트 업데이트
false
중 ApolloServer
을 만들어야 합니다.우리는 scripts
스크립트를 만들어서 package.json
people 서비스를 시작하고 dev:people
스크립트를 만들어서people 서비스의 포트가 사용할 수 있기를 기다린 다음 nodemon
로 게이트웨이 API를 시작합니다.마지막으로, 우리는 dev:gateway
스크립트를 만들고 nodemon
와일드카드를 사용하여 모든 dev
스크립트를 시작합니다.{
...
"scripts": {
"dev": "concurrently -k npm:dev:*",
"dev:people": "nodemon -r esm ./people/index.js",
"dev:gateway": "wait-on tcp:4001 && nodemon -r esm ./index.js"
},
...
}
노드를 실행할 때 엔지니어 서비스와 게이트웨이 API 프로세스에 concurrently
(또는 dev:-
플래그를 사용하여 모듈을 미리 로드합니다-r
.js(esm 패키지의 요구에 따라).GraphQL API가 http://localhost:4000/graphql에서 사용할 수 있는지 확인하기 위해 지금
--require
를 실행합니다.너도 이제 브라우저의 이 URL에서 GraphQL 놀이터를 열 수 있다.이어서 우리는 영화 서비스를 건설할 것이다.films 서비스의 모델은people 서비스보다 더 복잡할 것입니다.
esm
형식을 추가하는 것 외에 이전에 만든 npm run dev
형식을 인용하고 확장하기 때문입니다.먼저 가져오기 및 유형 정의를 Film
에 설정합니다.import { ApolloServer, gql } from "apollo-server";
import { buildFederatedSchema } from "@apollo/federation";
import { films } from "../data.js";
const port = 4002;
const typeDefs = gql`
type Film {
id: ID!
title: String
actors: [Person]
director: Person
}
extend type Person @key(fields: "id") {
id: ID! @external
appearedIn: [Film]
directed: [Film]
}
extend type Query {
film(id: ID!): Film
films: [Film]
}
`;
영화 서비스에서 Person
유형을 사용하려면 다시 정의해야 하지만, 이번에는 films/index.js
키워드를 앞에 두어야 한다.우리는 그것의 키 필드 Person
를 포함해야 하지만, 이번에는 다른 서비스에서 정의된 것을 표시하기 위해dd extend
명령을 사용합니다.그 다음에 우리는 id
유형에 두 개의 새로운 필드를 추가해서 이 사람이 출연하거나 감독한 영화를 열거할 수 있다.@external
유형에서는 Person
대상에 영화에서 연기하거나 감독한 사람을 열거할 수 있지만 이번에는 이 영화와 관련된 사람이다.필름스 서비스의 Film
유형을 인용하고 확장함으로써 데이터 그래프의 두 방향에서 사람과 영화 간의 관계를 두루 훑어볼 수 있다. 설령 서로 다른 서비스에서 해당하는 유형을 정의했다 하더라도.다음은 영화 서비스에 추가된 모든 새로운 형식과 추가 필드 컴파일러가 필요합니다.다음 코드를
Person
에 추가합니다.// ...
const resolvers = {
Film: {
actors(film) {
return film.actors.map((actor) => ({ __typename: "Person", id: actor }));
},
director(film) {
return { __typename: "Person", id: film.director };
}
},
Person: {
appearedIn(person) {
return films.filter((film) =>
film.actors.find((actor) => actor === person.id)
);
},
directed(person) {
return films.filter((film) => film.director === person.id);
}
},
Query: {
film(_, { id }) {
return films.find((film) => film.id === id);
},
films() {
return films;
}
}
};
해석Person
의films/index.js
과actors
필드에서 영화 서비스 부서에서 이들에 대한 유일한 정보는 그들의 유일한 ID입니다. 하지만 이것은 괜찮습니다!Apollo Federation을 사용하여 이 필드를 해석하려면, people 서비스로 전송을 요청할 때 이 대상을 식별하기 위해 대상 (또는 대상 목록) 과 키 필드/값을 포함하는 대상을 되돌려보내기만 하면 됩니다.또한
directors
유형은 처음에 다른 서비스에서 정의되었지만, 우리는 인원 ID와 Film
ID가 일치하거나 __typename
그룹에 나타난 영화의 일치를 통해 영화 서비스가 여기에 추가한 새로운 필드를 분석해야 한다.추가할 마지막 코드
Person
는 이 서비스를 시작할 director
입니다. 우리가 people 서비스에서 했던 것처럼:// ...
const server = new ApolloServer({
schema: buildFederatedSchema([{ typeDefs, resolvers }]),
});
server.listen({ port }).then(({ url }) => {
console.log(`Films service ready at ${url}`);
});
게이트웨이 API에 영화 서비스를 추가해야 합니다actors
.// ...
const gateway = new ApolloGateway({
serviceList: [
{ name: "people", url: "http://localhost:4001" },
{ name: "films", url: "http://localhost:4002" } // NEW!
]
});
// ...
마지막으로, 우리는 films/index.js
에 영화 서비스를 시작하기 위해 다른 npm 스크립트를 추가하고, 인터페이스를 통해 영화 서비스의 포트를 즉시 기다리도록 요구할 것이다.{
...
"scripts": {
"dev": "concurrently -k npm:dev:*",
"dev:people": "nodemon -r esm ./people/index.js",
"dev:films": "nodemon -r esm ./films/index.js",
"dev:gateway": "wait-on tcp:4001 tcp:4002 && nodemon -r esm ./index.js"
},
...
}
GraphQL API는 현재 GraphQL 놀이공원에서 캐릭터와 영화를 예상대로 조회할 수 있도록 준비되어 있습니다.참고로 the final version of the code here를 볼 수 있습니다.나는 이 글이 네가 아폴로 연맹이 얼마나 친근한지 엿볼 수 있기를 바란다. 만약 네가 이전에 아폴로 서버의 경험이 조금 있었다면.인코딩 고마워요!
Reference
이 문제에 관하여(아폴로 연맹과 게이트웨이 입문), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mandiwise/getting-started-with-apollo-federation-and-gateway-4739텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)