做好政府網(wǎng)站建設(shè)工作的通知安卓神級系統(tǒng)優(yōu)化工具
項目地址:源代碼
僅作為學(xué)習(xí)用例使用,是我開發(fā)過程中的總結(jié)、實際的一部分使用方式
開發(fā)環(huán)境:
jdk11
springboot2.7.6
springcloud2021.0.5
alibabacloud 2021.0.4.0
redis6.0
mysql8.0
一、項目搭建
wdz-api:存放遠程服務(wù)調(diào)用相關(guān)接口
wdz-auth:認證業(yè)務(wù)
wdz-gateway:網(wǎng)關(guān)
wdz-modules:業(yè)務(wù)模塊微服務(wù)
wdz-common:存放公用中間件、數(shù)據(jù)庫等服務(wù)
pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><packaging>pom</packaging><modules><module>wdz-common</module><module>wdz-gateway</module><module>wdz-api</module><module>wdz-auth</module><module>wdz-modules</module></modules><groupId>com.wdz</groupId><artifactId>wdz-ruzhou</artifactId><version>1.0.0</version><name>wdz-ruzhou</name><description>微服務(wù)架構(gòu)</description><properties><java.version>11</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.7.6</spring-boot.version><spring-cloud.version>2021.0.5</spring-cloud.version><spring-cloud.alibaba>2021.0.4.0</spring-cloud.alibaba><fastjson2.version>2.0.14</fastjson2.version><lombok.version>1.18.24</lombok.version></properties><dependencyManagement><dependencies><!--springcloud 微服務(wù)依賴--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><!--springboot 依賴--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency><!--alibaba 微服務(wù)依賴--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud.alibaba}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></dependency><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>${fastjson2.version}</version></dependency></dependencies></dependencyManagement><!--配置打包環(huán)境數(shù)據(jù)--><profiles><profile><id>dev</id><properties><profiles.active>dev</profiles.active><nacos.username>nacos</nacos.username><nacos.password>nacos</nacos.password><nacos.server>127.0.0.1:8848</nacos.server><nacos.discovery.namespace>5efed786-91f6-44c4-8e14-049df72b2a48</nacos.discovery.namespace><nacos.config.namespace>5efed786-91f6-44c4-8e14-049df72b2a48</nacos.config.namespace></properties><activation><activeByDefault>true</activeByDefault></activation></profile><profile><id>test</id><properties><profiles.active>test</profiles.active><nacos.username>nacos</nacos.username><nacos.password>nacos</nacos.password><nacos.server>127.0.0.1:8848</nacos.server><nacos.discovery.namespace>f02ccd30-e3d5-4235-9282-d0a613bd322b</nacos.discovery.namespace><nacos.config.namespace>f02ccd30-e3d5-4235-9282-d0a613bd322b</nacos.config.namespace></properties></profile><profile><id>prod</id><properties><profiles.active>prod</profiles.active><nacos.username>nacos</nacos.username><nacos.password>nacos</nacos.password><nacos.server>127.0.0.1:8848</nacos.server><nacos.discovery.namespace>747829ca-6d8a-4417-a46a-bd31a6f5e442</nacos.discovery.namespace><nacos.config.namespace>747829ca-6d8a-4417-a46a-bd31a6f5e442</nacos.config.namespace></properties></profile></profiles><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>3.0.0</version></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>${java.version}</source><target>${java.version}</target><encoding>${project.build.sourceEncoding}</encoding></configuration></plugin></plugins><!--用于yml配置中變量替換如: @nacos.name@--><resources><resource><directory>src/main/resources</directory><!-- 引入所有 匹配文件進行過濾 --><includes><include>application*</include><include>bootstrap*</include><include>logback*</include></includes><!-- 啟用過濾 即該資源中的變量將會被過濾器中的值替換 --><filtering>true</filtering></resource></resources></build>
</project>
nacos(2.2.0.1)
我為什么選擇nacos作為注冊中心?
1、獨立的可視化管理后臺
2、持久化,配置數(shù)據(jù)直接存儲在數(shù)據(jù)庫中
3、動態(tài)配置,修改配置可實時生效,不用重啟
4、活躍度高,資料文件豐富
5、功能全面
6、是經(jīng)過阿里巴巴考驗的
戳==>官網(wǎng)
安裝nacos
點擊選擇版本下載
windows建議下載zip
linux 建議下載tar.gz
下載完成解壓即可
配置數(shù)據(jù)庫
打開conf下的application.properties文件:
修改數(shù)據(jù)庫配置,將注釋打開,并配置數(shù)據(jù)源
創(chuàng)建數(shù)據(jù)庫目前只支持mysql,版本要求:5.6.5+
需要IPV6支持使用:derby-schema.sql 否則使用:mysql-schema.sql 配置完成后
單機啟動nacos:
Linux/Unix/Mac使用命令:sh startup.sh -m standalone
windows使用命令:./startup.cmd -m standalone
standalone:表示單機模式運行,非集群模式
官方文檔
啟動過程中如果出現(xiàn)jwt認證問題啟動失敗,請參考:戳詳情
錯誤示例
修改文件:
nacos.core.auth.plugin.nacos.token.secret.key
使用base64 處理數(shù)據(jù)長度大于等于32即可
訪問:http://localhost:8848/nacos,默認用戶名密碼:nacos
集群啟動 官方文檔
如果是在一臺電腦上/服務(wù)器上模擬集群:
將nacos解壓之后的文件nacos復(fù)制多份,
并修改對應(yīng)conf文件夾下的application.properties文件端口配置
再將conf下的cluster.conf.example 復(fù)制一份并修改后綴為conf
將其他nacos地址配置在cluster.conf中
依次啟動服務(wù):
windows命令:./startup.cmd
linux命令: sh ./startup.sh
訪問對應(yīng)nacos
nacos 服務(wù)配置config與發(fā)現(xiàn) discovery
創(chuàng)建測試注冊服務(wù)網(wǎng)關(guān)服務(wù),nacos作為注冊中心有多種方式,本文用javaSDK的方式
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>wdz-ruzhou</artifactId><groupId>com.wdz</groupId><version>1.0.0</version></parent><modelVersion>4.0.0</modelVersion><groupId>com.wdz</groupId><artifactId>wdz-gateway</artifactId><packaging>jar</packaging><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
yml配置:
server:port: 8080servlet:context-path: /spring:application:name: wdz-gatewayprofiles:active: @profiles.active@
---
# 使用導(dǎo)入的方式讀取所有需要的nacos中的配置文件
spring:config:import:- optional:nacos:application-common.yml- optional:nacos:${spring.application.name}.ymlcloud:nacos:username: @nacos.username@password: @nacos.password@server-addr: @nacos.server@# 服務(wù)發(fā)現(xiàn)discovery:namespace: @nacos.discovery.namespace@# 配置config:namespace: @nacos.config.namespace@
集群nacos負載配置:
通過nginx配置服務(wù)訪問的nacos
upstream nacos-cluster{server 127.0.0.1:8247;server 127.0.0.1:8549;server 127.0.0.1:8848;
}
server{listen 801;server_name localhost;location /nacos{proxy_pass http://nacos-cluster;}
}
結(jié)果
負載均衡Ribbon
內(nèi)置負載均衡規(guī)則類 | 規(guī)則描述 |
---|---|
RoundRobinRule | 簡單輪詢服務(wù)列表選擇服務(wù)器,它是Ribbon默認的負載均衡規(guī)則 |
AvailabilityFilteringRule | 忽略規(guī)則:1、鏈接3次失敗,會標記為短路狀態(tài),將持續(xù)30秒,如果還是失敗則持續(xù)短路,時間增長,2、并發(fā)數(shù)過高的服務(wù)鏈接,并發(fā)數(shù)達到上限則會被忽略 |
WeightedResponseTimeRule | 權(quán)重策略,每個服務(wù)器配置一個權(quán)重值,權(quán)重值越小,選擇這個服務(wù)器的比重就會越小 |
ZoneAvooidanceRule | 以區(qū)域可用的服務(wù)器為基礎(chǔ)進行服務(wù)器的選擇,使用Zone對服務(wù)器進行分類,Zone相當于一個機房,一個區(qū)域,然后再對Zone內(nèi)的多個服務(wù)做輪詢 |
BestAvailableRule | 忽略哪些短路服務(wù)器,并選擇并發(fā)數(shù)較低的服務(wù)器 |
RandomRule | 隨機選擇一個可用服務(wù)器 |
RetryRule | 重試機制的選擇邏輯 |
自定義策略方式:
代碼方式:作用的是所有服務(wù)
@Bean
public IRule diyRule(){return new RandomRule();
}
yml方式:作用的是所配置的服務(wù)
servicename: # 服務(wù)名稱如:userserviceribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
ribbon默認是懶加載,第一次訪問的時候響應(yīng)時間會比較長,初次加載之后響應(yīng)就會變短。
開啟ribbon饑餓加載有效提高第一次訪問響應(yīng)時間
ribbon:eager-load:enabled: true # 開啟饑餓加載clients: # 指定加載的服務(wù)名稱- userservice- orderservice- systemservice- XXXservice
nacos服務(wù)分級存儲模型
一級是服務(wù):如:userservice、orderservice
二級是集群:配置了同一個discovery.cluster-name:
三級是實例:如杭州機房的某臺部署了要訪問的服務(wù)器
設(shè)置實例的集群屬性:名稱一樣的在同一個集群內(nèi)
spring.cloud.nacos.discovery.cluster-name:NacosRule負載均衡策略:
1、優(yōu)先選擇同集群的服務(wù)
2、本地集群找不到提供者,才去其他集群找,并且會報警告
3、確定了可用實例列表后,再采用隨機負載均衡挑選實例
NacosRule配置:
servicename: # 服務(wù)名稱如:userserviceribbon:NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
環(huán)境隔離:namespace
spring:cloud:nacos:discovery:namespace: @nacos.discovery.namespace@
# 不同名稱空間之間的服務(wù)不能互通,如user使用的prod order使用的dev,這兩個服務(wù)不能互通
nacos特點
1、支持服務(wù)端主動監(jiān)測提供者狀態(tài),臨時實例采用心跳模式,非臨時實例采用主動監(jiān)測模式
2、林實施例心跳不正常會被剔除nacos的服務(wù)列表,非臨時實例不會被剔除
3、服務(wù)列表變更消息推送模式,服務(wù)列表更新及時
4、nacos集群默認采用AP方式,集群中存在非臨時實例時,采用CP模式
CAP:C(一致性),A(可用性),P(分區(qū)容錯)原文
Feign 源碼
feign是聲明式的http客戶端
使用方式
pom引入依賴
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
java代碼
@FeignClient("applicationName")
public interface ApplicationName{@GetMapping("/get")Object queryById(Long id);
}
自定義feign配置
類型 作用 說明 feign.Logger.Level 修改日志級別 包含四種不同的級別:none、basic、headers、full feign.codec.Decoder 響應(yīng)結(jié)果解析器 http遠程調(diào)用的結(jié)果做解析,例如解析json字符串為java對象 feign.codec.Encoder 請求參數(shù)編碼 將請求參數(shù)編碼,便于通過http請求發(fā)送 feign.Contract 支持注解格式 默認是SpringMvc的注解 feign.Retryer 失敗重試機制 請求失敗的重試機制,默認沒有,會使用Ribbon的重試 none: 不記錄日志
basic:只記錄請求方法和URL以及響應(yīng)狀態(tài)代碼和執(zhí)行時間
headers:記錄基本信息以及請求和響應(yīng)標頭
full:記錄請求和響應(yīng)的頭部、主體和元數(shù)據(jù)
yml日志配置
feign:client:config:default: # DETAULT 是全局配置,如果換成application.name 則是指定服務(wù)有效loggerLevel: FULL
feign:client:config:userservice: # 針對userservice有效loggerLevel: FULL
代碼方式:
public class FeignClientConfig{@Beanpublic Logger.Level feignLogLevel(){return Logger.Level.BASIC;}
}
然后將該配置添加到:
全局配置方式啟動類上
EnableFeignClients(defaultConfiguration=FeignClentConfig.class)
局部配置方式
@FeignClient(value="applicationname",configuration=FeignClientConfig)
feign性能優(yōu)化
URLConnection:默認實現(xiàn),不支持連接池
Apache HttpClient:支持鏈接池
OKHttp:支持連接池
因為http鏈接時要三次握手,斷開時要4次揮手,導(dǎo)致的性能浪費
優(yōu)化的性能主要包括:
1、使用連接池代替默認的URLConnection
2、日志級別,最好用basic或none,日志也會浪費性能
連接池配置:
引入依賴
<!--優(yōu)化feignURLConnection-->
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId>
</dependency>
配置yml
feign:httpclient:enabled: true # 開啟feign對httpClient的支持max-connections: 200 # 最大鏈接數(shù) 可根據(jù)測試結(jié)果最優(yōu)配置max-connections-per-route: 50 # 每個路徑最大鏈接數(shù) 可根據(jù)測試結(jié)果最優(yōu)配置
實踐:
system項目引用
EnableFeignClients.clients 指定feignClient接口,及默認配置
如果發(fā)現(xiàn)RemoteUserService 加載不到提示,spring-cloud-starter-loadbalancer依賴缺失
在api中添加依賴:負載均衡依賴
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
測試接口
目標服務(wù)接口
測試結(jié)果:
SpringAMQP
springboot封裝的消息隊列,使用的是rabbitmq
生產(chǎn)端
引入依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
配置
spring:rabbitmq:host: 127.0.0.1 # 主機port: 5672 # 端口virtual-host: / # 虛擬主機username: rabbitmq # 用戶名password: 123456 # 密碼
消費端
引入依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
配置
spring:rabbitmq:host: 127.0.0.1 # 主機port: 5672 # 端口virtual-host: / # 虛擬主機username: rabbitmq # 用戶名password: 123456 # 密碼
監(jiān)聽java代碼:
@Component
public class RabbitMqListener {@RabbitListener(queues = "mq-user")public void listenerQueueMsg(String msg){System.out.println(msg);}
}
如果提示異常:隊列不存在,且啟動失敗
添加配置:
@Configuration
public class RabbitMqConfig {@Beanpublic Queue initQueue(){return new Queue("mq-user");}
}
由于rabbitmq的消費預(yù)取機制,會導(dǎo)致處理能力弱的消費端處理速度變慢,所以限制預(yù)取信息條數(shù)
spring:rabbitmq:listener:simple:prefetch: 1 # 每次只能獲取一條消息,處理完成之后才能獲取下一個
監(jiān)聽端信息:
@Slf4j
@Component
public class RabbitMqListener {@RabbitListener(queues = "mq-user")public void listenerQueueMsg(String msg) {log.info("[listenerQueueMsg]=========:{}",msg);}@RabbitListener(queues = "mq-user")public void listenerQueueMsg2(String msg) {log.info("[listenerQueueMsg2]=========:{}",msg);}
}
消息發(fā)布/訂閱
發(fā)布訂閱模式允許將同一消息發(fā)送給多個消費者,實現(xiàn)方式是加入exchange(交換機):
fanout:廣播
direct:路由
topic:話題
交換機只處理轉(zhuǎn)發(fā),會造成消息丟失
FanoutExchange 方式
發(fā)送消息用戶服務(wù):
@GetMapping("/send")public LoginUser send(String username) {String queueName = "demo.fanout";String message = username;rabbitTemplate.convertAndSend(queueName,"", message);return new LoginUser(1L, username, "123456");}@GetMapping("/to")public LoginUser to(String username) {String queueName = "demo.fanout";String message = username;rabbitTemplate.convertAndSend(queueName,"", message);return new LoginUser(1L, username, "123456");}
接收消息 system服務(wù):
監(jiān)聽代碼@RabbitListener(queues = "demo.fanout2")public void listenerFanoutMsg2(String msg) {log.info("[demo.fanout2]=========:{}", msg);}
@Configuration
public class FanoutExchangeConfig {/*** 一個消息多個消費者監(jiān)* fanout 廣播模式* 定義交換機*/@Beanpublic FanoutExchange fanoutExchange() {return new FanoutExchange("demo.fanout");}@Beanpublic Queue fanoutQueue() {return new Queue("demo.fanout");}/*** 綁定交換機與隊列關(guān)系** @param fanoutExchange* @param fanoutQueue* @return*/@Beanpublic Binding fanoutBinding(FanoutExchange fanoutExchange,Queue fanoutQueue) {return BindingBuilder.bind(fanoutQueue).to(fanoutExchange);}
}
接收消息 order服務(wù):
監(jiān)聽
@Slf4j
@Component
public class RabbitMqListener {@RabbitListener(queues = "demo.fanout")public void listenerFanoutMsg(String msg) {log.info("[demo.fanout]=========:{}", msg);}
}
fanout 配置
@Configuration
public class FanoutExchangeConfig {/*** 一個消息多個消費者監(jiān)* fanout 廣播模式* 定義交換機*/@Beanpublic FanoutExchange fanoutExchange() {return new FanoutExchange("demo.fanout");}@Beanpublic Queue fanoutQueue() {return new Queue("demo.fanout2");}/*** 綁定交換機與隊列關(guān)系** @param fanoutExchange* @param fanoutQueue* @return*/@Beanpublic Binding fanoutBinding(FanoutExchange fanoutExchange,Queue fanoutQueue) {return BindingBuilder.bind(fanoutQueue).to(fanoutExchange);}
}
均可接收到消息
DirectExchange 方式
direct exchange 會將接收到的消息根據(jù)規(guī)則路由到指定的queue
每個queue都與exchange設(shè)置一個bindingkey
發(fā)布者發(fā)送消息時指定消息的RoutingKey
exchange將消息路由到BingingKey與消息RoutingKey一致的隊列
order/system中的監(jiān)聽
// 注解方式處理監(jiān)聽信息
// bindings 代碼實現(xiàn)的Binding
// @QueueBinding 綁定信息
// value = @Queue(name = "direct.queue")綁定消息隊列
// exchange = @Exchange(name = "demo.direct",type = ExchangeTypes.DIRECT)
// 綁定交換機,名稱是demo.direct 類型是direct
// key 是direct模式的主要配置,可同時監(jiān)聽多個key
@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue"),exchange = @Exchange(name = "demo.direct",type = ExchangeTypes.DIRECT),key = {"system","direct"}))public void listenerMessage(String msg) {log.info("[system.direct]=========:{}", msg);}
消息發(fā)送者:
/***@param exchange 交換機名稱*@param message 消息內(nèi)容*@param routingKey direct 路由key*@return*/@GetMapping("/direct")public void direct(String exchange,String message,String routingKey) {rabbitTemplate.convertAndSend(exchange,routingKey, message);}
發(fā)送信息:
http://localhost/user/direct?exchange=demo.direct&message=發(fā)送的消息內(nèi)容&routingKey=system
Topic 方式
topic方式與direct方式類似,只是key由精準匹配轉(zhuǎn)換為模糊匹配
// 監(jiān)聽@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue"),exchange = @Exchange(name = "topic-wdz",type = ExchangeTypes.TOPIC),key = "#.order"))public void listenerTopicMessage(String msg) {log.info("[listenerTopicMessage]=========:{}", msg);}
發(fā)送
@GetMapping("/direct")
public void direct(String exchange,String message,String routingKey) {rabbitTemplate.convertAndSend(exchange,routingKey, message);
}
優(yōu)化
由于springamqp默認使用的是jdk默認的序列化(ObjectOutputStream)方式,性能問題有待提升。
更換為JSON方式序列化。
生產(chǎn)者/消費者引入依賴
<dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformats-binary</artifactId><version>2.13.4</version></dependency>
初始化bean即可
@Bean
publicMessageConverter messageConverter(){return new Jackson2JsonMessageConverter();
}
Sentinel
分布式事務(wù)seata
事務(wù)(transaction):遵守ACID原則
原子性(Atomicity):事務(wù)中的所有操作,要么全部成功,要么全部失敗
一致性(consistency):要保證數(shù)據(jù)庫內(nèi)部完整性的約束、聲明性約束
隔離性(isolation):對同一自愿操作的事務(wù)不能同時發(fā)生
持久性(durability):對數(shù)據(jù)庫的一切修改將永久保存,不管是否出現(xiàn)故障
演示案例:
下單流程:
訂單服務(wù)創(chuàng)建訂單–>賬戶服務(wù)扣減余額–>商品服務(wù)扣減庫存
1、訪問訂單服務(wù)創(chuàng)建訂單
2、通過feign調(diào)用user扣減余額
3、通過feign調(diào)用goods扣減庫存
feign接口
@FeignClient(value = "wdz-goods")
public interface RemoteGoodsService {@GetMapping("/goods/subtractStock")void subtractStock(@PathVariable("username") String username);}
@FeignClient(value = "wdz-user")
public interface RemoteUserService {@GetMapping("/user/subtractBalance")void subtractBalance();
}
控制器代碼
訂單服務(wù)控制器
@RestController
@RequestMapping("order")
public class OrderController {@Autowiredprivate RemoteGoodsService remoteGoodsService;@Autowiredprivate RemoteUserService remoteUserService;@GetMapping("create")public void create(){System.out.println("訂單服務(wù):創(chuàng)建了訂單");remoteGoodsService.subtractStock();remoteUserService.subtractBalance();}
}
用戶服務(wù)控制器代碼
@RestController
@RequestMapping("user")
public class UserController {@GetMapping("subtractBalance")public void subtractBalance(){System.out.println("用戶服務(wù):減余額");}
}
商品控制器代碼
@RestController
@RequestMapping("goods")
public class GoodsController {@GetMapping("subtractStock")public void subtractStock(){System.out.println("商品服務(wù):減少了庫存");}
}
依次啟動nacos-->gateway-->user-->goods-->order
訪問:http://localhost:8080/order/order/create
訂單服務(wù):創(chuàng)建了訂單
用戶服務(wù):減余額
商品服務(wù):減少了庫存