Definiera tjänster och meddelanden i Protobuf
Skapa .proto-kontrakt och generera typade gränssnitt för NestJS-mikrotjänster.
Definiera tjänster och meddelanden i Protobuf är en gratis lektion i NestJS: backend-API:er för företag på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för NestJS: backend-API:er för företag, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i NestJS: backend-API:er för företag innehåller totalt 4 lektioner.
Varför Protobuf driver kontraktet
I en NestJS-baserad gRPC-mikrotjänst är .proto-filen den enda sanningskällan. Den definierar trådformatet, RPC-ytan och – när den har kompilerats – de TypeScript-typer som både klienten och servern delar.
- Meddelanden beskriver datastrukturerna som skickas över tråden.
- Tjänster deklarerar de anropbara RPC-metoderna samt deras begärande- och svarmeddelanden.
Till skillnad från REST + OpenAPI (där schemat ofta skrivs efter koden) skapar ni med gRPC kontraktet först och genererar koden utifrån det. Detta är en kontraktsförst-design.
En .proto-fils anatomi
Varje kontrakt börjar med att syntaxversionen och ett package deklareras. Paketet blir ett namnrymd som NestJS använder för att hitta tjänsten vid körning.
syntax = "proto3";— använd alltid proto3 för modern gRPC.package billing;— namnrymden som refereras i NestJS transportalternativ.
Nedan visas ett minimalt men komplett kontrakt för en faktureringstjänst.
// proto/billing.proto
syntax = "proto3";
package billing;
service InvoiceService {
rpc GetInvoice (GetInvoiceRequest) returns (Invoice);
}
message GetInvoiceRequest {
string id = 1;
}
message Invoice {
string id = 1;
string customer_id = 2;
int64 amount_cents = 3;
string currency = 4;
}Fältnumren är kontraktet
Varje fält har ett etikettnummer (det vill säga = 1, = 2 och så vidare). Det är dessa nummer – inte fältnamnen – som kodas på tråden.
- Återanvänd eller numrera aldrig om ett befintligt fält; det bryter binär kompatibilitet med distribuerade klienter.
- Etiketter från 1 till 15 använder en byte; reservera dem för de fält som skickas oftast.
- Ni kan tryggt byta namn på ett fält (namnet är lokalt för den genererade koden), men ändra aldrig dess nummer eller typ.
När ni tar bort ett fält markerar ni dess nummer som reserved så att det aldrig återanvänds av misstag.
message Invoice {
reserved 5, 6;
reserved "legacy_tax_field";
string id = 1;
string customer_id = 2;
int64 amount_cents = 3;
string currency = 4;
}Skalära typer och int64-fällan
Proto3:s skalära typer mappas till TypeScript, men mappningen har fallgropar för företags-API:er som hanterar pengar eller ID:n.
string→string,bool→boolean,int32/float/double→number.int64,uint64,fixed64representeras somstring(ellerLong) av de flesta laddare, eftersom JS-tal förlorar precision över 2^53.
För amount_cents som int64 bör det genererade gränssnittet behandla värdet som en sträng för att undvika omärkbar avrundning av stora värden.
// Generated-style interface for the Invoice message
export interface Invoice {
id: string;
customerId: string;
// int64 surfaces as string to preserve precision
amountCents: string;
currency: string;
}snake_case in, camelCase out
Protobuf-konventionen är snake_case för fältnamn. NestJS gRPC-laddaren (@grpc/proto-loader) använder som standard keepCase: false, vilket konverterar fält till camelCase i de genererade objekten och körningsobjekten.
customer_idi.protoblircustomerIdi TypeScript.- Om ni anger
keepCase: truemåste ni läsacustomer_idordagrant – detta är en vanlig källa tillundefined-buggar.
Välj en konvention per projekt och konfigurera laddaren konsekvent.
// main.ts transport options
import { Transport, GrpcOptions } from '@nestjs/microservices';
import { join } from 'path';
export const grpcOptions: GrpcOptions = {
transport: Transport.GRPC,
options: {
package: 'billing',
protoPath: join(__dirname, 'proto/billing.proto'),
loader: { keepCase: false, longs: String, enums: String },
},
};Enum-typer och regeln för nollvärdet
Proto3-enumtyper måste definiera ett nollvärde som första post – det är det implicita standardvärdet när ett fält inte är satt på tråden.
- Namnge nollvärdet
*_UNSPECIFIEDså att ett utelämnat värde kan skiljas från det "första riktiga tillståndet". - Enumtyper är öppna i proto3: en klient med ett nyare schema kan skicka ett nummer som servern inte känner till, så hantera alltid standardgrenen.
Med enums: String i laddaren kommer värdena fram som sina strängnamn i TypeScript.
enum InvoiceStatus {
INVOICE_STATUS_UNSPECIFIED = 0;
INVOICE_STATUS_DRAFT = 1;
INVOICE_STATUS_SENT = 2;
INVOICE_STATUS_PAID = 3;
INVOICE_STATUS_VOID = 4;
}
message Invoice {
string id = 1;
InvoiceStatus status = 5;
}Tjänstegränssnittet i NestJS
Varje rpc-metod blir en metod i ett genererat TypeScript-gränssnitt. Enkla RPC-anrop returnerar en Observable (eller Promise) med svarmeddelandet i NestJS.
Vanligtvis skriver eller genererar ni ett gränssnitt manuellt och injicerar klienten via ClientGrpc.getService().
import { Observable } from 'rxjs';
export interface GetInvoiceRequest {
id: string;
}
export interface InvoiceServiceClient {
getInvoice(request: GetInvoiceRequest): Observable<Invoice>;
}
export interface Invoice {
id: string;
customerId: string;
amountCents: string;
currency: string;
status: string;
}Implementera tjänstehanteraren
På serversidan dekorerar ni en kontrollmetod med @GrpcMethod. Det första argumentet är tjänstenamnet från .proto, och det andra är rpc-metodnamnet.
- Metoden tar emot det avkodade begärandemeddelandet som ett vanligt objekt.
- Returnera svarmeddelandets struktur direkt, eller en
Observable/Promisesom innehåller den.
import { Controller } from '@nestjs/common';
import { GrpcMethod } from '@nestjs/microservices';
@Controller()
export class InvoiceController {
@GrpcMethod('InvoiceService', 'GetInvoice')
getInvoice(data: { id: string }): Invoice {
return {
id: data.id,
customerId: 'cust_42',
amountCents: '120000',
currency: 'EUR',
status: 'INVOICE_STATUS_SENT',
};
}
}Nästa meddelanden och komposition
Meddelanden kan sättas samman. Ett fält kan vara av en annan meddelandetyp, vilket gör att ni kan modellera rika aggregat utan att platta ut allt till en enda struktur.
- Referera till en meddelandetyp med namn; definiera den före eller efter användningen – ordningen spelar ingen roll i en fil.
- Ett nästlat meddelande som inte har satts kommer som
undefinedi TypeScript, så kontrollera det innan ni kommer åt dess fält.
message Money {
int64 amount_cents = 1;
string currency = 2;
}
message LineItem {
string sku = 1;
uint32 quantity = 2;
Money unit_price = 3;
}
message Invoice {
string id = 1;
string customer_id = 2;
Money total = 3;
repeated LineItem line_items = 4;
}Upprepade fält, maps och strömmande RPC-anrop
Två ytterligare byggstenar kompletterar de flesta företagskontrakt:
repeated T field = N;→ en TypeScript-arrayT[]. En tom lista och en lista som inte har satts kan inte skiljas åt på tråden.map<string, T>→ en TypeScript-post; användbart för etiketter och metadata.
Sätt prefixet stream på begäran, svaret eller båda för att deklarera serverströmning, klientströmning eller dubbelriktade RPC-anrop. I NestJS använder strömmande metoder @GrpcStreamMethod och fungerar med RxJS-strömmar av typen Observable.
service InvoiceService {
rpc GetInvoice (GetInvoiceRequest) returns (Invoice);
// server-streaming: many invoices for one query
rpc ListInvoices (ListInvoicesRequest) returns (stream Invoice);
}
message ListInvoicesRequest {
string customer_id = 1;
map<string, string> filters = 2;
}Generera typade gränssnitt med ts-proto
Handskrivna gränssnitt kan avvika från .proto. Använd en generator som ts-proto (via protoc) för att skapa gränssnitt, hjälpfunktioner för kodning/avkodning samt en NestJS-anpassad klient-/tjänststruktur som alltid hålls synkroniserad med kontraktet.
nestJs=truegenererar de gRPC-tjänst- och klientgränssnitt som NestJS förväntar sig.- Kör den i CI så att en föråldrad genererad fil gör att bygget misslyckas, vilket garanterar att koden överensstämmer med kontraktet.
// package.json script
{
"scripts": {
"proto:gen": "protoc --plugin=node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=./src/generated --ts_proto_opt=nestJs=true,outputServices=grpc-js,useDate=false ./proto/billing.proto"
}
}Snabbkontroll: utveckla kontraktet
Ni har distribuerat Invoice med string customer_id = 2;. Ett nytt krav innebär att ni måste sluta skicka customer_id och i stället skicka ett mer detaljerat nästlat meddelande, Customer customer = 6;. Äldre distribuerade klienter måste fortsätta fungera.
Sammanfattning: Protobuf med kontraktet först
Ni kan nu skapa ett tjänstekontrakt och omvandla det till typade NestJS-gränssnitt:
- Struktur:
syntax = proto3, enpackage-namnrymd,message-strukturer och enservicemedrpc-metoder. - Fältnummer är trådkontraktet – utveckla endast genom tillägg; markera uttjänta nummer och namn med
reserved. - Typmappning: var uppmärksam på
int64→string, snake_case → camelCase; enumtyper behöver ett nollvärde med*_UNSPECIFIED. - Komposition: nästlade meddelanden,
repeated-arrayer,mapochstream-RPC-anrop. - Generering: härled typer från
.protomed ts-proto i CI så att koden aldrig kan avvika från kontraktet.
Lär dig TypeScript med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 20
- Lektioner
- 76
Vanliga frågor
Är lektionen ”Definiera tjänster och meddelanden i Protobuf” gratis?
Ja – hela texten till ”Definiera tjänster och meddelanden i Protobuf” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i NestJS: backend-API:er för företag, kan Ni uppgradera till CoddyKit PRO. Kursen i NestJS: backend-API:er för företag innehåller totalt 4 lektioner.
Vad lär jag mig i ”Definiera tjänster och meddelanden i Protobuf”?
Skapa .proto-kontrakt och generera typade gränssnitt för NestJS-mikrotjänster. Ni övar på NestJS: backend-API:er för företag med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig NestJS: backend-API:er för företag?
Du behöver inga förkunskaper. Utbildningen i NestJS: backend-API:er för företag på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.
Hur lång tid tar lektionen ”Definiera tjänster och meddelanden i Protobuf”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här NestJS: backend-API:er för företag-lektionen?
Ja. Varje NestJS: backend-API:er för företag-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Definiera tjänster och meddelanden i Protobuf
- Implementera och använda gRPC-metoder
- Strömmande RPC:er och backpressure
- Utveckling av kontrakt och bakåtkompatibilitet