javascript
SpringCloud微服务架构,Spring Cloud 服务治理(Eureka,Consul,Nacos),Ribbon 客户端负载均衡,RestTemplate与OpenFeign实现远程调用
什么是SpringCloud
微服務(wù)架構(gòu)
? "微服務(wù)”一詞源于 Martin Fowler的名為 Microservices的博文,可以在他的官方博客上找到
http://martinfowler.com/articles/microservices.html
? 微服務(wù)是系統(tǒng)架構(gòu)上的一種設(shè)計(jì)風(fēng)格,它的主旨是將一個(gè)原本獨(dú)立的系統(tǒng)拆分成多個(gè)小型服務(wù),這些小型服務(wù)都在各自獨(dú)立的進(jìn)程中運(yùn)行,服務(wù)之間一般通過(guò) HTTP 的 RESTfuLAPI 進(jìn)行通信協(xié)作。
? 被拆分成的每一個(gè)小型服務(wù)都圍繞著系統(tǒng)中的某一項(xiàng)或些耦合度較高的業(yè)務(wù)功能進(jìn)行構(gòu)建,并且每個(gè)服務(wù)都維護(hù)著白身的數(shù)據(jù)存儲(chǔ)、業(yè)務(wù)開(kāi)發(fā)自動(dòng)化測(cè)試案例以及獨(dú)立部署機(jī)制。
? 由于有了輕量級(jí)的通信協(xié)作基礎(chǔ),所以這些微服務(wù)可以使用不同的語(yǔ)言來(lái)編寫(xiě)。
定義:是一些列組件的集合
組件:
- 注冊(cè)中心
- 配置中心
- 熔斷器
- 網(wǎng)關(guān)
- 負(fù)載均衡
- 消息總線
- 數(shù)據(jù)監(jiān)控
SpringCloud與Dubbo的區(qū)別
- Dubbo是基于RPC協(xié)議實(shí)現(xiàn)遠(yuǎn)程調(diào)用的,同時(shí)要求所用語(yǔ)言必須是Java
- SpringCloud規(guī)定服務(wù)之間通過(guò)http協(xié)議進(jìn)行通信
- Dubbo性能較好(因?yàn)榈讓踊趕ocket),SpringCloud功能全
SpringCloud 服務(wù)治理(詳細(xì)解釋在代碼注釋中)
服務(wù)注冊(cè)與發(fā)現(xiàn)
Eureka
? Eureka 是 Netflix 公司開(kāi)源的一個(gè)服務(wù)注冊(cè)與發(fā)現(xiàn)的組件 。
? Eureka 和其他 Netflix 公司的服務(wù)組件(例如負(fù)載均衡、熔斷器、網(wǎng)關(guān)等) 一起,被 Spring Cloud 社區(qū)整合為
Spring-Cloud-Netflix 模塊。
? Eureka 包含兩個(gè)組件:Eureka Server (注冊(cè)中心) 和 Eureka Client (服務(wù)提供者、服務(wù)消費(fèi)者)。
Eureka – 搭建服務(wù)
搭建eureka服務(wù),編寫(xiě)provider服務(wù)提供者,編寫(xiě)consumer服務(wù)消費(fèi)者端,并將服務(wù)注冊(cè)到eureka注冊(cè)中心,使用Ribbon實(shí)現(xiàn)負(fù)載均衡
這些簡(jiǎn)單的實(shí)體類(lèi)與返回的結(jié)果集就不粘貼出來(lái)了,主要看eureka搭建后的效果
父pom.xml
pom文件中包含一些nacos,OpenFeign后面會(huì)用
搭建 Provider 和 Consumer 服務(wù)。
Provider 創(chuàng)建 fs-provider-8001 項(xiàng)目
多個(gè)提供復(fù)制一下,然后更改端口號(hào)與application.yml中配置注冊(cè)的注冊(cè)中心即可
我只粘貼出application.yml,pom.xml,主啟動(dòng),與服務(wù)提供的controller,因?yàn)閐ao,service就是使用了MyBatis-plus
pom.xml
<?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>study-springcloud</artifactId><groupId>com.fs</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>fs-provider-8001</artifactId><dependencies><!-- spring-boot-starter-web spring-boot-starter-actuator綁定在一塊 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- eureka-Client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><!-- 第一種是:如果你的應(yīng)用不會(huì)再需要返回xml的系列化格式,那么直接在pom.xml文件中將jackson-dataformat-xml這外包排除即可(如果其他包也進(jìn)行了jackson-dataformat-xml的依賴(lài)引用也要視情況排除):第二種是:不排除jackson-dataformat-xml包,而是直接在相應(yīng)接口方法或Controller上明確指定將返回JSON格式的值:@GetMapping(value = "/user-instance", produces = MediaType.APPLICATION_PROBLEM_JSON_VALUE) --> <!-- 排除controller返回的格式為xml--><exclusions><exclusion><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId></exclusion></exclusions></dependency><!-- mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency> <!-- jdbc--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency> <!-- druid--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId></dependency> <!-- MyBatis-puls--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId></dependency><!-- 自己的實(shí)體類(lèi)--><dependency><groupId>com.fs</groupId><artifactId>fs-api-commons</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies> </project>application.yml
搭建集群provider集群就把 server.prot改下,吧defaultZone:多個(gè)地址用逗號(hào)隔開(kāi)
注意的是,域名記得在host文件中修改域名與端口的映射
FsProvider8001主啟動(dòng)
package com.fs;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@SpringBootApplication //開(kāi)啟Eureka客戶端 @EnableEurekaClient public class FsProvider8001 {public static void main(String[] args) {SpringApplication.run(FsProvider8001.class,args);} }PaymentController
package com.fs.controller;import com.fs.pojo.Payment; import com.fs.result.Result; import com.fs.service.PaymentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import java.util.List; import java.util.concurrent.TimeUnit;@RestController @RequestMapping("/payment") public class PaymentController {//注入業(yè)務(wù)層@Autowiredprivate PaymentService paymentService;@RequestMapping("/findAll")public Result<List<Payment>> findAll(){List<Payment> all = paymentService.findAll();return new Result<List<Payment>>(true,"查詢(xún)成功8001",all);}@RequestMapping("/testTimeOut")public Result test(){try {//讓方法停止2秒,模擬方法執(zhí)行時(shí)間過(guò)長(zhǎng),因?yàn)镽ibbon的超時(shí)時(shí)間默認(rèn)為1秒,超時(shí)就會(huì)報(bào)錯(cuò)TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}return new Result<List<Payment>>(true,"查詢(xún)成功");}}Consumer 創(chuàng)建 fs-consumer-80 消費(fèi)者 使用 RestTemplate 完成遠(yuǎn)程調(diào)用。
Resttemplate
? Spring提供的一種簡(jiǎn)單便捷的模板類(lèi),用于在 java 代碼里訪問(wèn) restful 服務(wù)。
? 其功能與 HttpClient 類(lèi)似,但是 RestTemplate 實(shí)現(xiàn)更優(yōu)雅,使用更方便。
pom.xml
<?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>study-springcloud</artifactId><groupId>com.fs</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>fs-consumer-80</artifactId><dependencies><!-- spring-boot-starter-web spring-boot-starter-actuator綁定在一塊 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- eureka-Client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><!-- 排除controller返回的格式為xml--><exclusions><exclusion><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId></exclusion></exclusions></dependency><!-- 自己的實(shí)體類(lèi)--><dependency><groupId>com.fs</groupId><artifactId>fs-api-commons</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies></project>application.yml
server:port: 80spring:application:name: fs-consumer-80 eureka:client:register-with-eureka: false # 消費(fèi)者我目前的用途不需要將消費(fèi)者注冊(cè)到注冊(cè)中心fetch-registry: true # 從注冊(cè)中心拉取服務(wù)registry-fetch-interval-seconds: 30 # 默認(rèn)30秒定時(shí)去注冊(cè)中心拉取服務(wù)service-url:defaultZone: http://localhost:7001/eureka #,http://localhost2:7002/eureka,http://localhost3:7003/eureka # 注冊(cè)中心地址# 配置的方式設(shè)置Ribbon的負(fù)載均衡 #FS-PROVIDER: # 設(shè)置的我們服務(wù)提供方的應(yīng)用名稱(chēng) # ribbon: # 固定寫(xiě)法 # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #負(fù)載均衡的規(guī)則,表示加權(quán)規(guī)則,yml配置優(yōu)先級(jí)第一,Java代碼第二,默認(rèn)的最后# 自定義屬性來(lái)存儲(chǔ)注冊(cè)中心 提供者的名字 provider:name: FS-PROVIDER主啟動(dòng) FsConsumer80
package com.fs;import com.fs.config.MyRule; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.ribbon.RibbonClient;@SpringBootApplication @EnableEurekaClient @EnableDiscoveryClient //激活發(fā)現(xiàn)客戶端 //開(kāi)啟客戶端負(fù)載均衡,不使用默認(rèn)的輪詢(xún), //name 設(shè)置我們這個(gè)負(fù)載均衡用于那個(gè)服務(wù)提供方 configuration 使用我們自定義的配置類(lèi)中配置的負(fù)載均衡 @RibbonClient(name = "FS-PROVIDER",configuration = MyRule.class) public class FsConsumer80 {public static void main(String[] args) {SpringApplication.run(FsConsumer80.class,args);} }MyRule 定義負(fù)載均衡策略
== Ribbon負(fù)載均衡器==
-
定義:解決客戶端的服務(wù)負(fù)載均衡算法處理器
-
功能:
- 負(fù)載均衡
- 簡(jiǎn)化遠(yuǎn)程調(diào)用過(guò)程
-
使用:
-
開(kāi)啟負(fù)載均衡功能(默認(rèn)輪詢(xún)策略)
@LoadBanlance -
修改主機(jī)名為服務(wù)名
http://服務(wù)名稱(chēng)/login
-
-
怎么修改負(fù)載均衡策略
-
注解方式
### xxx 是一個(gè)JavaConfig類(lèi),其中?配置使用的策略Bean @RibbonClient(name="",configuration = XXX.Class) -
配置方式
[服務(wù)名稱(chēng)1]:ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule [服務(wù)名稱(chēng)2]:ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.BestAvailableRule
-
MyRule
package com.fs.config;import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.RandomRule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;/* 編碼的方式設(shè)置 定義Ribbon負(fù)載均衡的配置類(lèi)注意:這個(gè)類(lèi)不能在@Configuration 下的@@ComponentScan掃描的包下因?yàn)?#64;SpringBootApplication這個(gè)注解定義為掃描被這個(gè)注解注解的類(lèi)的包及其子包所以,我們這個(gè)Ribbon負(fù)載均衡的配置類(lèi)就只能從新新建一個(gè)包,不在主配置類(lèi)包下及其子包就可以了這里配置為隨機(jī)后記得在主啟動(dòng)類(lèi)上加上一個(gè)注解@RibbonClient*/ @Configuration public class MyRule {@Beanpublic IRule myIRule(){//import com.netflix.loadbalancer.RandomRule;這個(gè)類(lèi)就就代表負(fù)載均衡為隨機(jī)//創(chuàng)建負(fù)載均衡的策略為隨機(jī)RandomRule randomRule = new RandomRule();return randomRule;} }RestTemplateConfig 注入RestTemplate
package com.fs.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate;/* 定義restTemplate*/ @Configuration public class RestTemplateConfig {@Bean//客戶端負(fù)載均衡@LoadBalanced //使用默認(rèn)的負(fù)載均衡輪詢(xún)public RestTemplate restTemplate(){return new RestTemplate();} }PaymentController 服務(wù)消費(fèi)者
package com.fs.controller;import com.fs.pojo.Payment; import com.fs.result.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate;import java.util.List;@RestController @RequestMapping("/consumer") public class PaymentController {//注入RestTemplate@Autowiredprivate RestTemplate restTemplate;//注入DiscoveryClient,動(dòng)態(tài)從eureka server 中獲取 provider 的host與ip@Autowiredprivate DiscoveryClient discoveryClient;// String host; // int port;// private String PAYMENT_URL ="http://"+host+ ":"+port;//從application.yml文件中讀取@Value("${provider.name}")private String providerName;@RequestMapping("/payment/findAll")public Result<List<Payment>> findAll(){//搭建集群后,使用服務(wù)名稱(chēng)做url,負(fù)載均衡的調(diào)用注冊(cè)中心的服務(wù)Result<List<Payment>> result = restTemplate.getForObject("http://"+providerName+"/payment/findAll", Result.class);return result;}// @RequestMapping("/payment/findAll") // public Result<List<Payment>> findAll(){ // //得到服務(wù)的實(shí)體,為什么是集合呢?因?yàn)槲磥?lái)的一個(gè)微服務(wù)名稱(chēng)是搭建集群的 // List<ServiceInstance> instances = discoveryClient.getInstances("FS-PROVIDER"); // String host = null; // int port = 0; // // if (instances.size()>0){ // //獲取第一個(gè) // ServiceInstance serviceInstance = instances.get(0); // //見(jiàn)名知意 // host = serviceInstance.getHost(); // port = serviceInstance.getPort(); // }else { // return null; // } // Result<List<Payment>> result = restTemplate.getForObject("http://"+host+":"+port+"/payment/findAll", Result.class); // result.setMessage(host+":"+port); // return result; // } }搭建 Eureka Server 服務(wù)。
pom.xml
<?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>study-springcloud</artifactId><groupId>com.fs</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>fs-server-eureka-7001</artifactId><dependencies><!-- eureka-server --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><!-- spring-boot-starter-web spring-boot-starter-actuator綁定在一塊 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies></project>application.yml
server:port: 7001 spring:application:name: fs-server-eureka-ha eureka:instance:hostname: localhost #主機(jī)名,域名,本機(jī)在host文件配置client:register-with-eureka: false # 是否將自己注冊(cè)到eureka,搭建繼續(xù)需要將eurekaserver注冊(cè)到注冊(cè)中心,相互注冊(cè)fetch-registry: false # 是否從EurekaServer抓取已有的注冊(cè)信息service-url:defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka# eureka集群 # client: # register-with-eureka: true # 是否將自己注冊(cè)到eureka,搭建繼續(xù)需要將eurekaserver注冊(cè)到注冊(cè)中心,相互注冊(cè) # fetch-registry: true # 是否從EurekaServer抓取已有的注冊(cè)信息 # service-url: # defaultZone: http://localhost2:7002/eureka,http://localhost3:7003/eureka # server: # enable-self-preservation: false # 默認(rèn)true 開(kāi)啟自我保護(hù)機(jī)制,但是開(kāi)發(fā)中可以關(guān)掉,方便開(kāi)發(fā),實(shí)際生產(chǎn)一定使用默認(rèn)的true # eviction-interval-timer-in-ms: 3000 #默認(rèn)60秒主啟動(dòng) ServerEureka7001
package com.fs;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication //開(kāi)啟eureka的服務(wù) @EnableEurekaServer public class ServerEureka7001 {public static void main(String[] args) {SpringApplication.run(ServerEureka7001.class,args);} }測(cè)試Eureka – 搭建服務(wù)
啟動(dòng)ServerEureka7001
啟動(dòng)FsProvider8001
啟動(dòng)FsConsumer80
瀏覽器分別打開(kāi):
http://localhost:7001/
http://localhost:8001/payment/findAll
http://localhost/consumer/payment/findAll
通過(guò)消費(fèi)端使用RestTemplate遠(yuǎn)程調(diào)用我們的服務(wù)提供者
Eureka – 相關(guān)配置及特性
- instance
eureka:instance:hostname: localhost # 主機(jī)名client:service-url:defaultZone: http://localhost:8761/eureka # eureka服務(wù)端地址,將來(lái)客戶端使用該地址和eureka進(jìn)行通信register-with-eureka: true # 是否將自己的路徑 注冊(cè)到eureka上。eureka server 不需要的,eureka provider client 需要fetch-registry: true # 是否需要從eureka中抓取路徑。eureka server 不需要的,eureka consumer client 需要- server
eureka:server:#是否開(kāi)啟自我保護(hù)機(jī)制,默認(rèn)trueenable-self-preservation:#清理間隔(單位毫秒,默認(rèn)是60*1000)eviction-interval-timer-in-ms:instance:lease-renewal-interval-in-seconds: 30 # 每一次eureka client 向 eureka server發(fā)送心跳的時(shí)間間隔lease-expiration-duration-in-seconds: 90 # 如果90秒內(nèi)eureka server沒(méi)有收到eureka client的心跳包,則剔除該服務(wù)- client
eureka:client:service-url:# eureka服務(wù)端地址,將來(lái)客戶端使用該地址和eureka進(jìn)行通信defaultZone:register-with-eureka: # 是否將自己的路徑 注冊(cè)到eureka上。fetch-registry: # 是否需要從eureka中抓取數(shù)據(jù)。- dashboard
eureka:dashboard:enabled: true # 是否啟用eureka web控制臺(tái)path: / # 設(shè)置eureka web控制臺(tái)默認(rèn)訪問(wèn)路徑Consul客戶端配置(了解,不常用)
- 服務(wù)ip和地址
- 服務(wù)名稱(chēng)
換湯不換藥,總的使用差不多
? Consul 是由 HashiCorp 基于 Go 語(yǔ)言開(kāi)發(fā)的,支持多數(shù)據(jù)中心,分布式高可用的服務(wù)發(fā)布和注冊(cè)服務(wù)軟件。
? 用于實(shí)現(xiàn)分布式系統(tǒng)的服務(wù)發(fā)現(xiàn)與配置。
? 使用起來(lái)也較 為簡(jiǎn)單。具有天然可移植性(支持Linux、windows和Mac OS X);安裝包僅包含一個(gè)可執(zhí)行文件,
方便部署 。
? 官網(wǎng)地址: https://www.consul.io
OpenFeign
什么是Feign
-
定義:是微服務(wù)之間通過(guò)http協(xié)議調(diào)用的簡(jiǎn)化使用的框架
-
事實(shí):
- Feign自動(dòng)集成Ribbon,且默認(rèn)開(kāi)啟相關(guān)功能
-
使用:
-
導(dǎo)包
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> -
配置
ribbon:ConnectTimeout: 1000 # 連接超時(shí)時(shí)間 默認(rèn)1sReadTimeout: 3000 # 邏輯處理的超時(shí)時(shí)間 默認(rèn)1s
這個(gè)配置信息可以在springboot的項(xiàng)目idea按兩下shitf,輸入feign**properties(****properties)這樣的類(lèi)中都可以發(fā)現(xiàn)這個(gè)類(lèi)有哪些配置可以在yml配置文件中配置 -
編碼
-
開(kāi)啟Feign功能
@EnableFeignClients -
編寫(xiě)Feign接口
// 指定當(dāng)前類(lèi)的方法都從Eureka中對(duì)應(yīng)的服務(wù)去調(diào)用 @FeignClient("服務(wù)的名稱(chēng)") public interface ProviderService {// 通過(guò)Controller的地址映射注解告訴Feign該類(lèi)findOne2方法從服務(wù)提供者的/findOne/{id}地址獲取信息// 通過(guò)Controller的參數(shù)獲取注解告訴Feign的參數(shù)信息// 通過(guò)返回值告訴Feign應(yīng)該返回的參數(shù)應(yīng)該封裝的格式@GetMapping("/goods/findOne/{id}")public Goods findOne(@PathVariable("id") int id);}
-
-
SpringBoot開(kāi)啟DEBUG日志
-
開(kāi)啟SpringBoot框架的DEBUG日志
-
開(kāi)啟全部
# 設(shè)置當(dāng)前的日志級(jí)別 debug,feign只支持記錄debug級(jí)別的日志 logging:level:root: debug -
開(kāi)啟部分
logging:level:com.fs: debug
-
-
開(kāi)啟Feign的日志
-
必須開(kāi)啟對(duì)應(yīng)Feign接口包的日志為DEBUG
-
編碼
-
定義日志級(jí)別
@Configuration public class FeignLogConfig {/*NONE,不記錄BASIC,記錄基本的請(qǐng)求行,響應(yīng)狀態(tài)碼數(shù)據(jù)HEADERS,記錄基本的請(qǐng)求行,響應(yīng)狀態(tài)碼數(shù)據(jù),記錄響應(yīng)頭信息FULL;記錄完成的請(qǐng)求 響應(yīng)數(shù)據(jù)*/@Beanpublic Logger.Level level(){return Logger.Level.FULL;} } -
配置生效
@FeignClient(value = "FEIGN-PROVIDER",configuration = FeignLogConfig.class)
-
-
Nacos客戶端配置 基于OpenFeign遠(yuǎn)程調(diào)用(代碼中詳細(xì)注釋)
? Nacos(Dynamic Naming and Configuration Service) 是阿里巴巴2018年7月開(kāi)源的項(xiàng)目。
? 它專(zhuān)注于服務(wù)發(fā)現(xiàn)和配置管理領(lǐng)域 致力于幫助您發(fā)現(xiàn)、配置和管理微服務(wù)。Nacos 支持幾乎所有主流類(lèi)型的“服務(wù)”的發(fā)現(xiàn)、配置和管理。
? 一句話概括就是Nacos = Spring Cloud注冊(cè)中心 + Spring Cloud配置中心。
? 官網(wǎng):https://nacos.io/
? 下載地址: https://github.com/alibaba/nacos/releases
docker安裝nacos
#1.3.2 # 創(chuàng)建 /home/dockerdata/nacos/logs目錄用于掛載# 拉取nacos鏡像 docker pull nacos/nacos-server:1.3.2 # 運(yùn)行容器 這里面的sql語(yǔ)句需要在github的nacos中去拷貝執(zhí)行 執(zhí)行成功后訪問(wèn)ip:端口/nacos docker run -d \ -e PREFER_HOST_MODE=ip \ -e MODE=standalone \ -e SPRING_DATASOURCE_PLATFORM=mysql \ -e MYSQL_SERVICE_HOST=47.112.174.148 \ -e MYSQL_SERVICE_PORT=3306 \ -e MYSQL_SERVICE_USER=root \ -e MYSQL_SERVICE_PASSWORD=root \ -e MYSQL_SERVICE_DB_NAME=nacos \ -e TIME_ZONE='Asia/Shanghai' \ -v /docker/dockerdata/nacos/logs:/home/nacos/logs \ -p 8848:8848 \ --name nacos1.3.2 \ --restart=always \ nacos/nacos-server:1.3.2# 意思 docker run -d \ -e PREFER_HOST_MODE=hostname \ -e MODE=standalone \ -e SPRING_DATASOURCE_PLATFORM=mysql \ -e MYSQL_MASTER_SERVICE_HOST=數(shù)據(jù)庫(kù)ip \ -e MYSQL_MASTER_SERVICE_PORT=數(shù)據(jù)庫(kù)端口 \ -e MYSQL_MASTER_SERVICE_USER=用戶名 \ -e MYSQL_MASTER_SERVICE_PASSWORD=密碼 \ -e MYSQL_MASTER_SERVICE_DB_NAME=對(duì)應(yīng)的數(shù)據(jù)庫(kù)名 \ -e MYSQL_SLAVE_SERVICE_HOST=從數(shù)據(jù)庫(kù)ip \ -p 8848:8848 \ --name nacos-sa-mysql \ --restart=always \ nacos/nacos-server使用上面的父項(xiàng)目搭建
fs-provider-nacos-8001 服務(wù)提供端
pom.xml
<?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>study-springcloud</artifactId><groupId>com.fs</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>fs-provider-nacos-8001</artifactId><dependencies><!-- springcloud alibaba nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--這兩個(gè)spring-cloud-starter-alibaba-nacos-discovery都可以--><!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-alibaba-nacos-discovery --> <!-- <dependency>--> <!-- <groupId>org.springframework.cloud</groupId>--> <!-- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>--> <!-- <version>0.9.0.RELEASE</version>--> <!-- </dependency>--><!-- https://mvnrepository.com/artifact/com.alibaba.nacos/nacos-client --><dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId><version>1.3.2</version></dependency><!-- spring-boot-starter-web spring-boot-starter-actuator綁定在一塊 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- jdbc--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!-- druid--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId></dependency><!-- MyBatis-puls--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId></dependency><!-- 自己的實(shí)體類(lèi)--><dependency><groupId>com.fs</groupId><artifactId>fs-api-commons</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies></project>application.yml
server:port: 8001 spring:application:name: fs-provider-nacosdatasource:username: rootpassword: rooturl: jdbc:mysql://192.168.93.132:3306/fs_springclouddriver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource #自定義數(shù)據(jù)源# 將服務(wù)提供者注冊(cè)到nacos注冊(cè)中心cloud:nacos:discovery:server-addr: 192.168.93.132:8848 # 配置nacos 服務(wù)端地址# 配置MyBatis-plus日志 mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl主啟動(dòng) FsNacosProvider8001
package com.fs;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class FsNacosProvider8001 {public static void main(String[] args) {SpringApplication.run(FsNacosProvider8001.class,args);} }PaymentController 服務(wù)提供controller
package com.fs.controller;import com.fs.pojo.Payment; import com.fs.result.Result; import com.fs.service.PaymentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import java.util.List; import java.util.concurrent.TimeUnit;@RestController @RequestMapping("/payment") public class PaymentController {//注入業(yè)務(wù)層@Autowiredprivate PaymentService paymentService;@RequestMapping("/findAll")public Result<List<Payment>> findAll(){List<Payment> all = paymentService.findAll();return new Result<List<Payment>>(true,"查詢(xún)成功nacos8001",all);}@RequestMapping("/testTimeOut")public Result test(){try {//讓方法停止2秒,模擬方法執(zhí)行時(shí)間過(guò)長(zhǎng),因?yàn)镽ibbon的超時(shí)時(shí)間默認(rèn)為1秒,超時(shí)就會(huì)報(bào)錯(cuò)TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}return new Result<List<Payment>>(true,"查詢(xún)成功");} }fs-consumer-nacos-80 服務(wù)消費(fèi)端
pom.xml
<?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>study-springcloud</artifactId><groupId>com.fs</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>fs-consumer-nacos-80</artifactId><dependencies><!-- springcloud alibaba nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--這兩個(gè)spring-cloud-starter-alibaba-nacos-discovery都可以--><!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-alibaba-nacos-discovery --><!-- <dependency>--><!-- <groupId>org.springframework.cloud</groupId>--><!-- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>--><!-- <version>0.9.0.RELEASE</version>--><!-- </dependency>--><!-- https://mvnrepository.com/artifact/com.alibaba.nacos/nacos-client --><dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId><version>1.3.2</version></dependency><!-- openFeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!-- spring-boot-starter-web spring-boot-starter-actuator綁定在一塊 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 自己的實(shí)體類(lèi)--><dependency><groupId>com.fs</groupId><artifactId>fs-api-commons</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies></project>application.yml
server:port: 80spring:application:name: fs-consumer-nacoscloud:nacos:discovery:server-addr: 192.168.93.132:8848 # 配置nacos 服務(wù)端地址logging:level:# root: debug # 開(kāi)啟springboot的debug的日志信息,不配置springboot默認(rèn)是info# com.fs: debug # 開(kāi)啟部分springboot的debug的日志信息# feign日志以什么級(jí)別監(jiān)控那個(gè)feign組件功能使用的接口,使用debug級(jí)別(只能記錄debug級(jí)別),然后調(diào)用服務(wù)方法,在控制臺(tái)就能看到詳細(xì)debug信息com.fs.springcloud.server.PaymentOpenFeignService: debug主啟動(dòng) FsNacosConsumer80
package com.fs;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication //開(kāi)啟OpenFeign @EnableFeignClients public class FsNacosConsumer80 {public static void main(String[] args) {SpringApplication.run(FsNacosConsumer80.class,args);} }OpenFeignConfig
package com.fs.config;import feign.Logger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;/* OpenFeign的日志配置類(lèi)*/ @Configuration public class OpenFeignConfig {@BeanLogger.Level feignLoggerLevel(){//表示開(kāi)啟的是詳細(xì)的feign日志,FULL表示最為詳細(xì)的,點(diǎn)進(jìn)去有4個(gè)return Logger.Level.FULL;}//還需要在yml中配置feign日志已什么級(jí)別監(jiān)控那個(gè)接口 }PaymentOpenFeign 為OpenFeign的接口
package com.fs.feign;import com.fs.config.OpenFeignConfig; import com.fs.pojo.Payment; import com.fs.result.Result; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping;import java.util.List; /*** feign的聲明式接口,發(fā)起遠(yuǎn)程調(diào)用的,簡(jiǎn)化restTemplate** 1.定義接口* 2.接口上添加注解@FeignClient(value = "注冊(cè)中心服務(wù)提供者名",configuration=定義的OpenFeign的日志類(lèi))* 3.編寫(xiě)調(diào)用接口,接口的聲明規(guī)則和提供方接口保持一致* 4.去controller注入改接口對(duì)象,調(diào)用接口方法來(lái)完成遠(yuǎn)程調(diào)用*/ @FeignClient(value = "fs-provider-nacos",configuration = OpenFeignConfig.class) public interface PaymentOpenFeign {//復(fù)制服務(wù)提供的controller方法,路徑記得加上controller類(lèi)上的路徑@RequestMapping("/payment/findAll")Result<List<Payment>> findAll();//測(cè)試time超時(shí),由于我們?cè)诜?wù)提供方的這個(gè)方法制作了sleep2秒,由于feign底層基于Ribbon,//Ribbon默認(rèn)超時(shí)時(shí)間為1秒,所以報(bào)錯(cuò)java.net.SocketTimeoutException: Read timed out//解決辦法在配置文件中配置Ribbon的超時(shí)時(shí)間@RequestMapping("/payment/testTimeOut")Result test(); }PaymentController 使用OpenFeign遠(yuǎn)程調(diào)用服務(wù)提供者
package com.fs.controller;import com.fs.feign.PaymentOpenFeign; import com.fs.pojo.Payment; import com.fs.result.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController @RequestMapping("/consumer") public class PaymentController {//注入OpenFeign接口@Autowiredprivate PaymentOpenFeign paymentOpenFeign;@RequestMapping("/payment/findAll")public Result<List<Payment>> findAll(){//調(diào)用OpenFeign接口Result<List<Payment>> all = paymentOpenFeign.findAll();return all;}//測(cè)試time超時(shí)@RequestMapping("/payment/testTimeOut")Result test(){Result test = paymentOpenFeign.test();return test;}}測(cè)試nacos
首先確保docker的nacos正常運(yùn)行且能正常訪問(wèn)
運(yùn)行:
FsNacosProvider8001
運(yùn)行:
FsNacosConsumer80
瀏覽器訪問(wèn)nacos查看服務(wù)是否注冊(cè)
直接訪問(wèn)服務(wù)提供接口,與使用消費(fèi)者端遠(yuǎn)程調(diào)用服務(wù)提供接口
總結(jié)
以上是生活随笔為你收集整理的SpringCloud微服务架构,Spring Cloud 服务治理(Eureka,Consul,Nacos),Ribbon 客户端负载均衡,RestTemplate与OpenFeign实现远程调用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 浅谈:Spring Boot原理分析,切
- 下一篇: SpringCloud微服务架构之,Hy