微服務間消息傳遞
微服務是一種軟件開發架構,它將一個大型應用程序拆分為一系列小型、獨立的服務。每個服務都可以獨立開發、部署和擴展,并通過輕量級的通信機制進行交互。
應用開發
-
common模塊中包含服務提供者和服務消費者共享的內容
-
provider模塊是服務的提供者,用于通過SpringMVC的控制器提供訪問接口
服務提供者
@RestController
@RequestMapping("/users")
public class HelloController {@GetMapping("/hello")public String sayHello(@RequestParam String username) {if (username == null || username.trim().length() < 1)username = "MicroService";return "Provider: hello " + username + "!";}
}
服務消費者
服務消費者通過http協議訪問服務提供者,可以使用JDK的URL或者使用HttpClient之類的工具,但是直接使用工具比較繁瑣,所以使用SpringBoot提供的RestTemplate進行訪問
在主類或者當前應用的配置類上聲明RestTemplate
@SpringBootApplication
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}
核心配置,主要修改一下訪問端口號,因為應用的默認端口都是8080,會有端口號沖突的問題
server.port=7081
定義控制器實現訪問服務提供者
@RestController
@RequestMapping("/consumer")
public class ConsumerController {@Autowiredprivate RestTemplate restTemplate;@GetMapping("/{name}")public String test(@PathVariable String name){
//RestTemplate針對RESTful中的get/post/delete/put分別提供了對應的方法String res =
restTemplate.getForObject("http://localhost:7080/users/hello?username=" +
name, String.class);return res;}
}
測試驗證
面試題
-
http協議的訪問流程,在瀏覽器中輸入一個URL地址都發生了什么事情
-
http協議的不同版本的區別,與https的區別
-
http協議中get和post之間的區別
Nacos服務治理
Nacos即Naming and Configuration Service是一個用于動態服務發現、配置管理和服務元數據的開源平臺。
Nacos的主要功能包括:
-
服務注冊和發現:Nacos允許服務實例向注冊中心注冊自己的信息,并且其他服務可以通過查詢注冊中心來發現可用的服務實例
-
配置管理:Nacos提供了一個中心化的配置管理平臺,可以動態地管理應用程序的配置信息。開發人員可以在運行時更新配置,而不需要重啟應用程序
-
服務元數據管理:Nacos可以幫助開發人員管理服務的元數據,包括版本號、權重、健康狀態等。這些元數據可以用于服務路由、負載均衡等場景
-
動態DNS服務:Nacos支持將服務名稱解析為具體的網絡地址,從而實現動態DNS服務的功能
應用開發步驟
服務提供者
需要添加額外的依賴,也就是Nacos的客戶端
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacosdiscovery</artifactId>
</dependency>
添加配置application.properties
# 配置當前應用名稱,默認情況下向nacos注冊的服務名稱就是這個名稱
spring.application.name=service-provider
# Nacos 服務發現與注冊配置,其中子屬性 server-addr 指定 Nacos 服務器主機和端口
spring.cloud.nacos.discovery.server-addr=localhost:8848
# 注冊到 nacos 的指定 namespace,默認為 public
spring.cloud.nacos.discovery.namespace=public
# 應用服務 WEB 訪問端口
server.port=6080
添加JavaConfig配置或者在主類上添加注解以啟用Nacos客戶端
@EnableDiscoveryClient
@Configuration
public class NacosDiscoveryConfiguration {
}
定義服務提供者接口
@RestController
@RequestMapping("/users")
public class HelloController {@GetMapping("/hello")public String sayHello(@RequestParam String username) {if (username == null || username.trim().length() < 1)username = "MicroService";return "Provider: hello " + username + "!";}
}
服務消費者
依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacosdiscovery</artifactId>
</dependency>
添加核心配置application.properties
server.port=6081
spring.application.name=service-consumer
# Nacos 服務發現與注冊配置,其中子屬性 server-addr 指定 Nacos 服務器主機和端口
spring.cloud.nacos.discovery.server-addr=localhost:8848
# 注冊到 nacos 的指定 namespace,默認為 public
spring.cloud.nacos.discovery.namespace=public
添加配置類或者在主類上添加注解啟用Nacos客戶端
@EnableDiscoveryClient
@SpringBootApplication
public class Consumer1Application {public static void main(String[] args) {SpringApplication.run(Consumer1Application.class, args);}@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}
定義服務消費者
@RestController
@RequestMapping("/consumer")
public class ConsumerController{ @Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;@GetMapping("/{name}")public String test(@PathVariable String name){
//服務的名稱對應的是服務提供者的application.properties中的配置spring.application.name=service-providerList<ServiceInstance> instances =
discoveryClient.getInstances("service-provider"); //因為一個服務可以運行在多個節點上或者使用多個進程
//自定義負載均衡策略實現從多個服務提供者實例中選擇一個Random r=new Random();ServiceInstance instance =
instances.get(r.nextInt(instances.size()));String res =
restTemplate.getForObject(instance.getUri()+"/users/hello?username=" + name,
String.class);return res;}
}
驗證測試
-
首先啟動nacos中間件 startup -m standalone ,對應的管理控制臺為http://localhost:8848/nacos
-
啟動服務提供者。在Nacos的webUI中就可以看到服務提供者的注冊信息
使用該管理控制臺可以針對服務提供者的詳細信息進行查看,例如節點情況
- 啟動服務消費者
引入負載均衡
在消費方引入負載均衡機制,同時簡化獲取服務提供者信息的流程
Spring Cloud引入組件LoadBalance實現負載均衡
添加依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacosdiscovery</artifactId>
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
properties配置
spring.application.name=service-consumer
# Nacos 服務發現與注冊配置,其中子屬性 server-addr 指定 Nacos 服務器主機和端口
spring.cloud.nacos.discovery.server-addr=localhost:8848
# 注冊到 nacos 的指定 namespace,默認為 public
spring.cloud.nacos.discovery.namespace=public
server.port=6082
主類上添加對應的注解
@EnableDiscoveryClient
@SpringBootApplication
public class Consumer2Application {public static void main(String[] args) {SpringApplication.run(Consumer2Application.class, args);}@LoadBalanced@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}
定義對應的控制器,需要訪問服務提供者
@RestController
@RequestMapping("/consumer")
public class ConsumerController {@Autowiredprivate RestTemplate restTemplate;@GetMapping("/{name}")public String test(@PathVariable String name){
//使用LB后具體的URL地址中使用服務提供者的名稱來替代原始的主機名和端口號String res = restTemplate.getForObject("http://serviceprovider/users/hello?username=" + name, String.class);return res;}
}
驗證測試
緩存配置
使用LB從Nacos獲取服務的注冊信息,可以在本地進行緩存。添加配置即可
spring.cloud.loadbalancer.cache.enabled=true 啟用本地緩存,可以根據實際情況權衡
spring.cloud.loadbalancer.cache.capacity=1000 設置緩存空間大小
spring.cloud.loadbalancer.cache.ttl=20 緩存的存活時間,單位為s
訂閱更新
緩存有可能和遠程的注冊信息不一致,所以引入長連接的訂閱實現Nacos的主動通知更改
spring.cloud.nacos.discovery.watch.enabled=true