Wybór wzorców
AI rekomenduje odpowiednie wzorce architektoniczne dla twojego przypadku użycia
Architektura systemów stanowi fundament udanych projektów oprogramowania. Ta lekcja pokazuje, jak możliwości AI Cursor transformują projektowanie architektury z abstrakcyjnego, zależnego od doświadczenia procesu w systematyczne, prowadzone podejście, które uwzględnia najlepsze praktyki i wzorce.
Tradycyjne projektowanie architektury wymaga lat doświadczenia i głębokiej znajomości wzorców, kompromisów i nowych technologii. Wsparcie AI demokratyzuje tę wiedzę, pomagając programistom podejmować świadome decyzje architektoniczne i unikać częstych pułapek.
Wybór wzorców
AI rekomenduje odpowiednie wzorce architektoniczne dla twojego przypadku użycia
Projektowanie skalowalności
AI pomaga projektować systemy które skalują się poziomo i pionowo
Wybór technologii
AI sugeruje optymalne stosy technologiczne oparte na wymaganiach
Analiza kompromisów
AI wyjaśnia plusy, minusy i implikacje decyzji architektonicznych
Analiza domeny
// Poproś AI o analizę domeny i sugestie granic"Przeanalizuj ten system e-commerce i zasugeruj granice mikrousług:- Zarządzanie użytkownikami i autoryzacja- Katalog produktów i inwentarz- Koszyk i checkout- Przetwarzanie i realizacja zamówień- Przetwarzanie płatności- System powiadomień- Analityka i raportowanie
Rozważ: własność danych, potrzeby skalowania, granice zespołów i niezależność wdrożeń"
Projektowanie serwisów
// AI projektuje architekturę serwisów"Zaprojektuj architekturę mikrousług z:- Wzorcami komunikacji serwisów (sync/async)- Strategiami spójności danych- Mechanizmem service discovery- Projektem API gateway- Rozproszonym tracingiem- Wzorcami circuit breaker"
// AI generuje architekturęexport interface ServiceArchitecture { services: { name: string; responsibilities: string[]; api: APIDefinition; database: DatabaseConfig; dependencies: string[]; scalingStrategy: ScalingConfig; }[];
communication: { synchronous: RestAPIConfig; asynchronous: MessageQueueConfig; graphql?: GraphQLGatewayConfig; };
infrastructure: { serviceDiscovery: 'consul' | 'eureka' | 'kubernetes'; loadBalancing: LoadBalancerConfig; monitoring: MonitoringStack; };}
Plan implementacji
# AI tworzy plan implementacji"Wygeneruj manifesty Kubernetes dla mikrousług:- Definicje serwisów z odpowiednimi etykietami- Konfiguracje deploymentów z limitami zasobów- ConfigMaps dla ustawień specyficznych dla środowiska- Zarządzanie sekretami- Polityki sieciowe dla komunikacji serwisów- Konfiguracja Ingress"
# AI generuje manifest serwisuapiVersion: v1kind: Servicemetadata: name: user-service labels: app: user-service tier: backendspec: selector: app: user-service ports: - port: 80 targetPort: 8080 protocol: TCP type: ClusterIP---apiVersion: apps/v1kind: Deploymentmetadata: name: user-servicespec: replicas: 3 selector: matchLabels: app: user-service template: metadata: labels: app: user-service version: v1 spec: containers: - name: user-service image: user-service:1.0.0 ports: - containerPort: 8080 env: - name: DATABASE_URL valueFrom: secretKeyRef: name: user-db-secret key: connection-string - name: KAFKA_BROKERS value: "kafka-0.kafka:9092,kafka-1.kafka:9092" resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m" livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 5 periodSeconds: 5
// AI implementuje event sourcing"Zaprojektuj system event sourcing dla zarządzania zamówieniami:- Projekt event store- Strategia wersjonowania zdarzeń- Obsługa projekcji- Optymalizacja snapshotów- Implementacja CQRS"
// AI generuje framework event sourcinginterface Event { id: string; aggregateId: string; type: string; version: number; timestamp: Date; data: any; metadata: EventMetadata;}
abstract class AggregateRoot { private uncommittedEvents: Event[] = []; protected version: number = 0;
constructor(public readonly id: string) {}
protected applyEvent(event: Event): void { this.handleEvent(event); this.version = event.version; }
protected raiseEvent(eventData: any): void { const event: Event = { id: generateId(), aggregateId: this.id, type: eventData.constructor.name, version: this.version + 1, timestamp: new Date(), data: eventData, metadata: this.getEventMetadata() };
this.applyEvent(event); this.uncommittedEvents.push(event); }
getUncommittedEvents(): Event[] { return this.uncommittedEvents; }
markEventsAsCommitted(): void { this.uncommittedEvents = []; }
abstract handleEvent(event: Event): void;
private getEventMetadata(): EventMetadata { return { userId: getCurrentUser(), correlationId: getCorrelationId(), causationId: getCausationId() }; }}
// Implementacja agregatu zamówieniaclass Order extends AggregateRoot { private items: OrderItem[] = []; private status: OrderStatus = 'pending'; private customerId: string;
static create(customerId: string): Order { const order = new Order(generateId()); order.raiseEvent(new OrderCreated(customerId)); return order; }
addItem(productId: string, quantity: number, price: number): void { if (this.status !== 'pending') { throw new Error('Nie można dodać pozycji do zamówienia niepending'); }
this.raiseEvent(new ItemAdded(productId, quantity, price)); }
submit(): void { if (this.items.length === 0) { throw new Error('Nie można wysłać pustego zamówienia'); }
this.raiseEvent(new OrderSubmitted()); }
handleEvent(event: Event): void { switch (event.type) { case 'OrderCreated': this.customerId = event.data.customerId; break; case 'ItemAdded': this.items.push({ productId: event.data.productId, quantity: event.data.quantity, price: event.data.price }); break; case 'OrderSubmitted': this.status = 'submitted'; break; } }}
// Implementacja event storeclass EventStore { async saveEvents(events: Event[]): Promise<void> { const transaction = await this.db.transaction();
try { for (const event of events) { await transaction.insert('events', { event_id: event.id, aggregate_id: event.aggregateId, event_type: event.type, event_version: event.version, event_data: JSON.stringify(event.data), event_metadata: JSON.stringify(event.metadata), created_at: event.timestamp }); }
await transaction.commit();
// Opublikuj zdarzenia do message bus await this.publishEvents(events); } catch (error) { await transaction.rollback(); throw error; } }
async getEvents( aggregateId: string, fromVersion?: number ): Promise<Event[]> { const query = this.db .select('*') .from('events') .where('aggregate_id', aggregateId) .orderBy('event_version');
if (fromVersion) { query.where('event_version', '>', fromVersion); }
const rows = await query;
return rows.map(row => ({ id: row.event_id, aggregateId: row.aggregate_id, type: row.event_type, version: row.event_version, timestamp: row.created_at, data: JSON.parse(row.event_data), metadata: JSON.parse(row.event_metadata) })); }}
// AI projektuje architekturę napędzaną wiadomościami"Utwórz architekturę napędzaną wiadomościami z:- Wyborem message brokera (Kafka/RabbitMQ/SQS)- Schematami wiadomości i wersjonowaniem- Strategiami retry i DLQ- Obsługą idempotentności- Gwarancjami kolejności wiadomości"
// AI implementuje framework wiadomościinterface MessageBus { publish<T>(topic: string, message: Message<T>): Promise<void>; subscribe<T>( topic: string, handler: MessageHandler<T>, options?: SubscriptionOptions ): Promise<Subscription>;}
class KafkaMessageBus implements MessageBus { private producer: KafkaProducer; private consumers: Map<string, KafkaConsumer> = new Map();
async publish<T>(topic: string, message: Message<T>): Promise<void> { const record = { topic, key: message.key, value: JSON.stringify(message), headers: { 'message-id': message.id, 'correlation-id': message.correlationId, 'schema-version': message.schemaVersion, 'content-type': 'application/json' }, partition: message.partition };
await this.producer.send({ topic, messages: [record] });
// Emituj metryki this.metrics.increment('messages.published', { topic, messageType: message.type }); }
async subscribe<T>( topic: string, handler: MessageHandler<T>, options: SubscriptionOptions = {} ): Promise<Subscription> { const consumer = new KafkaConsumer({ groupId: options.consumerGroup || `${topic}-consumer`, ...this.config });
await consumer.connect(); await consumer.subscribe({ topic, fromBeginning: options.fromBeginning });
const wrappedHandler = this.wrapHandler(handler, options);
consumer.run({ eachMessage: async ({ message, partition }) => { const parsedMessage = this.parseMessage<T>(message);
try { await wrappedHandler(parsedMessage);
// Zatwierdź offset po udanym przetworzeniu await consumer.commitOffsets([{ topic, partition, offset: (parseInt(message.offset) + 1).toString() }]); } catch (error) { await this.handleError(error, parsedMessage, options); } } });
this.consumers.set(topic, consumer);
return { unsubscribe: () => this.unsubscribe(topic) }; }
private wrapHandler<T>( handler: MessageHandler<T>, options: SubscriptionOptions ): MessageHandler<T> { return async (message: Message<T>) => { // Sprawdzenie idempotentności if (options.idempotent) { const processed = await this.checkIdempotency(message.id); if (processed) { this.logger.info('Wiadomość już przetworzona', { messageId: message.id }); return; } }
// Przetwórz wiadomość await handler(message);
// Oznacz jako przetworzoną if (options.idempotent) { await this.markProcessed(message.id); } }; }
private async handleError( error: Error, message: Message<any>, options: SubscriptionOptions ): Promise<void> { this.logger.error('Przetwarzanie wiadomości nie powiodło się', { error: error.message, messageId: message.id, topic: message.topic });
// Logika retry if (options.retry) { const retryCount = message.headers?.['retry-count'] || 0;
if (retryCount < options.retry.maxAttempts) { // Opublikuj do retry topic z opóźnieniem await this.publishRetry(message, retryCount + 1); } else { // Wyślij do DLQ await this.publishToDLQ(message, error); } } }}
// AI implementuje wzorzec saga"Implementuj rozproszoną sagę dla przetwarzania zamówień:- Orkiestracja vs choreografia- Logika kompensacji- Persystencja stanu- Obsługa timeoutów- Monitorowanie i debugowanie"
// AI tworzy orkiestrator sagaabstract class Saga<TState> { protected state: TState; private steps: SagaStep<TState>[] = []; private currentStep: number = 0;
constructor( private sagaId: string, private repository: SagaRepository ) {}
protected addStep(step: SagaStep<TState>): void { this.steps.push(step); }
async execute(): Promise<void> { try { // Załaduj istniejący stan jeśli wznawiasz await this.loadState();
// Wykonaj pozostałe kroki while (this.currentStep < this.steps.length) { const step = this.steps[this.currentStep];
try { await this.executeStep(step); this.currentStep++; await this.saveState(); } catch (error) { // Kompensuj i rzuć await this.compensate(); throw error; } }
// Oznacz sagę jako ukończoną await this.complete(); } catch (error) { await this.fail(error); throw error; } }
private async executeStep(step: SagaStep<TState>): Promise<void> { this.logger.info(`Wykonywanie kroku: ${step.name}`, { sagaId: this.sagaId, step: this.currentStep });
// Ustaw timeout dla kroku const timeout = setTimeout(() => { throw new Error(`Krok ${step.name} przekroczył limit czasu`); }, step.timeout || 30000);
try { this.state = await step.execute(this.state); clearTimeout(timeout); } catch (error) { clearTimeout(timeout); throw error; } }
private async compensate(): Promise<void> { this.logger.info('Rozpoczynanie kompensacji', { sagaId: this.sagaId });
// Wykonaj kompensację w odwrotnej kolejności for (let i = this.currentStep - 1; i >= 0; i--) { const step = this.steps[i];
if (step.compensate) { try { await step.compensate(this.state); } catch (error) { this.logger.error('Kompensacja nie powiodła się', { sagaId: this.sagaId, step: step.name, error: error.message }); } } } }
private async saveState(): Promise<void> { await this.repository.save({ sagaId: this.sagaId, type: this.constructor.name, state: this.state, currentStep: this.currentStep, status: 'running', updatedAt: new Date() }); }}
// Saga przetwarzania zamówieńclass OrderProcessingSaga extends Saga<OrderSagaState> { constructor(sagaId: string, order: Order) { super(sagaId);
this.state = { orderId: order.id, customerId: order.customerId, items: order.items, paymentId: null, inventoryReservations: [], shipmentId: null };
// Zdefiniuj kroki saga this.addStep({ name: 'ReserveInventory', execute: async (state) => { const reservations = await this.inventoryService .reserveItems(state.items); return { ...state, inventoryReservations: reservations }; }, compensate: async (state) => { await this.inventoryService .releaseReservations(state.inventoryReservations); }, timeout: 10000 });
this.addStep({ name: 'ProcessPayment', execute: async (state) => { const payment = await this.paymentService .processPayment(state.orderId, state.totalAmount); return { ...state, paymentId: payment.id }; }, compensate: async (state) => { if (state.paymentId) { await this.paymentService.refund(state.paymentId); } }, timeout: 30000 });
this.addStep({ name: 'CreateShipment', execute: async (state) => { const shipment = await this.shippingService .createShipment(state.orderId, state.items); return { ...state, shipmentId: shipment.id }; }, compensate: async (state) => { if (state.shipmentId) { await this.shippingService.cancelShipment(state.shipmentId); } }, timeout: 15000 }); }}
Równoważenie obciążenia
Efektywnie dystrybuuj ruch między instancjami
Zarządzanie sesjami
Obsługuj sesje w środowisku rozproszonym
Partycjonowanie danych
Shard danych dla skalowania poziomego
Strategia cache
Implementuj rozproszone cache’owanie
// AI projektuje skalowalną architekturę"Zaprojektuj architekturę skalowalną poziomo dla platformy social media:- Obsługuj miliony równoczesnych użytkowników- Wiadomości i powiadomienia w czasie rzeczywistym- Przechowywanie i dostarczanie mediów- Globalna dystrybucja- Optymalizacja kosztów"
// AI generuje projekt skalowalnościinterface ScalableArchitecture { // Warstwa równoważenia obciążenia loadBalancing: { global: { type: 'GeoDNS'; regions: string[]; failoverStrategy: 'active-passive'; }; regional: { type: 'ALB' | 'NLB'; algorithm: 'least-connections'; healthChecks: HealthCheckConfig; }; };
// Warstwa aplikacji application: { autoScaling: { minInstances: number; maxInstances: number; targetCPU: number; scaleUpThreshold: number; scaleDownThreshold: number; }; deployment: { strategy: 'blue-green' | 'rolling' | 'canary'; rollbackTriggers: string[]; }; };
// Warstwa danych data: { primary: { type: 'Aurora PostgreSQL'; replication: 'multi-master'; readReplicas: number; sharding: ShardingStrategy; }; cache: { type: 'Redis Cluster'; evictionPolicy: 'LRU'; replication: boolean; }; search: { type: 'Elasticsearch'; shards: number; replicas: number; }; };
// Warstwa kolejki wiadomości messaging: { type: 'Kafka'; partitions: number; replicationFactor: number; retentionHours: number; };}
// Implementacja shardinguclass ShardManager { private shards: Map<string, DatabaseShard> = new Map();
constructor(private config: ShardingConfig) { this.initializeShards(); }
private initializeShards(): void { for (let i = 0; i < this.config.shardCount; i++) { const shard = new DatabaseShard({ id: i, connectionString: this.config.getConnectionString(i), keyRange: this.calculateKeyRange(i) });
this.shards.set(shard.id, shard); } }
getShardForKey(key: string): DatabaseShard { const hash = this.hashKey(key); const shardId = hash % this.config.shardCount; return this.shards.get(shardId.toString()); }
async reshardData(newShardCount: number): Promise<void> { // AI implementuje logikę reshardingu const migrationPlan = this.createMigrationPlan(newShardCount);
for (const migration of migrationPlan) { await this.migrateShard(migration); } }
private hashKey(key: string): number { // Implementacja consistent hashing return createHash('sha256') .update(key) .digest() .readUInt32BE(0); }}
// AI implementuje cache wielopoziomowy"Zaprojektuj strategię cache'owania dla platformy e-commerce:- Cache przeglądarki dla statycznych zasobów- CDN dla globalnej dystrybucji- Cache na poziomie aplikacji- Cache zapytań bazodanowych- Strategia unieważniania cache"
class CacheArchitecture { // Poziom 1: Cache przeglądarki configureBrowserCache() { return { static: { maxAge: 31536000, // 1 rok immutable: true }, dynamic: { maxAge: 0, mustRevalidate: true, etag: true } }; }
// Poziom 2: Konfiguracja CDN configureCDN() { return { provider: 'CloudFront', origins: [ { domain: 'api.example.com', cacheByHeaders: ['Accept', 'Authorization'], cacheByQueryString: ['version', 'lang'] } ], behaviors: [ { path: '/api/*', ttl: 300, compress: true }, { path: '/static/*', ttl: 86400, compress: true } ] }; }
// Poziom 3: Cache aplikacji class ApplicationCache { private localCache = new LRUCache<string, any>({ max: 1000, ttl: 1000 * 60 * 5 // 5 minut });
private redisCache: RedisClient;
async get<T>(key: string): Promise<T | null> { // Najpierw sprawdź lokalny cache const local = this.localCache.get(key); if (local) return local;
// Sprawdź Redis const cached = await this.redisCache.get(key); if (cached) { const parsed = JSON.parse(cached); this.localCache.set(key, parsed); return parsed; }
return null; }
async set<T>( key: string, value: T, ttl: number = 3600 ): Promise<void> { // Ustaw w obu cache'ach this.localCache.set(key, value); await this.redisCache.setex( key, ttl, JSON.stringify(value) );
// Opublikuj zdarzenie unieważnienia dla innych instancji await this.publishInvalidation(key); }
async invalidate(pattern: string): Promise<void> { // Wyczyść lokalny cache for (const key of this.localCache.keys()) { if (key.match(pattern)) { this.localCache.delete(key); } }
// Wyczyść klucze Redis const keys = await this.redisCache.keys(pattern); if (keys.length > 0) { await this.redisCache.del(...keys); }
// Powiadom inne instancje await this.publishInvalidation(pattern); } }}
// AI implementuje architekturę zero trust"Zaprojektuj architekturę bezpieczeństwa zero trust:- Autoryzacja serwis-do-serwis- Szyfrowanie end-to-end- Zasada najmniejszych uprawnień- Ciągła weryfikacja- Monitorowanie bezpieczeństwa"
class ZeroTrustArchitecture { // Konfiguracja service mesh configureServiceMesh() { return { type: 'Istio', mtls: { mode: 'STRICT', certRotation: '24h' }, authorization: { defaultPolicy: 'DENY', rules: this.generateAuthorizationRules() }, observability: { tracing: true, metrics: true, accessLogs: true } }; }
// Bezpieczeństwo API Gateway class SecureAPIGateway { async authenticateRequest(request: Request): Promise<AuthContext> { // Wyciągnij token const token = this.extractToken(request); if (!token) { throw new UnauthorizedError('Brak tokena autoryzacji'); }
// Weryfikuj JWT const claims = await this.verifyJWT(token);
// Sprawdź wiązanie tokena if (claims.cnf) { await this.verifyTokenBinding(request, claims.cnf); }
// Weryfikuj zaufanie urządzenia const deviceTrust = await this.verifyDeviceTrust(request); if (!deviceTrust.trusted) { throw new UnauthorizedError('Niezaufane urządzenie'); }
// Sprawdź wynik ryzyka użytkownika const riskScore = await this.calculateRiskScore(claims.sub, request); if (riskScore > 0.7) { await this.triggerMFA(claims.sub); }
return { userId: claims.sub, permissions: await this.getPermissions(claims.sub), sessionId: claims.sid, riskScore }; }
private async verifyJWT(token: string): Promise<JWTClaims> { // Weryfikuj podpis const decoded = jwt.verify(token, this.publicKey, { algorithms: ['RS256'], issuer: this.config.issuer, audience: this.config.audience });
// Sprawdź cofnięcie const revoked = await this.checkRevocation(decoded.jti); if (revoked) { throw new UnauthorizedError('Token cofnięty'); }
return decoded; } }
// Szyfrowanie danych class EncryptionService { async encryptSensitiveData( data: any, classification: DataClassification ): Promise<EncryptedData> { // Wybierz szyfrowanie na podstawie klasyfikacji const strategy = this.getEncryptionStrategy(classification);
// Wygeneruj DEK (klucz szyfrowania danych) const dek = await this.generateDEK();
// Zaszyfruj dane const encrypted = await strategy.encrypt(data, dek);
// Zaszyfruj DEK z KEK (klucz szyfrowania kluczy) const encryptedDEK = await this.kms.encrypt(dek, { keyId: strategy.kekId, context: { classification: classification, timestamp: Date.now() } });
return { data: encrypted, dek: encryptedDEK, algorithm: strategy.algorithm, classification }; } }}
// AI projektuje architekturę wydajności"Utwórz architekturę wysokiej wydajności dla analityki czasu rzeczywistego:- Odpowiedź zapytania poniżej sekundy- Obsługa 1M zdarzeń/sekundę- Agregacje w czasie rzeczywistym- Analiza danych historycznych- Efektywne kosztowo przechowywanie"
class PerformanceArchitecture { // Pipeline ingestion zdarzeń class EventIngestionPipeline { private buffer: RingBuffer<Event>; private batchProcessor: BatchProcessor;
async ingest(event: Event): Promise<void> { // Dodaj do ring buffer dla batchingu this.buffer.add(event);
// Przetwórz jeśli batch jest pełny if (this.buffer.size >= this.batchSize) { await this.processBatch(); } }
private async processBatch(): Promise<void> { const batch = this.buffer.drain();
// Przetwarzanie równoległe await Promise.all([ this.writeToHotStorage(batch), this.updateRealTimeAggregates(batch), this.publishToStreamProcessors(batch) ]); }
private async writeToHotStorage(events: Event[]): Promise<void> { // Zapisz do bazy danych szeregów czasowych dla najnowszych danych const timeSeries = events.map(e => ({ metric: e.type, timestamp: e.timestamp, value: e.value, tags: e.tags }));
await this.timeSeriesDB.writeBatch(timeSeries); } }
// Optymalizacja zapytań class QueryOptimizer { async optimizeQuery(query: AnalyticsQuery): Promise<OptimizedQuery> { // Analizuj wzorzec zapytania const pattern = this.analyzePattern(query);
// Wybierz strategię wykonania if (pattern.isRealTime && pattern.timeRange < 3600) { return this.optimizeForHotPath(query); } else if (pattern.isAggregation) { return this.optimizeForPreAggregates(query); } else { return this.optimizeForColdStorage(query); } }
private optimizeForHotPath(query: AnalyticsQuery): OptimizedQuery { return { executor: 'TimeSeriesDB', indexes: ['timestamp', 'metric_type'], cacheKey: this.generateCacheKey(query), ttl: 60, parallel: true }; } }
// Warstwowe przechowywanie class StorageTiering { async tierData(): Promise<void> { // Warstwa gorąca: Ostatnie 24 godziny w pamięci // Warstwa ciepła: Ostatnie 30 dni na SSD // Warstwa zimna: Starsze niż 30 dni w object storage
const cutoffs = { hot: Date.now() - 24 * 60 * 60 * 1000, warm: Date.now() - 30 * 24 * 60 * 60 * 1000 };
// Przenieś dane między warstwami await Promise.all([ this.moveToWarmTier(cutoffs.hot), this.moveToColdTier(cutoffs.warm), this.compactColdTier() ]); } }}
# AI tworzy architekturę cloud-native"Zaprojektuj architekturę aplikacji natywną dla Kubernetes:- Serwisy bezstanowe- ConfigMaps i Secrets- Health checks i sondy- Limity zasobów- Horizontal pod autoscaling"
# AI generuje architekturęapiVersion: v1kind: ConfigMapmetadata: name: app-configdata: database.host: "postgres.database.svc.cluster.local" cache.nodes: "redis-0.redis:6379,redis-1.redis:6379" features.flags: | { "new-ui": true, "beta-features": false }---apiVersion: apps/v1kind: StatefulSetmetadata: name: app-statefulspec: serviceName: app-stateful replicas: 3 selector: matchLabels: app: app-stateful template: metadata: labels: app: app-stateful annotations: prometheus.io/scrape: "true" prometheus.io/port: "9090" spec: initContainers: - name: init-schema image: migrate/migrate command: ['migrate', '-path', '/migrations', '-database', '$(DATABASE_URL)', 'up'] env: - name: DATABASE_URL valueFrom: secretKeyRef: name: database-secret key: url containers: - name: app image: myapp:latest ports: - containerPort: 8080 name: http - containerPort: 9090 name: metrics env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP envFrom: - configMapRef: name: app-config - secretRef: name: app-secrets resources: requests: memory: "512Mi" cpu: "500m" limits: memory: "1Gi" cpu: "1000m" livenessProbe: httpGet: path: /health/live port: 8080 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /health/ready port: 8080 initialDelaySeconds: 5 periodSeconds: 5 startupProbe: httpGet: path: /health/startup port: 8080 failureThreshold: 30 periodSeconds: 10 volumeMounts: - name: data mountPath: /data volumeClaimTemplates: - metadata: name: data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 10Gi---apiVersion: autoscaling/v2kind: HorizontalPodAutoscalermetadata: name: app-hpaspec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: app-deployment minReplicas: 3 maxReplicas: 100 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 - type: Resource resource: name: memory target: type: Utilization averageUtilization: 80 - type: Pods pods: metric: name: http_requests_per_second target: type: AverageValue averageValue: "1000" behavior: scaleDown: stabilizationWindowSeconds: 300 policies: - type: Percent value: 10 periodSeconds: 60 scaleUp: stabilizationWindowSeconds: 0 policies: - type: Percent value: 100 periodSeconds: 15 - type: Pods value: 4 periodSeconds: 15 selectPolicy: Max
Nowoczesne projektowanie architektury rzadko jest wysiłkiem pojedynczej osoby. Funkcje współpracy Cursor umożliwiają zespołom projektowanie, przeglądanie i implementację architektur razem, zapewniając zgodność i dzielenie się wiedzą w całej organizacji.
// Zespół dyskutuje architekturę w Slack"@Cursor przeanalizuj proponowany podział mikrousług w tym wątku"
// Cursor czyta cały wątek Slack, tworzy:// - Diagram architektury// - Analizę granic serwisów// - Odpowiedzi na obawy zespołu// - Alternatywne podejścia
Korzyści:
---description: Standardy architektury zespołualwaysApply: true---- Wszystkie serwisy muszą następować architekturę heksagonalną- Użyj event sourcing dla serwisów krytycznych audytowo- Wymagane wersjonowanie API od v1.0- Każdy serwis posiada swoje dane (brak współdzielonych BD)- Dokumentuj ADR dla głównych decyzji
Zastosuj w zespole:
// Konfiguracja BugBot dla architektury# .cursor/BUGBOT.md## Punkty przeglądu architektury- Sprawdź naruszenia granic serwisów- Weryfikuj brak synchronicznych zależności kołowych- Zapewnij odpowiednie wzorce obsługi błędów- Waliduj założenia skalowania- Przejrzyj granice bezpieczeństwa
Automatyczne sprawdzenia:
Przy implementacji złożonych architektur w zespołach:
Podział według domeny
# Zespół A: Domena użytkownikacursor --user-data-dir ~/.cursor-user-service services/user# "Implementuj serwis użytkownika zgodnie z dokumentem architektury"
# Zespół B: Domena zamówieńcursor --user-data-dir ~/.cursor-order-service services/order# "Implementuj serwis zamówień z event sourcing"
# Zespół C: API Gatewaycursor --user-data-dir ~/.cursor-gateway gateway/# "Implementuj bramę GraphQL agregującą serwisy"
Dzielenie kontekstu przez MCP
// Wspólny .cursor/mcp.json{ "mcpServers": { "confluence": { "command": "confluence-mcp", "args": ["--space", "ARCH"], "env": { "CONFLUENCE_TOKEN": "$CONFLUENCE_TOKEN" } }, "figma": { "command": "figma-mcp", "args": ["--file", "architecture-diagrams"] } }}
Synchronizacja przez agentów tła
// Każdy zespół uruchamia agenta tła"Monitoruj inne serwisy pod kątem zmian interfejsów, aktualizuj nasze kontrakty serwisów odpowiednio"
// Agent obserwuje git, aktualizuje interfejsy// Wysyła na Slack gdy wykryje konflikty
Proces wspólnych ADR
1. **Proponuj** (Każdy członek zespołu) "Szkic ADR dla przejścia na architekturę event-driven"
2. **Dyskutuj** (Zespół przegląda w PR) - AI podsumowuje implikacje - BugBot sprawdza konflikty - Zespół komentuje/głosuje
3. **Implementuj** (Wielu programistów) - Każdy bierze określone serwisy - AI zapewnia zgodność z ADR - Automatyczna weryfikacja
4. **Dokumentuj** (Z pomocą AI) "Zaktualizuj dokumentację architektury na podstawie ADR-007"
Zacznij prosto
Rozpocznij od prostej architektury i ewoluuj na podstawie potrzeb
Projektuj na awarie
Załóż że komponenty będą się psuć i projektuj odpowiednio
Monitoruj wszystko
Kompleksowe monitorowanie od pierwszego dnia
Dokumentuj decyzje
Rejestruj decyzje architektoniczne i uzasadnienia
Integracja DevOps
Implementuj CI/CD dla swojej architektury
Testowanie wydajności
Waliduj architekturę pod obciążeniem
Przegląd bezpieczeństwa
Przeprowadź przegląd architektury bezpieczeństwa