微服務(wù)調(diào)用方式之Ribbon
Ribbon簡(jiǎn)介
Ribbon是Netflix發(fā)布的云中間層服務(wù)開源項(xiàng)目,其主要功能是提供客戶端實(shí)現(xiàn)負(fù)載均衡算法。Ribbon客戶端組件提供一系列完善的配置項(xiàng)如連接超時(shí),重試等葵袭。簡(jiǎn)單的說(shuō)沉颂,Ribbon是一個(gè)客戶端負(fù)載均衡器,我們可以在配置文件中Load Balancer后面的所有機(jī)器独泞,Ribbon會(huì)自動(dòng)的幫助你基于某種規(guī)則(如簡(jiǎn)單輪詢,隨機(jī)連接等)去連接這些機(jī)器苔埋,我們也很容易使用Ribbon實(shí)現(xiàn)自定義的負(fù)載均衡算法懦砂。
Ribbon的使用
通過(guò)IDEA創(chuàng)建項(xiàng)目并引入依賴<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yuan</groupId>
<artifactId>order_service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>order_service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
向注冊(cè)中心注冊(cè)服務(wù)(application.yml)
server:
port: 8781
#指定注冊(cè)中心地址
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
#服務(wù)的名稱
spring:
application:
name: order-service
使用Ribbon
啟動(dòng)類中加入如下代碼:
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
使用添加@LoadBalanced注解后的RestTemplate調(diào)用服務(wù)提供者的接口時(shí),可以使用虛擬IP替代真實(shí)IP地址组橄。所謂的虛擬IP就是服務(wù)提供者在application.yml文件中配置的spring.application.name屬性的值荞膘。示例如下:(調(diào)用上篇文章中的)
@RestController
@RequestMapping("api/v1/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
//調(diào)用方式二
@Autowired
private LoadBalancerClient loadBalancer;
@RequestMapping("save")
public Object save(@RequestParam("user_id") int userId,@RequestParam("product_id") int productId){
Object obj=restTemplate.getForObject("http://product-service/api/v1/product/findById?id="+productId,Object.class);
//調(diào)用方式二
//ServiceInstance instance = loadBalancer.choose("product-service");
//String url = String.format("http://%s:%s/api/v1/product/find?id="+productId, instance.getHost(),instance.getPort());
// RestTemplate restTemplate = new RestTemplate();
// Map<String,Object> productMap = restTemplate.getForObject(url, Map.class);
return obj;
}
}
啟動(dòng)注冊(cè)中心 服務(wù)提供者和消費(fèi)者調(diào)用url進(jìn)行測(cè)試
修改負(fù)載均衡策略(IRule實(shí)現(xiàn)類全路徑)
文檔:http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/single/spring-cloud.html#_customizing_the_ribbon_client_by_setting_properties
#自定義負(fù)載均衡策略
product-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
如果部分機(jī)器配置強(qiáng),則可以改為 WeightedResponseTimeRule
微服務(wù)調(diào)用方式之feign
Ribbon簡(jiǎn)介
Feign是Netflix開發(fā)的聲明式玉工、模塊化的HTTP客戶端羽资,其靈感來(lái)自Retrofit、JAXRS-2.0以及WebSocket遵班。Feign可幫組我們更加便捷屠升、優(yōu)雅的調(diào)用HTTP API潮改。
在Spring Cloud中,使用Feign非常簡(jiǎn)單——?jiǎng)?chuàng)建一個(gè)接口腹暖,并在接口上添加一些注解汇在,代碼就完成了。Feign支持多種注解脏答,例如Feign自帶的注解或者JAX-RS注解等糕殉。
配置Feign
引入依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
啟動(dòng)類增加注解@EnableFeignClients
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
yml配置:
server:
port: 8781
#指定注冊(cè)中心地址
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
#服務(wù)的名稱
spring:
application:
name: order-service
#修改調(diào)用超時(shí)時(shí)間
feign:
client:
config:
default:
connectTimeout: 2000
readTimeout: 2000
Feign的使用
@FeignClient(name = "product-service")
public interface ProductClient {
@GetMapping("/api/v1/product/find")
String findById(@RequestParam(value = "id") int id);
}
上面是最簡(jiǎn)單的feign client的使用,聲明完為feign client后殖告,其他spring管理的類阿蝶,如service就可以直接注入使用了,例如:
@Autowired
private ProductClient productClient;
@Override
public ProductOrder save(int userId, int productId) {
String response = productClient.findById(productId);
JsonNode jsonNode = JsonUtils.str2JsonNode(response);
ProductOrder productOrder = new ProductOrder();
productOrder.setCreateTime(new Date());
productOrder.setUserId(userId);
productOrder.setTradeNo(UUID.randomUUID().toString());
productOrder.setProductName(jsonNode.get("name").toString());
productOrder.setPrice(Integer.parseInt(jsonNode.get("price").toString()));
return productOrder;
}
可以看到黄绩,使用feign之后羡洁,我們調(diào)用eureka 注冊(cè)的其他服務(wù),在代碼中就像各個(gè)service之間相互調(diào)用那么簡(jiǎn)單爽丹。
Feign Client開啟日志
方式一:通過(guò)java bean的方式指定
@EnableFeignClients注解上有個(gè)defaultConfiguration屬性焚廊,可以指定默認(rèn)Feign Client的一些配置。
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class)
@SpringBootApplication
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args);
}
}
@Configuration
public class DefaultFeignConfiguration {
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.BASIC;
}
}
方式二:通過(guò)配置文件指定
logging:
level:
com.xt.open.jmall.product.remote.feignclients.CartFeignClient: debug
Feign原理簡(jiǎn)述
- 啟動(dòng)時(shí)习劫,程序會(huì)進(jìn)行包掃描咆瘟,掃描所有包下所有@FeignClient注解的類,并將這些類注入到spring的IOC容器中诽里。當(dāng)定義的Feign中的接口被調(diào)用時(shí)袒餐,通過(guò)JDK的動(dòng)態(tài)代理來(lái)生成RequestTemplate。
- RequestTemplate中包含請(qǐng)求的所有信息谤狡,如請(qǐng)求參數(shù)灸眼,請(qǐng)求URL等。
- RequestTemplate聲場(chǎng)Request墓懂,然后將Request交給client處理焰宣,這個(gè)client默認(rèn)是JDK的HTTPUrlConnection,也可以是OKhttp捕仔、Apache的HTTPClient等匕积。
- 最后client封裝成LoadBaLanceClient,結(jié)合ribbon負(fù)載均衡地發(fā)起調(diào)用榜跌。