目錄
RestTemplate方式調用存在的問題:
定義和使用Feign客戶端
自定義Feign的配置
性能優化
Feign的最佳實踐
Feign的使用步驟:
1、引入依賴
2、添加@EnableFeignClients注解3、編寫FeignClient接口
4、使用FeignClient中定義的方法代替RestTemplate
?Feign的日志配置:
1、方式一是配置文件,feign.client.config.xxx.loggerLevel
①如果xxx是default則代表全局
②如果xxx是服務名稱,例如userservice則代表某服務2、方式二是java代碼配置Logger.Level這個Bean
①如果在@EnableFeignClients注解聲明則代表全局②如果在@FeignClient注解中聲明則代表某服務
?Feign的優化:命
1、日志級別盡量用basic
2、使用Httpclient或OKHttp代替URLConnection
????????引入feign-httpClient依賴
????????配置文件開啟httpClient功能,設置連接池參數Feign的最佳實踐:
1、讓controller和FeignClient繼承同一接口
2、將FeignClient、POJO、Feign的默認配置都定義到一個項目中,供所有消費者使用不同包的FeignClient的導入有兩種方式:
1、在@EnableFeignClients注解中添加basePackages,指定FeignClient所在的包
2、在@EnableFeignClients注解中添加clients,指定具體Feignclient的字節碼
?
RestTemplate方式調用存在的問題:
string url = "http: //userservice/user/" + order.getUserId();
User user = restTemplate.getFor0bject(url,User.class);
存在下面的問題:
代碼可讀性差,編程體驗不統一
參數復雜URL難以維護
定義和使用Feign客戶端
1.引入依賴:
在orderservice的pom文件引入依賴
<!--feign客戶端依賴--> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
<?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>cloud-demo</artifactId><groupId>cn.itcast.demo</groupId><version>1.0</version></parent><modelVersion>4.0.0</modelVersion><artifactId>order-service</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><!--eureka客戶依賴-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
<!-- </dependency>--><!-- nacos客戶端依賴包 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--feign客戶端依賴--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
2.在order-service的啟動類添加注解開啟Feign的功能:
在orderservice的啟動類中添加注解
@EnableFeignClients
package cn.itcast.order;import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}//創建RestTemplate并注入Spring容器@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}// @Bean
// public IRule randomRule(){
// return new RandomRule();//將負載均衡設置為隨機,范圍為整個order
// }
}
3.編寫Feign客戶端:
添加一個包,并寫一個接口,再引入客戶端注解FeignClient
package cn.itcast.order.clients;import cn.itcast.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient("userservice")
public interface UserClient {@GetMapping("/user/{id}")User findById(@PathVariable("id") Long id);
}
4、改造orderservice的service.java文件,把以前寫的RestTemplate方式換成Feign方式
package cn.itcast.order.service;import cn.itcast.order.clients.UserClient;
import cn.itcast.order.mapper.OrderMapper;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate UserClient userClient;public Order queryOrderById(Long orderId) {// 1.查詢訂單Order order = orderMapper.findById(orderId);// 2.用Feign遠程調用// 2.1.url路徑User user = userClient.findById(order.getUserId());// 3.封裝user到orderorder.setUser(user);// 4.返回return order;}// @Autowired
// private RestTemplate restTemplate;
//
// public Order queryOrderById(Long orderId) {
// // 1.查詢訂單
// Order order = orderMapper.findById(orderId);
// // 2.利用RestTemplate發送http請求,查詢用戶
// // 2.1.url路徑
// String url = "http://userservice/user/" + order.getUserId();
// // 2.2.發送http請求,實現遠程調用
// User user = restTemplate.getForObject(url, User.class);//第一個參數是路徑,第二個參數是返回的類=類型
// // 3.封裝user到order
// order.setUser(user);
// // 4.返回
// return order;
// }
}
訪問數據,可以發現:兩個userservice都能訪問,并且是負載均衡的
自定義Feign的配置
方式一:配置文件方式,在orderservice的application.yml文件添加
1、全局生效:
feign:client:config:default: #這里填default是全局生效,填服務名就是局部生效loggerLevel: FULL #顯示完整信息
server:port: 8080
spring:datasource:url: jdbc:mysql://localhost:3306/cloud_order?useSSL=falseusername: rootpassword: 1234driver-class-name: com.mysql.jdbc.Driverapplication:name: orderservice #order的微服務名稱cloud:nacos:server-addr: localhost:8848
# discovery:
# cluster-name: HZ #集群名稱
# namespace: 8279562b-ce89-420a-b765-f8b2adfdbe49 #命名空間id
# ephemeral: false #是否為臨時實例
mybatis:type-aliases-package: cn.itcast.user.pojoconfiguration:map-underscore-to-camel-case: true
logging:level:cn.itcast: debugpattern:dateformat: MM-dd HH:mm:ss:SSS
#eureka:
# client:
# service-url: #eureka地址信息1
# defaultZone: http://127.0.0.1:10086/eureka
userservice:ribbon:NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule #負載均衡規則:隨機。范圍:userservice服務
ribbon:eager-load:enabled: true #開啟饑餓加載clients: #指定饑餓加載的服務- userservice
feign:client:config:default: #這里填default是全局生效,填服務名就是局部生效loggerLevel: FULL #顯示完整信息
?可以看到只是訪問一次數據,就有很多信息
2、局部生效:?
feign:client:config:userservice: #這里填default是全局生效,填服務名就是局部生效loggerLevel: FULL #顯示完整信息
方式二: java代碼方式,需要先聲明一個Bean:
先把方式一的代碼注釋掉
#feign: # client: # config: # default: #這里填default是全局生效,填服務名就是局部生效 # loggerLevel: FULL #顯示完整信息
server:port: 8080
spring:datasource:url: jdbc:mysql://localhost:3306/cloud_order?useSSL=falseusername: rootpassword: 1234driver-class-name: com.mysql.jdbc.Driverapplication:name: orderservice #order的微服務名稱cloud:nacos:server-addr: localhost:8848
# discovery:
# cluster-name: HZ #集群名稱
# namespace: 8279562b-ce89-420a-b765-f8b2adfdbe49 #命名空間id
# ephemeral: false #是否為臨時實例
mybatis:type-aliases-package: cn.itcast.user.pojoconfiguration:map-underscore-to-camel-case: true
logging:level:cn.itcast: debugpattern:dateformat: MM-dd HH:mm:ss:SSS
#eureka:
# client:
# service-url: #eureka地址信息1
# defaultZone: http://127.0.0.1:10086/eureka
userservice:ribbon:NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule #負載均衡規則:隨機。范圍:userservice服務
ribbon:eager-load:enabled: true #開啟饑餓加載clients: #指定饑餓加載的服務- userservice
#feign:
# client:
# config:
# default: #這里填default是全局生效,填服務名就是局部生效
# loggerLevel: FULL #顯示完整信息
先添加一個包config,再添加一個DefaultFeignConfiguration.java
package cn.itcast.order.config;import feign.Logger;
import org.springframework.context.annotation.Bean;public class DefaultFeignConfiguration {@Beanpublic Logger.Level logLevel(){return Logger.Level.BASIC;}
}
1、如果是全局配置,則把它放到@EnableFeignClients這個注解中:
@EnableFeignClients(defaultConfiguration = FeignclientConfiguration.class)
添加在啟動類上:
package cn.itcast.order;import cn.itcast.order.config.DefaultFeignConfiguration;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class)
public class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}//創建RestTemplate并注入Spring容器@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}// @Bean
// public IRule randomRule(){
// return new RandomRule();//將負載均衡設置為隨機,范圍為整個order
// }
}
請求數據,可以看到比起方式一,這種方式的信息簡潔許多。因為第一種方式用的FULL,而第二種方式是BASIC
2、如果是局部配置,則把它放到@FeignClient這個注解中:
@FeignClient(value = "userservice", configuration = FeignClientConfiguration.class)?
添加在UserClient.interface上,這里就不再做演示了。
性能優化
Feign添加HttpClient的支持:
引入依賴
<!--引入httpClient依賴--> <dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId> </dependency>
配置連接池
feign:httpclient:enabled: true #支持httpclient的開關max-connections: 200 #最大連接數max-connections-per-route: 50 #單個請求路徑的最大連接數
server:port: 8080
spring:datasource:url: jdbc:mysql://localhost:3306/cloud_order?useSSL=falseusername: rootpassword: 1234driver-class-name: com.mysql.jdbc.Driverapplication:name: orderservice #order的微服務名稱cloud:nacos:server-addr: localhost:8848
# discovery:
# cluster-name: HZ #集群名稱
# namespace: 8279562b-ce89-420a-b765-f8b2adfdbe49 #命名空間id
# ephemeral: false #是否為臨時實例
mybatis:type-aliases-package: cn.itcast.user.pojoconfiguration:map-underscore-to-camel-case: true
logging:level:cn.itcast: debugpattern:dateformat: MM-dd HH:mm:ss:SSS
#eureka:
# client:
# service-url: #eureka地址信息1
# defaultZone: http://127.0.0.1:10086/eureka
userservice:ribbon:NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule #負載均衡規則:隨機。范圍:userservice服務
ribbon:eager-load:enabled: true #開啟饑餓加載clients: #指定饑餓加載的服務- userservice
feign:httpclient:enabled: true #支持httpclient的開關max-connections: 200 #最大連接數max-connections-per-route: 50 #單個請求路徑的最大連接數
Feign的最佳實踐
方式一(繼承)︰給消費者的FeignClient和提供者的controller定義統一的父接口作為標準。
方式二(抽取)︰將FeignClient抽取為獨立模塊,并且把接口有關的POJO、默認的Feign配置都放到這個模塊中,提供給所有消費者使用
這里我只實現方式二
1.首先創建一個module,命名為feign-api,然后引入feign的starter依賴
<!--引入feign依賴--> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
<?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>cloud-demo</artifactId><groupId>cn.itcast.demo</groupId><version>1.0</version></parent><modelVersion>4.0.0</modelVersion><artifactId>feign-api</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency></dependencies></project>
2.將order-service中編寫的UserClient、User、DefaultFeignConfiguration都剪切到feign-api項目中
因為這些代碼移到其他模塊了,所以會報錯
①UserClient的User報錯,重新導包,用feign包內的User
②Orderservice的Order依賴User報錯,在pom文件引入依賴,并重新導包,用feign模塊的包
<!--引入feign的統一依賴--> <dependency><groupId>cn.itcast.demo</groupId><artifactId>feign-api</artifactId><version>1.0</version> </dependency>
<?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>cloud-demo</artifactId><groupId>cn.itcast.demo</groupId><version>1.0</version></parent><modelVersion>4.0.0</modelVersion><artifactId>order-service</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><!--eureka客戶依賴-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
<!-- </dependency>--><!-- nacos客戶端依賴包 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--feign客戶端依賴--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--引入httpClient依賴--><dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId></dependency><!--引入feign的統一依賴--><dependency><groupId>cn.itcast.demo</groupId><artifactId>feign-api</artifactId><version>1.0</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
③Orderservice的Orderservice報錯,重新導入feign模塊下的包
④Orderservice的啟動類報錯,導入feign模塊的包
⑤當定義的FeignClient不在SpringBootApplication的掃描包范圍時,這些FeignClient無法使用。
有兩種方式解決:
方式一:指定FeignClient所在包
@EnableFeignclients(basePackages = "cn.itcast.feign.clients")
方式二:指定Feignclient字節碼
@EnableFeignclients(clients = {Userclient.class})?
在order的啟動類的EnableFeignclients加一個屬性
@EnableFeignClients(clients = UserClient.class, defaultConfiguration = DefaultFeignConfiguration.class)
我這里使用第一個方式?
package cn.itcast.order;import cn.itcast.feign.clients.UserClient;
import cn.itcast.feign.config.DefaultFeignConfiguration;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
@EnableFeignClients(clients = UserClient.class, defaultConfiguration = DefaultFeignConfiguration.class)
public class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}//創建RestTemplate并注入Spring容器@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}// @Bean
// public IRule randomRule(){
// return new RandomRule();//將負載均衡設置為隨機,范圍為整個order
// }
}
訪問數據,請求成功
代碼文件點擊下載https://pan.baidu.com/s/1GooYipFzcnCyubANjf5S6Q?pwd=vpea上一篇:Nacos配置管理