微服务架构设计与实践# Compose 中实现凸角、凹角、切角、尖角

概述Jetpack Compose 通过诸如 RoundedCornerShape 或 CutCornerShape 的类,可以在各种组件上应用圆角或切角。## 切角实现你可能不知道,Compose 还支持更多样化的角度处理方式。本文将详细介绍如何在 Jetpack Compose 中实现各种角度效果。### 基础切角kotlin// 基础切角实现Box( modifier = Modifier .size(100.dp) .clip(CutCornerShape(16.dp)) .background(Color.Blue))### 圆角实现kotlin// 圆角实现Box( modifier = Modifier .size(100.dp) .clip(RoundedCornerShape(16.dp)) .background(Color.Green))## 自定义角度形状### 凸角实现凸角可以通过自定义 Shape 来实现:kotlinclass ConvexCornerShape(private val cornerRadius: Dp) : Shape { override fun createOutline( size: Size, layoutDirection: LayoutDirection, density: Density ): Outline { val radius = with(density) { cornerRadius.toPx() } val path = Path().apply { // 实现凸角路径 moveTo(0f, radius) quadraticBezierTo(0f, 0f, radius, 0f) lineTo(size.width - radius, 0f) quadraticBezierTo(size.width, 0f, size.width, radius) lineTo(size.width, size.height - radius) quadraticBezierTo(size.width, size.height, size.width - radius, size.height) lineTo(radius, size.height) quadraticBezierTo(0f, size.height, 0f, size.height - radius) close() } return Outline.Generic(path) }}### 凹角实现凹角的实现需要反向的曲线:kotlinclass ConcaveCornerShape(private val cornerRadius: Dp) : Shape { override fun createOutline( size: Size, layoutDirection: LayoutDirection, density: Density ): Outline { val radius = with(density) { cornerRadius.toPx() } val path = Path().apply { // 实现凹角路径 moveTo(radius, 0f) quadraticBezierTo(0f, 0f, 0f, radius) lineTo(0f, size.height - radius) quadraticBezierTo(0f, size.height, radius, size.height) lineTo(size.width - radius, size.height) quadraticBezierTo(size.width, size.height, size.width, size.height - radius) lineTo(size.width, radius) quadraticBezierTo(size.width, 0f, size.width - radius, 0f) close() } return Outline.Generic(path) }}### 尖角实现尖角可以通过三角形路径实现:kotlinclass PointedCornerShape(private val cornerSize: Dp) : Shape { override fun createOutline( size: Size, layoutDirection: LayoutDirection, density: Density ): Outline { val cornerPx = with(density) { cornerSize.toPx() } val path = Path().apply { moveTo(cornerPx, 0f) lineTo(0f, cornerPx) lineTo(0f, size.height - cornerPx) lineTo(cornerPx, size.height) lineTo(size.width - cornerPx, size.height) lineTo(size.width, size.height - cornerPx) lineTo(size.width, cornerPx) lineTo(size.width - cornerPx, 0f) close() } return Outline.Generic(path) }}## 使用示例### 组合使用不同角度kotlin@Composablefun CornerShapeDemo() { Column( modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { // 凸角 Box( modifier = Modifier .size(100.dp) .clip(ConvexCornerShape(16.dp)) .background(Color.Red) ) // 凹角 Box( modifier = Modifier .size(100.dp) .clip(ConcaveCornerShape(16.dp)) .background(Color.Blue) ) // 尖角 Box( modifier = Modifier .size(100.dp) .clip(PointedCornerShape(16.dp)) .background(Color.Green) ) }}## 性能优化### 缓存 Shape 对象kotlinobject CornerShapes { val convex16 = ConvexCornerShape(16.dp) val concave16 = ConcaveCornerShape(16.dp) val pointed16 = PointedCornerShape(16.dp)}### 使用 remember 优化kotlin@Composablefun OptimizedCornerShape() { val customShape = remember { ConvexCornerShape(16.dp) } Box( modifier = Modifier .size(100.dp) .clip(customShape) .background(Color.Cyan) )}## 总结Jetpack Compose 提供了强大的形状定制能力,通过自定义 Shape 类,我们可以实现各种复杂的角度效果:1. 凸角:使用二次贝塞尔曲线创建向外凸出的角2. 凹角:使用反向曲线创建向内凹陷的角3. 切角:使用直线切割创建平直的角4. 尖角:使用三角形路径创建锐利的角这些技术可以帮助开发者创建更加丰富和独特的 UI 设计。## 扩展阅读- Jetpack Compose 官方文档- Path 和 Shape 的高级用法- 自定义绘制和动画效果## 引言微服务架构作为现代软件架构的重要模式,通过将大型单体应用拆分为多个小型、独立的服务,实现了更好的可扩展性、可维护性和技术多样性。本文将深入探讨微服务架构的设计原则、实施策略和最佳实践,帮助开发者构建高效、可靠的微服务系统。## 微服务架构概述### 核心概念微服务架构是一种将单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,并使用轻量级机制(通常是 HTTP API)进行通信。#### 微服务的特征mermaidgraph TB A[微服务特征] --> B[业务能力导向] A --> C[去中心化治理] A --> D[故障隔离] A --> E[自动化部署] A --> F[技术多样性] A --> G[数据去中心化]#### 与单体架构的对比javascript// 单体架构示例class MonolithicECommerceApp { constructor() { this.userService = new UserService(); this.productService = new ProductService(); this.orderService = new OrderService(); this.paymentService = new PaymentService(); } async createOrder(userId, productId, quantity) { // 所有逻辑在一个应用中 const user = await this.userService.getUser(userId); const product = await this.productService.getProduct(productId); const order = await this.orderService.createOrder(user, product, quantity); const payment = await this.paymentService.processPayment(order); return { order, payment }; }}// 微服务架构示例class MicroserviceOrchestrator { constructor() { this.userServiceClient = new UserServiceClient('http://user-service'); this.productServiceClient = new ProductServiceClient('http://product-service'); this.orderServiceClient = new OrderServiceClient('http://order-service'); this.paymentServiceClient = new PaymentServiceClient('http://payment-service'); } async createOrder(userId, productId, quantity) { try { // 通过 API 调用各个微服务 const user = await this.userServiceClient.getUser(userId); const product = await this.productServiceClient.getProduct(productId); const order = await this.orderServiceClient.createOrder({ userId: user.id, productId: product.id, quantity }); const payment = await this.paymentServiceClient.processPayment({ orderId: order.id, amount: order.totalAmount }); return { order, payment }; } catch (error) { // 处理分布式系统中的错误 await this.handleDistributedError(error); throw error; } }}## 微服务拆分策略### 领域驱动设计 (DDD)javascript// 用户域 (User Domain)class UserAggregate { constructor(id, email, profile) { this.id = id; this.email = email; this.profile = profile; this.events = []; } updateProfile(newProfile) { this.profile = { ...this.profile, ...newProfile }; this.addEvent(new UserProfileUpdatedEvent(this.id, newProfile)); } addEvent(event) { this.events.push(event); } getUncommittedEvents() { return [...this.events]; } clearEvents() { this.events = []; }}// 订单域 (Order Domain)class OrderAggregate { constructor(id, userId, items) { this.id = id; this.userId = userId; this.items = items; this.status = 'PENDING'; this.events = []; } addItem(productId, quantity, price) { const item = new OrderItem(productId, quantity, price); this.items.push(item); this.addEvent(new OrderItemAddedEvent(this.id, item)); } confirm() { if (this.status !== 'PENDING') { throw new Error('Order cannot be confirmed'); } this.status = 'CONFIRMED'; this.addEvent(new OrderConfirmedEvent(this.id, this.userId)); }}### 按业务能力拆分yaml# 微服务拆分示例services: # 用户管理服务 user-service: responsibilities: - 用户注册和认证 - 用户资料管理 - 权限管理 database: user_db # 产品目录服务 product-service: responsibilities: - 产品信息管理 - 库存管理 - 价格管理 database: product_db # 订单服务 order-service: responsibilities: - 订单创建和管理 - 订单状态跟踪 - 订单历史 database: order_db # 支付服务 payment-service: responsibilities: - 支付处理 - 退款管理 - 支付历史 database: payment_db # 通知服务 notification-service: responsibilities: - 邮件通知 - 短信通知 - 推送通知 database: notification_db### 数据一致性策略javascript// Saga 模式实现class OrderSaga { constructor(eventBus, services) { this.eventBus = eventBus; this.userService = services.userService; this.productService = services.productService; this.orderService = services.orderService; this.paymentService = services.paymentService; this.setupEventHandlers(); } setupEventHandlers() { this.eventBus.on('OrderCreationRequested', this.handleOrderCreation.bind(this)); this.eventBus.on('PaymentProcessed', this.handlePaymentProcessed.bind(this)); this.eventBus.on('PaymentFailed', this.handlePaymentFailed.bind(this)); } async handleOrderCreation(event) { const { userId, productId, quantity } = event.data; try { // 步骤 1: 验证用户 const user = await this.userService.validateUser(userId); // 步骤 2: 检查库存 const available = await this.productService.checkInventory(productId, quantity); if (!available) { throw new Error('Insufficient inventory'); } // 步骤 3: 预留库存 await this.productService.reserveInventory(productId, quantity); // 步骤 4: 创建订单 const order = await this.orderService.createOrder({ userId, productId, quantity, status: 'PENDING' }); // 步骤 5: 处理支付 await this.paymentService.processPayment({ orderId: order.id, amount: order.totalAmount, userId }); } catch (error) { // 补偿操作 await this.compensateOrderCreation(event.data, error); } } async compensateOrderCreation(orderData, error) { const { productId, quantity } = orderData; // 释放预留的库存 await this.productService.releaseReservedInventory(productId, quantity); // 取消订单 if (orderData.orderId) { await this.orderService.cancelOrder(orderData.orderId); } // 发布失败事件 this.eventBus.emit('OrderCreationFailed', { orderData, error: error.message }); }}## 服务间通信### 同步通信 - REST APIjavascript// API Gateway 实现class APIGateway { constructor() { this.routes = new Map(); this.middleware = []; this.setupRoutes(); } setupRoutes() { // 用户服务路由 this.routes.set('/api/users', { service: 'user-service', baseUrl: process.env.USER_SERVICE_URL }); // 产品服务路由 this.routes.set('/api/products', { service: 'product-service', baseUrl: process.env.PRODUCT_SERVICE_URL }); // 订单服务路由 this.routes.set('/api/orders', { service: 'order-service', baseUrl: process.env.ORDER_SERVICE_URL }); } use(middleware) { this.middleware.push(middleware); } async handleRequest(req, res) { try { // 执行中间件 for (const middleware of this.middleware) { await middleware(req, res); } // 路由匹配 const route = this.matchRoute(req.path); if (!route) { return res.status(404).json({ error: 'Route not found' }); } // 服务发现和负载均衡 const serviceInstance = await this.discoverService(route.service); // 请求转发 const response = await this.forwardRequest(req, serviceInstance); // 返回响应 res.status(response.status).json(response.data); } catch (error) { this.handleError(error, res); } } matchRoute(path) { for (const [pattern, route] of this.routes) { if (path.startsWith(pattern)) { return route; } } return null; } async discoverService(serviceName) { // 从服务注册中心获取服务实例 const instances = await this.serviceRegistry.getInstances(serviceName); // 负载均衡选择实例 return this.loadBalancer.selectInstance(instances); } async forwardRequest(req, serviceInstance) { const targetUrl = `${serviceInstance.url}${req.path}`; return await fetch(targetUrl, { method: req.method, headers: { ...req.headers, 'X-Request-ID': req.headers['x-request-id'] || this.generateRequestId() }, body: req.method !== 'GET' ? JSON.stringify(req.body) : undefined }); }}// 服务客户端实现class ServiceClient { constructor(serviceName, baseUrl) { this.serviceName = serviceName; this.baseUrl = baseUrl; this.circuitBreaker = new CircuitBreaker(); this.retryPolicy = new RetryPolicy(); } async get(path, options = {}) { return this.request('GET', path, null, options); } async post(path, data, options = {}) { return this.request('POST', path, data, options); } async request(method, path, data, options) { const requestConfig = { method, url: `${this.baseUrl}${path}`, headers: { 'Content-Type': 'application/json', 'X-Service-Name': this.serviceName, ...options.headers }, timeout: options.timeout || 5000 }; if (data) { requestConfig.data = JSON.stringify(data); } // 熔断器保护 return this.circuitBreaker.execute(async () => { // 重试机制 return this.retryPolicy.execute(async () => { const response = await fetch(requestConfig.url, requestConfig); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return response.json(); }); }); }}### 异步通信 - 消息队列javascript// 事件驱动架构实现class EventBus { constructor(messageQueue) { this.messageQueue = messageQueue; this.handlers = new Map(); this.deadLetterQueue = new DeadLetterQueue(); } async publish(eventType, eventData, options = {}) { const event = { id: this.generateEventId(), type: eventType, data: eventData, timestamp: new Date().toISOString(), source: options.source || 'unknown', version: options.version || '1.0' }; try { await this.messageQueue.publish(eventType, event, { persistent: true, priority: options.priority || 0, ttl: options.ttl || 3600000 // 1 hour }); console.log(`Event published: ${eventType}`, event.id); } catch (error) { console.error(`Failed to publish event: ${eventType}`, error); throw error; } } async subscribe(eventType, handler, options = {}) { if (!this.handlers.has(eventType)) { this.handlers.set(eventType, []); } this.handlers.get(eventType).push({ handler, options }); // 设置消息队列订阅 await this.messageQueue.subscribe(eventType, async (message) => { await this.handleMessage(eventType, message); }, { autoAck: false, prefetch: options.prefetch || 1 }); } async handleMessage(eventType, message) { const handlers = this.handlers.get(eventType) || []; for (const { handler, options } of handlers) { try { await this.executeHandler(handler, message, options); await this.messageQueue.ack(message); } catch (error) { await this.handleError(eventType, message, error, options); } } } async executeHandler(handler, message, options) { const timeout = options.timeout || 30000; return Promise.race([ handler(message.content), new Promise((_, reject) => { setTimeout(() => reject(new Error('Handler timeout')), timeout); }) ]); } async handleError(eventType, message, error, options) { const retryCount = message.properties.headers['x-retry-count'] || 0; const maxRetries = options.maxRetries || 3; if (retryCount < maxRetries) { // 重试 await this.retryMessage(eventType, message, retryCount + 1); } else { // 发送到死信队列 await this.deadLetterQueue.send(eventType, message, error); await this.messageQueue.ack(message); } } async retryMessage(eventType, message, retryCount) { const delay = Math.pow(2, retryCount) * 1000; // 指数退避 setTimeout(async () => { message.properties.headers['x-retry-count'] = retryCount; await this.messageQueue.publish(eventType, message.content, { headers: message.properties.headers }); await this.messageQueue.ack(message); }, delay); }}// 具体服务中的事件处理class OrderService { constructor(eventBus, orderRepository) { this.eventBus = eventBus; this.orderRepository = orderRepository; this.setupEventHandlers(); } setupEventHandlers() { // 监听用户创建事件 this.eventBus.subscribe('UserCreated', this.handleUserCreated.bind(this)); // 监听支付完成事件 this.eventBus.subscribe('PaymentCompleted', this.handlePaymentCompleted.bind(this)); // 监听库存更新事件 this.eventBus.subscribe('InventoryUpdated', this.handleInventoryUpdated.bind(this)); } async createOrder(orderData) { const order = await this.orderRepository.create(orderData); // 发布订单创建事件 await this.eventBus.publish('OrderCreated', { orderId: order.id, userId: order.userId, items: order.items, totalAmount: order.totalAmount }); return order; } async handlePaymentCompleted(event) { const { orderId, paymentId, amount } = event.data; const order = await this.orderRepository.findById(orderId); if (order) { order.status = 'PAID'; order.paymentId = paymentId; await this.orderRepository.update(order); // 发布订单支付完成事件 await this.eventBus.publish('OrderPaid', { orderId: order.id, userId: order.userId, paymentId }); } }}## 服务发现与注册### 服务注册中心实现javascript// 服务注册中心class ServiceRegistry { constructor() { this.services = new Map(); this.healthCheckInterval = 30000; // 30秒 this.startHealthCheck(); } async register(serviceInfo) { const { name, id, address, port, health, metadata } = serviceInfo; const service = { id: id || this.generateServiceId(name), name, address, port, health: health || '/health', metadata: metadata || {}, registeredAt: new Date(), lastHeartbeat: new Date(), status: 'UP' }; if (!this.services.has(name)) { this.services.set(name, new Map()); } this.services.get(name).set(service.id, service); console.log(`Service registered: ${name}:${service.id}`); return service.id; } async deregister(serviceName, serviceId) { if (this.services.has(serviceName)) { const serviceInstances = this.services.get(serviceName); serviceInstances.delete(serviceId); if (serviceInstances.size === 0) { this.services.delete(serviceName); } } console.log(`Service deregistered: ${serviceName}:${serviceId}`); } async getInstances(serviceName) { const serviceInstances = this.services.get(serviceName); if (!serviceInstances) { return []; } // 只返回健康的服务实例 return Array.from(serviceInstances.values()) .filter(service => service.status === 'UP'); } async heartbeat(serviceName, serviceId) { const serviceInstances = this.services.get(serviceName); if (serviceInstances && serviceInstances.has(serviceId)) { const service = serviceInstances.get(serviceId); service.lastHeartbeat = new Date(); service.status = 'UP'; } } startHealthCheck() { setInterval(async () => { for (const [serviceName, instances] of this.services) { for (const [serviceId, service] of instances) { await this.checkServiceHealth(serviceName, serviceId, service); } } }, this.healthCheckInterval); } async checkServiceHealth(serviceName, serviceId, service) { try { const healthUrl = `http://${service.address}:${service.port}${service.health}`; const response = await fetch(healthUrl, { timeout: 5000 }); if (response.ok) { service.status = 'UP'; service.lastHeartbeat = new Date(); } else { service.status = 'DOWN'; } } catch (error) { service.status = 'DOWN'; console.warn(`Health check failed for ${serviceName}:${serviceId}`, error.message); } }}// 服务客户端自动注册class ServiceClient { constructor(serviceInfo, registry) { this.serviceInfo = serviceInfo; this.registry = registry; this.serviceId = null; this.heartbeatInterval = null; } async start() { // 注册服务 this.serviceId = await this.registry.register(this.serviceInfo); // 启动心跳 this.startHeartbeat(); // 优雅关闭处理 process.on('SIGTERM', () => this.shutdown()); process.on('SIGINT', () => this.shutdown()); } startHeartbeat() { this.heartbeatInterval = setInterval(async () => { try { await this.registry.heartbeat(this.serviceInfo.name, this.serviceId); } catch (error) { console.error('Heartbeat failed:', error); } }, 15000); // 15秒心跳 } async shutdown() { console.log('Shutting down service...'); // 停止心跳 if (this.heartbeatInterval) { clearInterval(this.heartbeatInterval); } // 注销服务 if (this.serviceId) { await this.registry.deregister(this.serviceInfo.name, this.serviceId); } process.exit(0); }}### 负载均衡策略javascript// 负载均衡器class LoadBalancer { constructor(strategy = 'round-robin') { this.strategy = strategy; this.roundRobinCounters = new Map(); } selectInstance(instances, strategy = this.strategy) { if (!instances || instances.length === 0) { throw new Error('No available instances'); } switch (strategy) { case 'round-robin': return this.roundRobin(instances); case 'random': return this.random(instances); case 'weighted': return this.weighted(instances); case 'least-connections': return this.leastConnections(instances); default: return this.roundRobin(instances); } } roundRobin(instances) { const key = instances.map(i => i.id).join(','); const counter = this.roundRobinCounters.get(key) || 0; const selectedIndex = counter % instances.length; this.roundRobinCounters.set(key, counter + 1); return instances[selectedIndex]; } random(instances) { const randomIndex = Math.floor(Math.random() * instances.length); return instances[randomIndex]; } weighted(instances) { const totalWeight = instances.reduce((sum, instance) => { return sum + (instance.metadata.weight || 1); }, 0); let randomWeight = Math.random() * totalWeight; for (const instance of instances) { const weight = instance.metadata.weight || 1; randomWeight -= weight; if (randomWeight <= 0) { return instance; } } return instances[0]; } leastConnections(instances) { return instances.reduce((least, current) => { const leastConnections = least.metadata.connections || 0; const currentConnections = current.metadata.connections || 0; return currentConnections < leastConnections ? current : least; }); }}## 配置管理### 配置中心实现javascript// 配置中心class ConfigurationCenter { constructor() { this.configurations = new Map(); this.watchers = new Map(); this.encryptionKey = process.env.CONFIG_ENCRYPTION_KEY; } async setConfig(key, value, options = {}) { const config = { key, value: options.encrypted ? this.encrypt(value) : value, encrypted: options.encrypted || false, version: this.generateVersion(), updatedAt: new Date(), metadata: options.metadata || {} }; this.configurations.set(key, config); // 通知观察者 await this.notifyWatchers(key, config); console.log(`Configuration updated: ${key}`); } async getConfig(key, defaultValue = null) { const config = this.configurations.get(key); if (!config) { return defaultValue; } return config.encrypted ? this.decrypt(config.value) : config.value; } async getConfigWithMetadata(key) { return this.configurations.get(key) || null; } async watchConfig(key, callback) { if (!this.watchers.has(key)) { this.watchers.set(key, []); } this.watchers.get(key).push(callback); // 立即发送当前配置 const currentConfig = this.configurations.get(key); if (currentConfig) { await callback(currentConfig); } } async notifyWatchers(key, config) { const watchers = this.watchers.get(key) || []; for (const watcher of watchers) { try { await watcher(config); } catch (error) { console.error(`Watcher error for key ${key}:`, error); } } } encrypt(value) { // 实现加密逻辑 const crypto = require('crypto'); const cipher = crypto.createCipher('aes-256-cbc', this.encryptionKey); let encrypted = cipher.update(JSON.stringify(value), 'utf8', 'hex'); encrypted += cipher.final('hex'); return encrypted; } decrypt(encryptedValue) { // 实现解密逻辑 const crypto = require('crypto'); const decipher = crypto.createDecipher('aes-256-cbc', this.encryptionKey); let decrypted = decipher.update(encryptedValue, 'hex', 'utf8'); decrypted += decipher.final('utf8'); return JSON.parse(decrypted); } generateVersion() { return Date.now().toString(); }}// 配置客户端class ConfigClient { constructor(configCenter, serviceName) { this.configCenter = configCenter; this.serviceName = serviceName; this.localCache = new Map(); this.refreshInterval = 60000; // 1分钟 this.startPeriodicRefresh(); } async getConfig(key, defaultValue = null) { // 先从本地缓存获取 if (this.localCache.has(key)) { const cached = this.localCache.get(key); if (Date.now() - cached.timestamp < 30000) { // 30秒缓存 return cached.value; } } // 从配置中心获取 try { const value = await this.configCenter.getConfig( `${this.serviceName}.${key}`, defaultValue ); // 更新本地缓存 this.localCache.set(key, { value, timestamp: Date.now() }); return value; } catch (error) { console.error(`Failed to get config ${key}:`, error); // 返回缓存值或默认值 const cached = this.localCache.get(key); return cached ? cached.value : defaultValue; } } async watchConfig(key, callback) { const fullKey = `${this.serviceName}.${key}`; await this.configCenter.watchConfig(fullKey, async (config) => { // 更新本地缓存 this.localCache.set(key, { value: config.encrypted ? await this.configCenter.decrypt(config.value) : config.value, timestamp: Date.now() }); // 调用回调 await callback(config); }); } startPeriodicRefresh() { setInterval(async () => { try { await this.refreshAllConfigs(); } catch (error) { console.error('Config refresh failed:', error); } }, this.refreshInterval); } async refreshAllConfigs() { const keys = Array.from(this.localCache.keys()); for (const key of keys) { try { await this.getConfig(key); } catch (error) { console.warn(`Failed to refresh config ${key}:`, error); } } }}## 监控和可观测性### 分布式链路追踪javascript// 分布式追踪实现class DistributedTracing { constructor() { this.traces = new Map(); this.spans = new Map(); } startTrace(operationName, parentSpanId = null) { const traceId = parentSpanId ? this.getTraceId(parentSpanId) : this.generateTraceId(); const span = { spanId: this.generateSpanId(), traceId, parentSpanId, operationName, startTime: Date.now(), endTime: null, tags: new Map(), logs: [], status: 'ACTIVE' }; this.spans.set(span.spanId, span); if (!this.traces.has(traceId)) { this.traces.set(traceId, { traceId, spans: [], startTime: span.startTime }); } this.traces.get(traceId).spans.push(span.spanId); return span.spanId; } finishSpan(spanId, status = 'SUCCESS') { const span = this.spans.get(spanId); if (span) { span.endTime = Date.now(); span.status = status; span.duration = span.endTime - span.startTime; } } addTag(spanId, key, value) { const span = this.spans.get(spanId); if (span) { span.tags.set(key, value); } } addLog(spanId, message, level = 'INFO') { const span = this.spans.get(spanId); if (span) { span.logs.push({ timestamp: Date.now(), level, message }); } } getTrace(traceId) { const trace = this.traces.get(traceId); if (!trace) return null; return { ...trace, spans: trace.spans.map(spanId => this.spans.get(spanId)) }; } generateTraceId() { return Math.random().toString(36).substr(2, 16); } generateSpanId() { return Math.random().toString(36).substr(2, 8); } getTraceId(spanId) { const span = this.spans.get(spanId); return span ? span.traceId : null; }}// 追踪中间件class TracingMiddleware { constructor(tracer, serviceName) { this.tracer = tracer; this.serviceName = serviceName; } middleware() { return async (req, res, next) => { // 从请求头获取父 span 信息 const parentSpanId = req.headers['x-parent-span-id']; const traceId = req.headers['x-trace-id']; // 创建新的 span const spanId = this.tracer.startTrace( `${req.method} ${req.path}`, parentSpanId ); // 添加标签 this.tracer.addTag(spanId, 'service.name', this.serviceName); this.tracer.addTag(spanId, 'http.method', req.method); this.tracer.addTag(spanId, 'http.url', req.url); this.tracer.addTag(spanId, 'user.id', req.user?.id); // 将 span 信息添加到请求对象 req.spanId = spanId; req.traceId = traceId || this.tracer.getTraceId(spanId); // 设置响应头 res.setHeader('X-Trace-Id', req.traceId); res.setHeader('X-Span-Id', spanId); // 记录请求开始 this.tracer.addLog(spanId, `Request started: ${req.method} ${req.path}`); // 监听响应结束 res.on('finish', () => { this.tracer.addTag(spanId, 'http.status_code', res.statusCode); const status = res.statusCode >= 400 ? 'ERROR' : 'SUCCESS'; this.tracer.finishSpan(spanId, status); this.tracer.addLog(spanId, `Request finished: ${res.statusCode}`, status === 'ERROR' ? 'ERROR' : 'INFO' ); }); next(); }; }}// 服务间调用追踪class TracedHttpClient { constructor(tracer, serviceName) { this.tracer = tracer; this.serviceName = serviceName; } async request(options, parentSpanId) { const spanId = this.tracer.startTrace( `HTTP ${options.method} ${options.url}`, parentSpanId ); try { // 添加追踪头 const headers = { ...options.headers, 'X-Parent-Span-Id': spanId, 'X-Trace-Id': this.tracer.getTraceId(spanId), 'X-Service-Name': this.serviceName }; this.tracer.addTag(spanId, 'http.method', options.method); this.tracer.addTag(spanId, 'http.url', options.url); this.tracer.addLog(spanId, `Making HTTP request to ${options.url}`); const response = await fetch(options.url, { ...options, headers }); this.tracer.addTag(spanId, 'http.status_code', response.status); const status = response.ok ? 'SUCCESS' : 'ERROR'; this.tracer.finishSpan(spanId, status); return response; } catch (error) { this.tracer.addTag(spanId, 'error', true); this.tracer.addLog(spanId, `HTTP request failed: ${error.message}`, 'ERROR'); this.tracer.finishSpan(spanId, 'ERROR'); throw error; } }}### 指标收集和监控javascript// 指标收集器class MetricsCollector { constructor() { this.counters = new Map(); this.gauges = new Map(); this.histograms = new Map(); this.timers = new Map(); } // 计数器 incrementCounter(name, labels = {}, value = 1) { const key = this.getMetricKey(name, labels); const current = this.counters.get(key) || 0; this.counters.set(key, current + value); } // 仪表盘 setGauge(name, labels = {}, value) { const key = this.getMetricKey(name, labels); this.gauges.set(key, { value, timestamp: Date.now() }); } // 直方图 recordHistogram(name, labels = {}, value) { const key = this.getMetricKey(name, labels); if (!this.histograms.has(key)) { this.histograms.set(key, { count: 0, sum: 0, buckets: new Map(), values: [] }); } const histogram = this.histograms.get(key); histogram.count++; histogram.sum += value; histogram.values.push(value); // 保持最近1000个值 if (histogram.values.length > 1000) { histogram.values.shift(); } // 更新桶计数 this.updateHistogramBuckets(histogram, value); } // 计时器 startTimer(name, labels = {}) { const key = this.getMetricKey(name, labels); const timerId = Math.random().toString(36); this.timers.set(timerId, { key, startTime: Date.now() }); return timerId; } endTimer(timerId) { const timer = this.timers.get(timerId); if (timer) { const duration = Date.now() - timer.startTime; this.recordHistogram(timer.key.split('|')[0], this.parseLabels(timer.key), duration); this.timers.delete(timerId); return duration; } return null; } // 获取所有指标 getMetrics() { return { counters: Object.fromEntries(this.counters), gauges: Object.fromEntries(this.gauges), histograms: this.getHistogramMetrics(), timestamp: Date.now() }; } getHistogramMetrics() { const result = {}; for (const [key, histogram] of this.histograms) { const values = histogram.values.sort((a, b) => a - b); result[key] = { count: histogram.count, sum: histogram.sum, avg: histogram.sum / histogram.count, min: Math.min(...values), max: Math.max(...values), p50: this.percentile(values, 0.5), p90: this.percentile(values, 0.9), p95: this.percentile(values, 0.95), p99: this.percentile(values, 0.99) }; } return result; } getMetricKey(name, labels) { const labelStr = Object.entries(labels) .sort(([a], [b]) => a.localeCompare(b)) .map(([k, v]) => `${k}=${v}`) .join(','); return labelStr ? `${name}|${labelStr}` : name; } parseLabels(key) { const parts = key.split('|'); if (parts.length < 2) return {}; const labels = {}; parts[1].split(',').forEach(pair => { const [k, v] = pair.split('='); labels[k] = v; }); return labels; } percentile(sortedValues, p) { if (sortedValues.length === 0) return 0; const index = Math.ceil(sortedValues.length * p) - 1; return sortedValues[Math.max(0, index)]; } updateHistogramBuckets(histogram, value) { const buckets = [1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000]; for (const bucket of buckets) { if (value <= bucket) { const current = histogram.buckets.get(bucket) || 0; histogram.buckets.set(bucket, current + 1); } } }}// 应用指标中间件class ApplicationMetrics { constructor(metricsCollector, serviceName) { this.metrics = metricsCollector; this.serviceName = serviceName; this.startSystemMetrics(); } middleware() { return (req, res, next) => { const startTime = Date.now(); // 请求计数 this.metrics.incrementCounter('http_requests_total', { service: this.serviceName, method: req.method, endpoint: req.route?.path || req.path }); // 并发请求数 this.metrics.setGauge('http_requests_active', { service: this.serviceName }, this.getActiveRequests() + 1); res.on('finish', () => { const duration = Date.now() - startTime; // 请求持续时间 this.metrics.recordHistogram('http_request_duration_ms', { service: this.serviceName, method: req.method, status: res.statusCode.toString(), endpoint: req.route?.path || req.path }, duration); // 响应状态码计数 this.metrics.incrementCounter('http_responses_total', { service: this.serviceName, status: res.statusCode.toString() }); // 更新并发请求数 this.metrics.setGauge('http_requests_active', { service: this.serviceName }, this.getActiveRequests() - 1); }); next(); }; } startSystemMetrics() { setInterval(() => { const memUsage = process.memoryUsage(); // 内存使用情况 this.metrics.setGauge('memory_usage_bytes', { service: this.serviceName, type: 'rss' }, memUsage.rss); this.metrics.setGauge('memory_usage_bytes', { service: this.serviceName, type: 'heap_used' }, memUsage.heapUsed); this.metrics.setGauge('memory_usage_bytes', { service: this.serviceName, type: 'heap_total' }, memUsage.heapTotal); // CPU 使用情况 const cpuUsage = process.cpuUsage(); this.metrics.setGauge('cpu_usage_microseconds', { service: this.serviceName, type: 'user' }, cpuUsage.user); this.metrics.setGauge('cpu_usage_microseconds', { service: this.serviceName, type: 'system' }, cpuUsage.system); }, 10000); // 每10秒收集一次 } getActiveRequests() { // 实现获取当前活跃请求数的逻辑 return 0; // 简化实现 }}## 安全性考虑### 服务间认证授权javascript// JWT 令牌管理class JWTManager { constructor(secretKey, options = {}) { this.secretKey = secretKey; this.algorithm = options.algorithm || 'HS256'; this.expiresIn = options.expiresIn || '1h'; this.issuer = options.issuer || 'microservice-system'; } generateToken(payload, options = {}) { const jwt = require('jsonwebtoken'); const tokenPayload = { ...payload, iss: this.issuer, iat: Math.floor(Date.now() / 1000) }; return jwt.sign(tokenPayload, this.secretKey, { algorithm: this.algorithm, expiresIn: options.expiresIn || this.expiresIn, audience: options.audience }); } verifyToken(token, options = {}) { const jwt = require('jsonwebtoken'); try { return jwt.verify(token, this.secretKey, { algorithms: [this.algorithm], issuer: this.issuer, audience: options.audience }); } catch (error) { throw new Error(`Token verification failed: ${error.message}`); } } refreshToken(token) { try { const decoded = this.verifyToken(token); // 移除时间相关的声明 delete decoded.iat; delete decoded.exp; delete decoded.nbf; return this.generateToken(decoded); } catch (error) { throw new Error(`Token refresh failed: ${error.message}`); } }}// 服务间认证中间件class ServiceAuthMiddleware { constructor(jwtManager, serviceName) { this.jwtManager = jwtManager; this.serviceName = serviceName; this.trustedServices = new Set(); } addTrustedService(serviceName) { this.trustedServices.add(serviceName); } middleware() { return async (req, res, next) => { try { const token = this.extractToken(req); if (!token) { return res.status(401).json({ error: 'No token provided' }); } const decoded = this.jwtManager.verifyToken(token, { audience: this.serviceName }); // 验证调用方服务 if (!this.trustedServices.has(decoded.service)) { return res.status(403).json({ error: 'Service not authorized' }); } // 将认证信息添加到请求对象 req.auth = { service: decoded.service, userId: decoded.userId, permissions: decoded.permissions || [], roles: decoded.roles || [] }; next(); } catch (error) { res.status(401).json({ error: 'Authentication failed', message: error.message }); } }; } extractToken(req) { const authHeader = req.headers.authorization; if (authHeader && authHeader.startsWith('Bearer ')) { return authHeader.substring(7); } return req.headers['x-service-token']; }}// API 网关安全class APIGatewaySecurity { constructor() { this.rateLimiters = new Map(); this.blacklistedIPs = new Set(); this.apiKeys = new Map(); } // 速率限制 rateLimitMiddleware(options = {}) { const windowMs = options.windowMs || 15 * 60 * 1000; // 15分钟 const maxRequests = options.maxRequests || 100; return (req, res, next) => { const clientId = this.getClientId(req); const now = Date.now(); if (!this.rateLimiters.has(clientId)) { this.rateLimiters.set(clientId, { requests: [], windowStart: now }); } const limiter = this.rateLimiters.get(clientId); // 清理过期的请求记录 limiter.requests = limiter.requests.filter( timestamp => now - timestamp < windowMs ); if (limiter.requests.length >= maxRequests) { return res.status(429).json({ error: 'Too many requests', retryAfter: Math.ceil(windowMs / 1000) }); } limiter.requests.push(now); next(); }; } // IP 黑名单 ipBlacklistMiddleware() { return (req, res, next) => { const clientIP = this.getClientIP(req); if (this.blacklistedIPs.has(clientIP)) { return res.status(403).json({ error: 'IP address is blacklisted' }); } next(); }; } // API Key 验证 apiKeyMiddleware() { return (req, res, next) => { const apiKey = req.headers['x-api-key']; if (!apiKey) { return res.status(401).json({ error: 'API key required' }); } const keyInfo = this.apiKeys.get(apiKey); if (!keyInfo || !keyInfo.active) { return res.status(401).json({ error: 'Invalid API key' }); } // 检查 API Key 权限 if (keyInfo.permissions && keyInfo.permissions.length > 0) { req.apiKeyPermissions = keyInfo.permissions; } next(); }; } getClientId(req) { return req.headers['x-api-key'] || req.auth?.userId || this.getClientIP(req); } getClientIP(req) { return req.headers['x-forwarded-for'] || req.headers['x-real-ip'] || req.connection.remoteAddress; } addAPIKey(key, permissions = [], active = true) { this.apiKeys.set(key, { permissions, active, createdAt: new Date() }); } blacklistIP(ip) { this.blacklistedIPs.add(ip); } removeFromBlacklist(ip) { this.blacklistedIPs.delete(ip); }}## 部署和运维### 容器化部署dockerfile# 微服务 Dockerfile 示例FROM node:18-alpine AS base# 安装 dumb-initRUN apk add --no-cache dumb-init# 创建应用用户RUN addgroup -g 1001 -S nodejsRUN adduser -S microservice -u 1001# 设置工作目录WORKDIR /app# 复制依赖文件COPY package*.json ./# 安装依赖RUN npm ci --only=production && npm cache clean --force# 复制应用代码COPY --chown=microservice:nodejs . .# 切换到非 root 用户USER microservice# 健康检查HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD node healthcheck.js# 暴露端口EXPOSE 3000# 使用 dumb-init 作为 PID 1ENTRYPOINT ["dumb-init", "--"]# 启动应用CMD ["node", "server.js"]``````yaml# docker-compose.ymlversion: '3.8'services: # API 网关 api-gateway: build: ./api-gateway ports: - "80:3000" environment: - NODE_ENV=production - SERVICE_REGISTRY_URL=http://service-registry:8500 depends_on: - service-registry networks: - microservices # 服务注册中心 service-registry: image: consul:1.15 ports: - "8500:8500" networks: - microservices # 用户服务 user-service: build: ./user-service environment: - NODE_ENV=production - DATABASE_URL=postgresql://user:password@user-db:5432/users - SERVICE_REGISTRY_URL=http://service-registry:8500 depends_on: - user-db - service-registry networks: - microservices deploy: replicas: 2 user-db: image: postgres:15-alpine environment: - POSTGRES_DB=users - POSTGRES_USER=user - POSTGRES_PASSWORD=password volumes: - user_data:/var/lib/postgresql/data networks: - microservices # 产品服务 product-service: build: ./product-service environment: - NODE_ENV=production - DATABASE_URL=postgresql://product:password@product-db:5432/products - SERVICE_REGISTRY_URL=http://service-registry:8500 depends_on: - product-db - service-registry networks: - microservices deploy: replicas: 2 product-db: image: postgres:15-alpine environment: - POSTGRES_DB=products - POSTGRES_USER=product - POSTGRES_PASSWORD=password volumes: - product_data:/var/lib/postgresql/data networks: - microservices # 消息队列 rabbitmq: image: rabbitmq:3.11-management-alpine ports: - "15672:15672" environment: - RABBITMQ_DEFAULT_USER=admin - RABBITMQ_DEFAULT_PASS=password volumes: - rabbitmq_data:/var/lib/rabbitmq networks: - microservices # 监控 prometheus: image: prom/prometheus:latest ports: - "9090:9090" volumes: - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus networks: - microservices grafana: image: grafana/grafana:latest ports: - "3001:3000" environment: - GF_SECURITY_ADMIN_PASSWORD=admin volumes: - grafana_data:/var/lib/grafana networks: - microservicesvolumes: user_data: product_data: rabbitmq_data: prometheus_data: grafana_data:networks: microservices: driver: bridge### Kubernetes 部署yaml# user-service-deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata: name: user-service labels: app: user-servicespec: replicas: 3 selector: matchLabels: app: user-service template: metadata: labels: app: user-service spec: containers: - name: user-service image: user-service:latest ports: - containerPort: 3000 env: - name: NODE_ENV value: "production" - name: DATABASE_URL valueFrom: secretKeyRef: name: user-service-secrets key: database-url resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m" livenessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 3000 initialDelaySeconds: 5 periodSeconds: 5---apiVersion: v1kind: Servicemetadata: name: user-servicespec: selector: app: user-service ports: - protocol: TCP port: 80 targetPort: 3000 type: ClusterIP---apiVersion: autoscaling/v2kind: HorizontalPodAutoscalermetadata: name: user-service-hpaspec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: user-service minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 - type: Resource resource: name: memory target: type: Utilization averageUtilization: 80## 总结微服务架构是一个复杂但强大的架构模式,它为现代应用开发带来了诸多优势:### 核心优势1. 独立部署:每个服务可以独立开发、测试和部署2. 技术多样性:不同服务可以使用不同的技术栈3. 故障隔离:单个服务的故障不会影响整个系统4. 可扩展性:可以根据需要独立扩展特定服务5. 团队自治:小团队可以独立负责特定的服务### 挑战与解决方案1. 分布式复杂性:通过服务网格、API 网关等工具简化管理2. 数据一致性:使用 Saga 模式、事件溯源等模式3. 服务发现:使用注册中心和负载均衡4. 监控调试:实施分布式追踪和集中化日志5. 安全性:建立完善的认证授权机制### 最佳实践1. 从单体开始:不要过早拆分,先理解业务边界2. 领域驱动:基于业务能力而非技术层面拆分3. 自动化优先:建立完善的 CI/CD 流水线4. 监控为王:建立全面的监控和告警体系5. 渐进式演进:逐步拆分,避免大爆炸式重构微服务架构不是银弹,需要根据具体的业务场景和团队能力来决定是否采用。但掌握微服务的设计原则和实践方法,将为构建现代化、可扩展的应用系统提供强有力的支撑。大数据

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐