# ð ç³»ç»æ¶æè®Ÿè®¡
# äžãæ žå¿æŠå¿µäžåå
ç³»ç»æ¶æè®Ÿè®¡æ¯æå¯¹ç³»ç»æŽäœç»æåç»ä»¶å ³ç³»çè§åïŒå®å³å®äºç³»ç»ç莚é屿§ã坿©å±æ§ãå¯ç»Žæ€æ§åæ§èœçå ³é®ç¹æ§ãäžäžªè¯å¥œçæ¶æè®Ÿè®¡å¯ä»¥æå¯Œå¢é髿å°åŒåå绎æ€ç³»ç»ã
# 1. ç³»ç»æ¶æè®Ÿè®¡çæ žå¿åå
åå | æè¿° | éèŠæ§ |
---|---|---|
åäžè莣åå | æ¯äžªç»ä»¶ææš¡ååªèŽèŽ£äžäžªæç¡®çåèœ | âââââ |
é«å èäœèŠå | ç»ä»¶å éšçާå¯å ³èïŒç»ä»¶ä¹éŽæŸèŠå | âââââ |
å ³æ³šç¹å犻 | äžåå ³æ³šç¹ç±äžåç»ä»¶èŽèŽ£ | âââââ |
æ¥å£å犻åå | é¿å 客æ·ç«¯äŸèµå ¶äžéèŠçæ¥å£ | ââââ |
äŸèµå眮åå | é«å±æš¡åäŸèµæœè±¡ïŒäžäŸèµå ·äœå®ç° | ââââ |
åŒæŸå°éåå | 对æ©å±åŒæŸïŒå¯¹ä¿®æ¹å°é | ââââ |
坿µè¯æ§ | æ¶æåºæ¯æåå æµè¯ãéææµè¯ç | ââââ |
å¯è§æµæ§ | ç³»ç»åºå ·å€å®åççæ§ãæ¥å¿å远螪èœå | ââââ |
# 2. ç³»ç»æ¶æç莚é屿§
ç³»ç»æ¶æè®Ÿè®¡éèŠå¹³è¡¡åç§èŽšé屿§ïŒä»¥äžæ¯äžäºå ³é®ç莚é屿§ïŒ
- åèœæ§ïŒç³»ç»æäŸçåèœæ¯åŠæ»¡è¶³çšæ·éæ±
- æ§èœïŒç³»ç»çååºæ¶éŽãååéãèµæºå©çšçç
- 坿©å±æ§ïŒç³»ç»åºå¯¹äžå¡å¢é¿åååçèœå
- å¯çšæ§ïŒç³»ç»æ£åžžè¿è¡çæ¶éŽæ¯äŸ
- å¯é æ§ïŒç³»ç»åšè§å®æ¡ä»¶äžå®æè§å®åèœçèœå
- å®å šæ§ïŒä¿æ€ç³»ç»å åæªææè®¿é®åæ»å»çèœå
- å¯ç»Žæ€æ§ïŒä¿®æ¹ç³»ç»çéŸæçšåºŠ
- å¯ç§»æ€æ§ïŒç³»ç»åšäžåç¯å¢éŽè¿ç§»çéŸæçšåºŠ
# äºãåžžè§çç³»ç»æ¶ææš¡åŒ
# 2.1 å屿¶æïŒLayered ArchitectureïŒ
å屿¶ææ¯æåžžè§çç³»ç»æ¶ææš¡åŒïŒå°ç³»ç»å䞺å€äžªå±æ¬¡ïŒæ¯äžå±èŽèŽ£ç¹å®çåèœïŒå±äžå±ä¹éŽéè¿æ¥å£è¿è¡éä¿¡ã
å žåçå屿¶æïŒ
âââââââââââââââââââââââââââââââââââââââââââ
â 衚瀺å±ïŒUIïŒ â
âââââââââââââââââââââââââââââââââââââââââââ€
â åºçšå±ïŒServiceïŒ â
âââââââââââââââââââââââââââââââââââââââââââ€
â é¢åå±ïŒDomainïŒ â
âââââââââââââââââââââââââââââââââââââââââââ€
â åºç¡è®Ÿæœå±ïŒInfrastructureïŒ â
âââââââââââââââââââââââââââââââââââââââââââ
åå±è莣ïŒ
- 衚瀺å±ïŒçšæ·çé¢åAPIæ¥å£ïŒèŽèŽ£äžçšæ·æå ¶ä»ç³»ç»äº€äº
- åºçšå±ïŒåè°é¢åå¯¹è±¡å®æäžå¡æµçšïŒäžå 嫿 žå¿äžå¡è§å
- é¢åå±ïŒæ žå¿äžå¡é»èŸåäžå¡è§åïŒå å«å®äœãåŒå¯¹è±¡ãé¢åæå¡ç
- åºç¡è®Ÿæœå±ïŒæäŸåºå±ææ¯æ¯æïŒåŠæ°æ®åºè®¿é®ãæ¶æ¯éåãçŒåç
äŒç¹ïŒ
- å ³æ³šç¹å犻ïŒäŸ¿äºå¢éåäœ
- å±äžå±ä¹éŽæŸèŠåïŒäŸ¿äºç¬ç«åŒååæµè¯
- 䟿äºç»Žæ€åå级
猺ç¹ïŒ
- å¯èœå¯ŒèŽæ§èœåŒéïŒç¹å«æ¯å¯¹äºå€å±è°çš
- 对äºç®ååºçšå¯èœè¿äºå€æ
å®ç°ç€ºäŸïŒJavaïŒïŒ
// è¡šç€ºå± - Controller
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping
public ResponseEntity<OrderDTO> createOrder(@RequestBody OrderRequest request) {
OrderDTO order = orderService.createOrder(request);
return ResponseEntity.ok(order);
}
}
// åºçšå± - Service
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private ProductService productService;
@Transactional
public OrderDTO createOrder(OrderRequest request) {
// æ£æ¥åºå
productService.checkInventory(request.getProductId(), request.getQuantity());
// å建订å
Order order = new Order();
order.setProductId(request.getProductId());
order.setQuantity(request.getQuantity());
order.setStatus(OrderStatus.CREATED);
order.setCreateTime(LocalDateTime.now());
orderRepository.save(order);
// æ£ååºå
productService.reduceInventory(request.getProductId(), request.getQuantity());
// 蜬æ¢äžºDTOè¿å
return convertToDTO(order);
}
}
// é¢åå± - Entity
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long productId;
private Integer quantity;
private String status;
private LocalDateTime createTime;
// getters and setters
}
// åºç¡è®Ÿæœå± - Repository
@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
// å®ä¹æ¥è¯¢æ¹æ³
}
# 2.2 埮æå¡æ¶æïŒMicroservices ArchitectureïŒ
埮æå¡æ¶æå°ç³»ç»æå䞺äžç»å°åãç¬ç«çæå¡ïŒæ¯äžªæå¡åŽç»ç¹å®çäžå¡åèœæå»ºïŒå¯ä»¥ç¬ç«éšçœ²åæ©å±ã
埮æå¡æ¶æçæ žå¿ç»ä»¶ïŒ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â 客æ·ç«¯åºçšïŒWeb/MobileïŒ â
âââââââââââââââââââââââââââââââââââââââââââ¬ââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââŒââââââââââââââââââââââââââââ
â APIçœå
³ïŒGatewayïŒ â
âââââââââââââââââââââââââââââââââââââââââââ¬ââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââŒââââââââââââââââââââââââââââ
â æå¡æ³šåäžåç°ïŒRegistryïŒ â
âââââââââââââââââââââââââââââââââââââââââââ¬ââââââââââââââââââââââââââââ€
â â â
⌠⌠âŒ
âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ
â 埮æå¡A â â 埮æå¡B â â 埮æå¡C â
â ïŒè®¢åæå¡ïŒ âââââââºâ ïŒæ¯ä»æå¡ïŒ âââââââºâ ïŒçšæ·æå¡ïŒ â
ââââââââââ¬âââââââââ ââââââââââ¬âââââââââ ââââââââââ¬âââââââââ
â â â
⌠⌠âŒ
âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ
â æ°æ®åºA â â æ°æ®åºB â â æ°æ®åºC â
âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ
埮æå¡æ¶æçå ³é®ç¹æ§ïŒ
- æå¡æåïŒæç §äžå¡é¢åæåæå¡
- ç¬ç«éšçœ²ïŒæ¯äžªæå¡å¯ä»¥ç¬ç«éšçœ²åæ©å±
- æ°æ®éçŠ»ïŒæ¯äžªæå¡æèªå·±çæ°æ®åº
- æå¡éä¿¡ïŒé垞䜿çšHTTP/RESTææ¶æ¯éå
- æå¡æ³šåäžåç°ïŒèªåšæ³šåååç°æå¡å®äŸ
- èŽèœœåè¡¡ïŒåšå€äžªæå¡å®äŸéŽåå请æ±
- 容éå€çïŒå€çæå¡æ éççç¥
äŒç¹ïŒ
- æé«ç³»ç»ççµæŽ»æ§å坿©å±æ§
- å¢éå¯ä»¥ç¬ç«åŒååéšçœ²æå¡
- 䟿äºéçšæ°ææ¯åæ¡æ¶
- æé«ç³»ç»çå¯çšæ§åå¯é æ§
ææïŒ
- ååžåŒç³»ç»ç倿æ§
- æå¡éŽéä¿¡çåŒéåäžèŽæ§é®é¢
- ååžåŒäºå¡å€ç
- ç³»ç»çæ§åè°è¯éŸåºŠå¢å
- éšçœ²åè¿ç»Žå€æåºŠæé«
å®ç°ç€ºäŸïŒSpring CloudïŒïŒ
// æå¡æ³šåäžåç° - Eureka Server
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
// 埮æå¡ - 订åæå¡
@SpringBootApplication
@EnableDiscoveryClient
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/{id}")
public Order getOrder(@PathVariable Long id) {
// è°çšçšæ·æå¡è·åçšæ·ä¿¡æ¯
User user = restTemplate.getForObject("http://user-service/users/{id}", User.class, id);
Order order = new Order();
order.setId(id);
order.setUserId(user.getId());
order.setUserName(user.getName());
// ... å
¶ä»è®¢åä¿¡æ¯
return order;
}
}
}
// APIçœå
³
@SpringBootApplication
@EnableZuulProxy
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
# 2.3 äºä»¶é©±åšæ¶æïŒEvent-Driven ArchitectureïŒ
äºä»¶é©±åšæ¶ææ¯äžç§ä»¥äºä»¶äžºäžå¿çæ¶ææš¡åŒïŒç³»ç»äžçç»ä»¶éè¿äº§çåæ¶èŽ¹äºä»¶è¿è¡éä¿¡ååäœã
äºä»¶é©±åšæ¶æçæ žå¿ç»ä»¶ïŒ
âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ
â äºä»¶ç产è
ââââââ¶â äºä»¶éé ââââââ¶â äºä»¶æ¶è޹è
â
âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ
â²
â
ââââââââââŽâââââââââ
â äºä»¶ååš â
âââââââââââââââââââ
å ³é®æŠå¿µïŒ
- äºä»¶ïŒæè¿°åççäºå®æç¶æååçæ¶æ¯
- äºä»¶ééïŒäŒ èŸäºä»¶çæºå¶ïŒéåžžæ¯æ¶æ¯éå
- äºä»¶ç产è ïŒå建并ååžäºä»¶çç»ä»¶
- äºä»¶æ¶è޹è ïŒè®¢é å¹¶å€çäºä»¶çç»ä»¶
- äºä»¶ååšïŒæä¹ åååšäºä»¶çç»ä»¶
äŒç¹ïŒ
- æŸèŠåïŒç»ä»¶ä¹éŽéè¿äºä»¶éä¿¡ïŒäžçŽæ¥äŸèµ
- 坿©å±æ§ïŒå¯ä»¥åšææ·»å æ°çäºä»¶æ¶è޹è
- åŒæ¥å€çïŒæ¯æåŒæ¥æäœïŒæé«ç³»ç»ååé
- 匹æ§ïŒå䞪ç»ä»¶æ éäžäŒçŽæ¥åœ±åå ¶ä»ç»ä»¶
ææïŒ
- äºä»¶é¡ºåºåäžèŽæ§ä¿è¯
- äºä»¶å€ççå¹çæ§
- ç³»ç»å¯è§æµæ§éäœ
- äºä»¶çæ¬ç®¡ç
å®ç°ç€ºäŸïŒKafkaïŒïŒ
// äºä»¶ç产è
@Service
public class OrderEventProducer {
@Autowired
private KafkaTemplate<String, OrderEvent> kafkaTemplate;
public void publishOrderCreatedEvent(Order order) {
OrderEvent event = new OrderEvent();
event.setOrderId(order.getId());
event.setEventType("ORDER_CREATED");
event.setPayload(order);
event.setTimestamp(System.currentTimeMillis());
kafkaTemplate.send("order-events", event);
}
}
// äºä»¶æ¶è޹è
@Service
public class InventoryEventConsumer {
@Autowired
private InventoryService inventoryService;
@KafkaListener(topics = "order-events", groupId = "inventory-group")
public void consumeOrderEvent(OrderEvent event) {
if ("ORDER_CREATED".equals(event.getEventType())) {
Order order = (Order) event.getPayload();
inventoryService.reduceInventory(order.getProductId(), order.getQuantity());
}
}
}
// é
眮Kafka
@Configuration
@EnableKafka
public class KafkaConfig {
@Bean
public ProducerFactory<String, OrderEvent> producerFactory() {
Map<String, Object> configProps = new HashMap<>();
configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
return new DefaultKafkaProducerFactory<>(configProps);
}
@Bean
public KafkaTemplate<String, OrderEvent> kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}
@Bean
public ConsumerFactory<String, OrderEvent> consumerFactory() {
Map<String, Object> configProps = new HashMap<>();
configProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
configProps.put(ConsumerConfig.GROUP_ID_CONFIG, "inventory-group");
configProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
configProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class);
return new DefaultKafkaConsumerFactory<>(configProps, new StringDeserializer(),
new JsonDeserializer<>(OrderEvent.class));
}
}
# 2.4 å èŸ¹åœ¢æ¶æïŒHexagonal ArchitectureïŒ
å èŸ¹åœ¢æ¶æïŒä¹ç§°äžºç«¯å£åéé åšæ¶æïŒå°åºçšçšåºæ žå¿äžå¡é»èŸäžå€éšç³»ç»å犻ïŒéè¿ç«¯å£åéé åšè¿è¡éä¿¡ã
å èŸ¹åœ¢æ¶æçæ žå¿ç»ä»¶ïŒ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â å
èŸ¹åœ¢æ¶æ â
â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â åºçšæ žå¿äžå¡é»èŸ â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â² â² â
â â â â
â â â â
â ââââââââââââââââââââââââââ ââââââââââââââââââââââââââ â
â â â â
â â 端å£ïŒPortïŒ â â
â âââââââââââââââââââââââââââââââ¬ââââââââââââââââââââââââââââââââ â
â â â
â âââââââââââââââââââââââââââââââŒââââââââââââââââââââââââââââââââ â
â â â â â
â ⌠⌠⌠â
âââââââââââââââ ââââââââââââââ âââââââââââââââ
ââ éé
åšA â â éé
åšB â â éé
åšC ââ
âââââââââââââââ ââââââââââââââ âââââââââââââââ
â â² â² â² â
âââââââŒâââââââââââââââââââââââââââŒâââââââââââââââââââââââââââŒâââââââââââ
â â â
âââââââŒâââââââââââââ ââââââââââŒâââââââââââââ ââââââââââŒâââââââââââââ
â å€éšç³»ç»A â â å€éšç³»ç»B â â å€éšç³»ç»C â
â ïŒUI/APIïŒ â â ïŒæ°æ®åºïŒ â â ïŒæ¶æ¯éåïŒ â
ââââââââââââââââââââ ââââââââââââââââââââââ ââââââââââââââââââââ
å ³é®æŠå¿µïŒ
- åºçšæ žå¿ïŒå å«é¢åæš¡ååäžå¡è§åïŒäžäŸèµå€éšç³»ç»
- 端å£ïŒå®ä¹äžå€éšç³»ç»äº€äºçæ¥å£
- éé åšïŒå®ç°ç«¯å£ïŒèŽèŽ£äžå€éšç³»ç»éä¿¡ïŒå¹¶å°å€éšè¯·æ±èœ¬æ¢äžºå éšè°çš
- 驱åšéé åšïŒé©±åšåºçšçšåºçéé åšïŒåŠUIãAPIç
- 被驱åšéé åšïŒè¢«åºçšçšåºè°çšçéé åšïŒåŠæ°æ®åºè®¿é®ãæ¶æ¯åéç
äŒç¹ïŒ
- äžå¡é»èŸäžææ¯å®ç°å®å šå犻
- äŸ¿äºæµè¯ïŒæ žå¿äžå¡é»èŸå¯ä»¥ç¬ç«æµè¯
- ææ¯æ å¯ä»¥çµæŽ»æŽæ¢ïŒäžåœ±åæ žå¿äžå¡é»èŸ
- æé«ç³»ç»çå¯ç»Žæ€æ§å坿©å±æ§
å®ç°ç€ºäŸïŒ
// åºçšæ žå¿ - é¢åæå¡
public class OrderService {
private final OrderRepository orderRepository;
private final ProductService productService;
// éè¿æé åœæ°æ³šå
¥äŸèµ
public OrderService(OrderRepository orderRepository, ProductService productService) {
this.orderRepository = orderRepository;
this.productService = productService;
}
public Order createOrder(OrderRequest request) {
// æ£æ¥åºå
if (!productService.checkInventory(request.getProductId(), request.getQuantity())) {
throw new InsufficientInventoryException("Insufficient inventory for product: " + request.getProductId());
}
// å建订å
Order order = new Order();
order.setProductId(request.getProductId());
order.setQuantity(request.getQuantity());
order.setStatus(OrderStatus.CREATED);
order.setCreateTime(LocalDateTime.now());
// ä¿å订å
orderRepository.save(order);
// æ£ååºå
productService.reduceInventory(request.getProductId(), request.getQuantity());
return order;
}
}
// ç«¯å£ - 订åä»åºæ¥å£
public interface OrderRepository {
Order save(Order order);
Order findById(Long id);
List<Order> findByUserId(Long userId);
}
// ç«¯å£ - 产åæå¡æ¥å£
public interface ProductService {
boolean checkInventory(Long productId, int quantity);
void reduceInventory(Long productId, int quantity);
}
// éé
åš - JPAå®ç°è®¢åä»åº
@Repository
public class JpaOrderRepository implements OrderRepository {
@Autowired
private OrderJpaRepository orderJpaRepository;
@Override
public Order save(Order order) {
return orderJpaRepository.save(convertToEntity(order));
}
@Override
public Order findById(Long id) {
return orderJpaRepository.findById(id).map(this::convertToDomain).orElse(null);
}
@Override
public List<Order> findByUserId(Long userId) {
return orderJpaRepository.findByUserId(userId).stream()
.map(this::convertToDomain)
.collect(Collectors.toList());
}
// èœ¬æ¢æ¹æ³
private OrderEntity convertToEntity(Order order) {
// 蜬æ¢é»èŸ
}
private Order convertToDomain(OrderEntity entity) {
// 蜬æ¢é»èŸ
}
}
// éé
åš - RESTæ§å¶åš
@RestController
@RequestMapping("/api/orders")
public class OrderController {
private final OrderService orderService;
@Autowired
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
@PostMapping
public ResponseEntity<OrderDTO> createOrder(@RequestBody OrderRequest request) {
Order order = orderService.createOrder(request);
return ResponseEntity.ok(convertToDTO(order));
}
// èœ¬æ¢æ¹æ³
private OrderDTO convertToDTO(Order order) {
// 蜬æ¢é»èŸ
}
}
# äžãæ¶æè¯äŒ°äžå³ç
# 3.1 æ¶æè¯äŒ°æ¹æ³
æ¶æè¯äŒ°æ¯ç¡®ä¿æ¶æè®Ÿè®¡ç¬Šåç³»ç»éæ±çéèŠç¯èïŒä»¥äžæ¯äžäºåžžçšçæ¶æè¯äŒ°æ¹æ³ïŒ
- ATAMïŒArchitecture Tradeoff Analysis MethodïŒïŒå ³æ³šæ¶æå³çäžçæè¡¡
- SAAMïŒSoftware Architecture Analysis MethodïŒïŒè¯äŒ°æ¶æå¯¹ç¹å®èŽšé屿§ç满足çšåºŠ
- SBARïŒScenario-Based Architecture Analysis and ReviewïŒïŒåºäºåºæ¯çæ¶æåæåè¯å®¡
- ARCïŒArchitecture Review CouncilïŒïŒç±äžå®¶ç»æçæ¶æè¯å®¡å§åäŒ
# 3.2 æ¶æå³çè®°åœïŒADRïŒ
æ¶æå³çè®°åœïŒArchitecture Decision Record, ADRïŒæ¯è®°åœéèŠæ¶æå³ççææ¡£ïŒå å«å³ççèæ¯ãé项ãå³ççç±å圱åçã
ADRæš¡æ¿ïŒ
# ADR-001: 䜿çšåŸ®æå¡æ¶æ
## æ¥æ
2023-05-01
## èæ¯
éçäžå¡çå¿«éåå±ïŒåäœåºçšç绎æ€åæ©å±ååŸè¶æ¥è¶å°éŸãå¢éè§æš¡æ©å€§ïŒå€äººåæ¶åŒååäžä»£ç åºå¯ŒèŽé¢ç¹ç代ç å²çªãç³»ç»åæš¡åèŠå床é«ïŒéŸä»¥ç¬ç«éšçœ²åæ©å±ã
## å³çé项
1. ç»§ç»ç»Žæ€åäœåºçšïŒéè¿ä»£ç éææé«å¯ç»Žæ€æ§
2. éçšåŸ®æå¡æ¶æïŒå°ç³»ç»æå䞺å€äžªç¬ç«çæå¡
3. éçšæš¡åååäœæ¶æïŒåšåäœåºçšå
éšå®ç°é«å
èäœèŠå
## å³ç
éæ©é项2ïŒéçšåŸ®æå¡æ¶æïŒå°ç³»ç»æç
§äžå¡é¢åæå䞺å€äžªç¬ç«çæå¡ã
## çç±
1. æé«ç³»ç»ç坿©å±æ§ïŒæ¯äžªæå¡å¯ä»¥ç¬ç«æ©å±
2. æé«å¢éåŒåæçïŒåå¢éå¯ä»¥ç¬ç«åŒååéšçœ²æå¡
3. éäœç³»ç»çèŠååºŠïŒæé«ç³»ç»çå¯ç»Žæ€æ§
4. 䟿äºéçšæ°ææ¯åæ¡æ¶ïŒæ¯äžªæå¡å¯ä»¥éæ©æéåçææ¯æ
5. æé«ç³»ç»çå¯çšæ§ïŒå䞪æå¡æ
éäžäŒå¯ŒèŽæŽäžªç³»ç»åŽ©æº
## 圱å
1. å¢å äºç³»ç»ç倿æ§ïŒéèŠè§£å³ååžåŒç³»ç»çåç§é®é¢
2. éèŠåŒå
¥æå¡æ³šåäžåç°ãAPIçœå
³çåºç¡è®Ÿæœ
3. éèŠè§£å³ååžåŒäºå¡é®é¢
4. éèŠå 区系ç»çæ§åæ¥å¿ç®¡ç
5. å¢ééèŠåŠä¹ åéåºåŸ®æå¡æ¶æçåŒååè¿ç»Žæ¹åŒ
## çžå
³å³ç
- ADR-002: éæ©Spring CloudäœäžºåŸ®æå¡æ¡æ¶
- ADR-003: éæ©Kafkaäœäžºæ¶æ¯éå
## ç¶æ
å·²æ¹å
# 3.3 æ¶ææŒè¿
æ¶æäžæ¯äžæäžåçïŒèæ¯éçäžå¡éæ±åææ¯åå±äžææŒè¿çãä»¥äžæ¯æ¶ææŒè¿çåžžè§æš¡åŒïŒ
- åäœåºçš -> æš¡åååäœ -> 埮æå¡ïŒè¿æ¯è®žå€ç³»ç»çæŒè¿è·¯åŸ
- åçŽæ©å± -> æ°Žå¹³æ©å±ïŒä»å¢å å䞪æå¡åšçèµæºå°å¢å æå¡åšæ°é
- éäžåŒæ¶æ -> ååžåŒæ¶æïŒä»ææåèœéäžåšäžäžªç³»ç»å°ååžåšå€äžªç³»ç»
- å ³ç³»åæ°æ®åº -> 倿°æ®åºæ··åïŒæ ¹æ®æ°æ®ç¹æ§éæ©åéçæ°æ®åº
- äŒ ç»éšçœ² -> 容åšå -> äºåçïŒéšçœ²æ¹åŒçæŒè¿
# åãæ¶æè®Ÿè®¡å®è·µ
# 4.1 é¢å驱åšè®Ÿè®¡ïŒDDDïŒçåºçš
é¢å驱åšè®Ÿè®¡ïŒDomain-Driven DesignïŒDDDïŒæ¯äžç§äžæ³šäºäžå¡é¢åç蜯件åŒåæ¹æ³ïŒå®å¯ä»¥åž®å©æä»¬æŽå¥œå°çè§£åè®Ÿè®¡å€æçäžå¡ç³»ç»ã
DDDçæ žå¿æŠå¿µïŒ
- é¢åïŒäžå¡é¢åïŒå å«äžå¡è§ååæŠå¿µ
- åé¢åïŒé¢åçåéšåïŒå æ¬æ žå¿åãæ¯æååéçšå
- å®äœïŒEntityïŒïŒå ·æå¯äžæ è¯çé¢å对象
- åŒå¯¹è±¡ïŒValue ObjectïŒïŒæ²¡æå¯äžæ è¯çäžå¯å对象
- é¢åæå¡ïŒDomain ServiceïŒïŒå°è£ äžå±äºå䞪å®äœæåŒå¯¹è±¡çäžå¡é»èŸ
- èåïŒAggregateïŒïŒäžç»çžå ³çå®äœååŒå¯¹è±¡ïŒäœäžºäžäžªæŽäœè¿è¡æ°æ®ä¿®æ¹
- ä»åšïŒRepositoryïŒïŒæäŸå¯¹èåç访é®åæä¹ å
- å·¥åïŒFactoryïŒïŒèŽèŽ£åå»ºå€æçé¢å对象
- é¢åäºä»¶ïŒDomain EventïŒïŒè¡šç€ºé¢åäžåççéèŠäºä»¶
DDDäžæ¶æçå ³ç³»ïŒ
DDDäžºæ¶æè®Ÿè®¡æäŸäºäž°å¯çæŠå¿µåæ¹æ³ïŒå¯ä»¥åž®å©æä»¬æŽå¥œå°è®Ÿè®¡ç³»ç»çç»æåç»ä»¶ãäŸåŠïŒåºäºDDDç埮æå¡æåå¯ä»¥æŽå¥œå°ä¿æäžå¡é»èŸç宿޿§åäžèŽæ§ã
# 4.2 æ¶æè®Ÿè®¡ææ¡£ïŒADDïŒ
æ¶æè®Ÿè®¡ææ¡£ïŒArchitecture Design DocumentïŒADDïŒæ¯è®°åœç³»ç»æ¶æè®Ÿè®¡çéèŠææ¡£ïŒå®æè¿°äºç³»ç»çæŽäœç»æãç»ä»¶å ³ç³»ãææ¯éåçã
ADDçäž»èŠå 容ïŒ
- ç³»ç»æŠè¿°ïŒç³»ç»çç®æ ãèåŽåäž»èŠåèœ
- æ¶æååïŒæ¶æè®Ÿè®¡çæå¯Œåå
- æ¶æè§åŸïŒä»äžåè§åºŠæè¿°ç³»ç»æ¶æ
- é»èŸè§åŸïŒç³»ç»çåèœæš¡ååç»ä»¶å ³ç³»
- ç©çè§åŸïŒç³»ç»çéšçœ²æ¶æ
- æ°æ®è§åŸïŒç³»ç»çæ°æ®æš¡ååååšæ¹åŒ
- éä¿¡è§åŸïŒç³»ç»çéä¿¡æ¹åŒååè®®
- ç»ä»¶æè¿°ïŒåç»ä»¶çåèœãæ¥å£åå®ç°æ¹åŒ
- ææ¯éåïŒéæ©çææ¯æ åæ¡æ¶
- 莚é屿§ïŒç³»ç»çæ§èœãå¯çšæ§ãå¯é æ§ç莚é屿§èŠæ±åå®ç°çç¥
- å®å šè®Ÿè®¡ïŒç³»ç»çå®å šçç¥åå®ç°æ¹åŒ
- éšçœ²æ¶æïŒç³»ç»çéšçœ²ç¯å¢åææç»æ
# 4.3 æ¶æåžçè§è²äžè莣
æ¶æåžåšèœ¯ä»¶åŒåè¿çšäžæ®æŒçéèŠçè§è²ïŒä»¥äžæ¯æ¶æåžçäž»èŠè莣ïŒ
- æ¶æè®Ÿè®¡ïŒèŽèŽ£ç³»ç»çæŽäœæ¶æè®Ÿè®¡ïŒå æ¬ææ¯éåãç»ä»¶ååç
- ææ¯å³çïŒå¶å®ææ¯è§èåæ åïŒåéèŠçææ¯å³ç
- é£é©è¯äŒ°ïŒè¯å«åè¯äŒ°ææ¯é£é©ïŒå¹¶å¶å®çžåºçåºå¯¹çç¥
- å¢éæå¯ŒïŒæå¯ŒåŒåå¢éçè§£åéµåŸªæ¶æè®Ÿè®¡
- æ¶æè¯å®¡ïŒå®æè¯å®¡ç³»ç»æ¶æïŒç¡®ä¿æ¶æçäžèŽæ§å莚é
- ææ¯æŒè¿ïŒå ³æ³šææ¯åå±è¶å¿ïŒæšåšç³»ç»æ¶æçæŒè¿
- è·šå¢éåäœïŒåè°äžåå¢éä¹éŽçå·¥äœïŒç¡®ä¿ç³»ç»çæŽäœäžèŽæ§
# äºãæ¡äŸåæ
# 5.1 çµåç³»ç»æ¶æè®Ÿè®¡
ç³»ç»æŠè¿°ïŒ äžäžªå žåççµåç³»ç»å æ¬çšæ·ç®¡çãåå管çã订å管çãæ¯ä»ç®¡çãåºå管ççæ žå¿æš¡åã
æ¶æè®Ÿè®¡ïŒ
埮æå¡æåïŒæç §äžå¡é¢åå°ç³»ç»æå䞺å€äžªåŸ®æå¡
- çšæ·æå¡ïŒèŽèŽ£çšæ·æ³šåãç»åœã䞪人信æ¯ç®¡ç
- ååæå¡ïŒèŽèŽ£ååä¿¡æ¯ç®¡çãå类管çãæçŽ¢ç
- 订åæå¡ïŒèŽèŽ£è®¢ååå»ºãæ¥è¯¢ãç¶æç®¡çç
- æ¯ä»æå¡ïŒèŽèŽ£æ¯ä»å€çã鿬Ÿç
- åºåæå¡ïŒèŽèŽ£åºå管çãåºåæ£åç
- æšèæå¡ïŒèŽèŽ£ååæšèã䞪æ§åæšèç
ææ¯éåïŒ
- æ¡æ¶ïŒSpring Cloud
- æå¡æ³šåäžåç°ïŒEureka
- APIçœå ³ïŒSpring Cloud Gateway
- é 眮äžå¿ïŒSpring Cloud Config
- æ¶æ¯éåïŒKafka/RabbitMQ
- æ°æ®åºïŒMySQLïŒå ³ç³»åæ°æ®ïŒãMongoDBïŒéç»æåæ°æ®ïŒ
- çŒåïŒRedis
- æçŽ¢åŒæïŒElasticsearch
æ¶æåŸïŒ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â 客æ·ç«¯ïŒWeb/MobileïŒ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¬ââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââŒââââââââââââââââââââââââââ
â APIçœå
³ïŒSpring Cloud GatewayïŒ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¬ââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââŒââââââââââââââââââââââââââ
â æå¡æ³šåäžåç°ïŒEureka/NacosïŒ â
âââââââââââââââââââââââââââââââââââââââââââ¬ââââââââââââââââââââââââââââââââââââââââââ¬ââââââââ€
â â â â
⌠⌠⌠âŒ
âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ
â çšæ·æå¡ â â ååæå¡ â â 订åæå¡ â â æ¯ä»æå¡ â
ââââââââââ¬âââââââââ ââââââââââ¬âââââââââ ââââââââââ¬âââââââââ ââââââââââ¬âââââââââ
â â â â
âââââââââââââââââââââââââââŒâââââââââââââââââââââââââââŒâââââââââââââââââââââââââââ€
â â â â
⌠⌠⌠âŒ
âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ
â RedisçŒå â â Elasticsearch â â Kafkaæ¶æ¯éå â â ååžåŒäºå¡ â
âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ
â² â² â² â²
â â â â
ââââââââââŽâââââââââ ââââââââââŽâââââââââ ââââââââââŽâââââââââ ââââââââââŽâââââââââ
â MySQLçšæ·åº â â MySQLåååº â â MySQL订ååº â â ç¬¬äžæ¹æ¯ä» â
âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ
å ³é®æ¶æå³çïŒ
- 埮æå¡æåçç¥ïŒåºäºäžå¡é¢åè¿è¡æåïŒç¡®ä¿æ¯äžªæå¡çè莣åäž
- æ°æ®é犻çç¥ïŒæ¯äžªæå¡æ¥æèªå·±çæ°æ®åºïŒéè¿APIè°çšè®¿é®å ¶ä»æå¡çæ°æ®
- ååžåŒäºå¡å€çïŒéçšæç»äžèŽæ§çç¥ïŒéè¿æ¶æ¯éåç¡®ä¿æ°æ®æç»äžèŽ
- é«å¯çšè®Ÿè®¡ïŒæ¯äžªæå¡éšçœ²å€äžªå®äŸïŒéè¿èŽèœœåè¡¡æé«å¯çšæ§
- çŒåçç¥ïŒåŒå ¥å€çº§çŒåïŒæ¬å°çŒå+ååžåŒçŒåïŒæé«ç³»ç»æ§èœ
- å®å šè®Ÿè®¡ïŒç»äžçè®€è¯æææºå¶ïŒAPIçœå ³å±å®ç°è®¿é®æ§å¶
# 5.2 éèç³»ç»æ¶æè®Ÿè®¡
ç³»ç»æŠè¿°ïŒ äžäžªå žåçéèç³»ç»å æ¬èŽŠæ·ç®¡çã亀æå€çãé£é©ç®¡çãæ¥è¡šç³»ç»çæ žå¿æš¡åïŒå¯¹å®å šæ§ãå¯é æ§åæ§èœèŠæ±æé«ã
æ¶æè®Ÿè®¡ïŒ
å屿¶æïŒ
- æ¥å ¥å±ïŒå€çå€éšç³»ç»åçšæ·çæ¥å ¥ïŒå æ¬APIçœå ³ãå®å šè®€è¯ç
- äžå¡å±ïŒå®ç°æ žå¿äžå¡é»èŸïŒå æ¬èŽŠæ·æå¡ã亀ææå¡ã飿§æå¡ç
- æ°æ®å±ïŒèŽèŽ£æ°æ®ååšå访é®ïŒå æ¬æ°æ®åºãçŒåãæ°æ®ä»åºç
- åºç¡è®Ÿæœå±ïŒæäŸåºå±æ¯æïŒå æ¬æ¥å¿ãçæ§ãé 眮管çç
å ³é®ææ¯éåïŒ
- æ¡æ¶ïŒSpring BootãSpring Cloud
- æ°æ®åºïŒOracleïŒæ žå¿äžå¡ïŒãMySQLïŒéæ žå¿äžå¡ïŒ
- çŒåïŒRedis
- æ¶æ¯éåïŒKafka
- ååžåŒäºå¡ïŒXAäºå¡æTCCäºå¡
- å®å 𿡿¶ïŒSpring SecurityãOAuth2
- çæ§ç³»ç»ïŒPrometheusãGrafana
æ¶æç¹ç¹ïŒ
- é«å¯çšæ§ïŒå ³é®æå¡å€æŽ»éšçœ²ïŒæ éèªåšåæ¢
- å®å šæ§ïŒå€çº§å®å šé²æ€ïŒå æ¬æ°æ®å å¯ãè®¿é®æ§å¶ã审计æ¥å¿ç
- å¯é æ§ïŒæ°æ®å€å¯æ¬ååšïŒäºå¡ä¿è¯ïŒçŸå€æºå¶
- æ§èœäŒåïŒçŒåãæ°æ®åºäŒåãåŒæ¥å€çç
- åè§æ§ïŒæ»¡è¶³éèè¡äžççç®¡èŠæ±
# å ãæ»ç»
ç³»ç»æ¶æè®Ÿè®¡æ¯èœ¯ä»¶åŒåçéèŠç¯èïŒå®å³å®äºç³»ç»ç莚éã坿©å±æ§åå¯ç»Žæ€æ§ãäžäžªå¥œçæ¶æè®Ÿè®¡åºè¯¥ïŒ
- 笊åäžå¡éæ±ïŒæ¶æè®Ÿè®¡åºè¯¥æå¡äºäžå¡éæ±ïŒæ¯æäžå¡çåå±ååå
- 平衡åç§èŽšé屿§ïŒæ§èœãå¯çšæ§ãå¯é æ§ãå®å šæ§ç莚é屿§ä¹éŽéèŠè¿è¡éåœçæè¡¡
- å ·å€è¯å¥œç坿©å±æ§ïŒèœå€åºå¯¹äžå¡å¢é¿åååçéæ±
- ä¿æéåœçå€æåºŠïŒäžè¿åºŠè®Ÿè®¡ïŒä¹äžè¿äºç®å
- éµåŸªè®Ÿè®¡ååïŒé«å èäœèŠåãåäžè莣ç讟计åå
æ¶æè®Ÿè®¡äžæ¯äžè¹Žèå°±çïŒèæ¯äžäžªæç»æŒè¿çè¿çšãéçäžå¡éæ±çåååææ¯çåå±ïŒæ¶æä¹éèŠäžæå°è°æŽåäŒåãäœäžºæ¶æåžïŒéèŠä¿æå¯¹äžå¡åææ¯çææåºŠïŒåæ¶è°æŽæ¶æä»¥éåºæ°ç鿱忿ã
æåïŒæ¶æè®Ÿè®¡æ¯äžäžªå¢é掻åšïŒéèŠäžäžå¡äººåãåŒå人åãæµè¯äººåçå¯ååäœïŒå ±å宿ãåªæå¢éæåå¯¹æ¶ææå ±åççè§£åå ±è¯ïŒæèœç¡®ä¿æ¶æçææå®æœåæŒè¿ã