SpringCloud使用Ribbon和Feign组件
注意:在SpringCloud已经整合Eureka的基础上
1、添加依赖
注意:Eureka-client中已经包含ribbon相关的包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、第一种方式:使用RestTemplate
- 类似于HttpClient
- RestTemplate 远程调用模板类,作用类似于HTTPClient
- @LoadBalanced 表示当前调用使用负载均衡
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
2、修改Controller类
@RequestMapping("/")
public String hello(@RequestParam String name) {
name += "!";
String url = "http://eureka-producer/hello/?name=" + name;
return restTemplate.getForObject(url, String.class);
}
3、第二种、使用LoadBalancerClient和RestTemplate实现调用
配置类注入RestTemplate
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
控制类中使用
- LoadBalancerClient 负载均衡客户端
- ServiceInstance 服务实例
- RestTemplate 远程调用模板
@RestController
@RequestMapping("/hello")
public class HelloController {
//注入负载均衡客户端
@Autowired
private LoadBalancerClient client;
@Autowired
private RestTemplate restTemplate; //使用声明式服务调用
@GetMapping("/")
public String hello(@RequestParam String name) {
name += "!";
ServiceInstance instance = client.choose("eureka-producer");
String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/hello/?name=" + name;
return restTemplate.getForObject(url, String.class);
}
}
4、第三种方式,使用注解方式
1、启动类上添加注解
- @EnableEurekaClient 表示当前项目是EurekaClient
- @EnableFeignClients 用于启动Fegin功能
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class EurekaConsumerFeignApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerFeignApplication.class, args);
}
}
2、添加调用接口(推荐使用,减少硬编码)
- @FeignClient(name = “eureka-producer”) 定义该接口是服务调用接口
- 接口方法中设置类似于Controller
@FeignClient(name = "eureka-producer")
public interface HelloRemote {
@GettingMapping("/hello/")
String hello(@RequestParam(value = "name") String name);
}
4、编写Controller类
业务调用可以通过HelloRemote接口实现调用
- @RestController 后端必须用这个
@RequestMapping("/hello")
@RestController
public class HelloController {
@AutoWried
HelloRemote helloRemote;
@RequestMapping("/{name}")
public String index(@PathVariable("name") String name) {
return helloRemote.hello(name + "!");
}
}
四、测试:
- 依次启动spring-cloud-eureka、spring-cloud-producer、spring-cloud-consumer三个项目
- 先输入:http://localhost:9000/hello?name=neo 检查spring-cloud-producer服务是否正常
五、Springcloud-Feign的各种配置整理
1、feign的GZIP压缩优化
# 全局配置服务器类型压缩
server:
port: 8089
compression:
enabled: true # 启用压缩
mime-types: ["text/html", "text/xml", "text/plain", "text/css", "text/javascript", "application/javascript", "application/xml", "application/json"]
min-response-size: 512
# 配置对请求的内容的压缩,有了上面spring boot的压缩,此处feign的压缩可以不用
feign:
compression:
request:
enabled: true
mime-types: ["text/xml", "application/xml", "application/json"]
min-request-size: 512
response:
enabled: true
client:
config:
default: # key 为default时表示的是全局配置
loggerLevel: basic # 配置日志级别
product-provider-01: # 为具体的服务提供者的spring.application.name的值,表示单独为这个工程配置
loggerLevel: full
2、Feign应用HttpClient连接池来控制优化
2.1 添加依赖
<!-- httpclient相关依赖 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
2.2、修改配置文件
feign:
httpclient:
enabled: true
2.3 提供连接池
//使用HttpClient客户端替换HttpURLConnection,仅需修改Application Client,其余无需修改。
//当使用HttpClient技术作为Feign的底层HTTP技术应用时,使用GET请求方式请求头传递自定义类型对象是可行的,
//只要在服务标准对象中定义的方法参数上增加注解@RequestBody即可处理。
@Configuration
public class HttpClientConfiguration {
@Bean
public HttpClient httpClient(){
System.out.println("init feign httpclient configuration " );
// 生成默认请求配置
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
// 超时时间
requestConfigBuilder.setSocketTimeout(5 * 1000);
// 连接时间
requestConfigBuilder.setConnectTimeout(5 * 1000);
RequestConfig defaultRequestConfig = requestConfigBuilder.build();
// 连接池配置
// 长连接保持30秒
final PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.MILLISECONDS);
// 总连接数
pollingConnectionManager.setMaxTotal(5000);
// 同路由的并发数
pollingConnectionManager.setDefaultMaxPerRoute(100);
// httpclient 配置
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
// 保持长连接配置,需要在头添加Keep-Alive
httpClientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());
httpClientBuilder.setConnectionManager(pollingConnectionManager);
httpClientBuilder.setDefaultRequestConfig(defaultRequestConfig);
HttpClient client = httpClientBuilder.build();
// 启动定时器,定时回收过期的连接, 最重要。 如果没有定义回收策略。连接池会在运行一段时间后失效。
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
pollingConnectionManager.closeExpiredConnections();
pollingConnectionManager.closeIdleConnections(5, TimeUnit.SECONDS);
}
}, 10 * 1000, 5 * 1000);
System.out.println("===== Apache httpclient 初始化连接池===");
return client;
}
}
六、Ribbon的配置,主要配置全局超时配置和单个服务的超时配置
# 配置全局的超时时间
ribbon:
ReadTimeout: 60000 # 读超时时间
ConnectTimeout: 10000 # 连接超时时间
MaxAutoRetries:1 # 最大自动重试次数
MaxAutoRetriesNextServer: 2 #最大自动在其他服务重试次数
# 单个服务的超时时间设置 aservice是服务名称
aservice:
ribbon:
ReadTimeout: 2000
ConnectTimeout: 500
OkToRetryOnAllOperations: true