ribbon是基于netfilx ribbon实现的一个工作在consumer端的负载均衡工具,提供了很多负载均衡策略:轮询策略、随机策略...
nacos已经集成了ribbon,故无启动器。
@Configuration
public class BeanConfig {
/**
* 负载均衡工作原理:
* 1.Ribbon会给RestTemplate添加一个拦截器,RestTemplate通过服务名“ribbon_provider”获取到List
* 2.通过负载均衡算法得到serviceInstance
* 3.通过serviceInstance把url中的服务名“ribbon_provider”替换成ip和port
* @return
*/
@Bean
@LoadBalanced // 开启负载均衡,默认为轮询策略
public RestTemplate restTemplate(){
return new RestTemplate();
}
// 使用随机策略调用服务提供者
@Bean
public IRule iRule(){
return new RandomRule();
}
}
@RestController
@RequestMapping(value = "/consumer")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/getUserById/{id}")
public User getUserById(@PathVariable Integer id) {
//不使用ribbon:ip:port
//String serviceUrl = "127.0.0.1:9090";
//使用ribbon:不再使用ip:port的方式,而是改成了serviceId(即Nacos中注册的服务名称)
String serviceUrl = "ribbon-provider";
return restTemplate.getForObject("http://" + serviceUrl +
"/provider/getUserById/" + id, User.class);
}
}
分别使用轮询和随机策略调用服务提供者
Feign是Spring Cloud提供的声明式、模板化的HTTP客户端, 它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可。
Spring Cloud集成Feign并对其进行了增强,使Feign支持了Spring MVC注解;Feign默认集成了Ribbon,所以Fegin默认就实现了负载均衡的效果。总结来说:ribbon + restTemplate = feign。
spring-cloud-starter-openfeign
1. 创建feign_provider
复制一个nacos_provider即可。
2. 创建feign_interface
org.springframework.cloud
spring-cloud-starter-openfeign
com.sanjin
springcloud_common
1.0-SNAPSHOT
package com.bjpowernode.feign;
@FeignClient(value="feign-provider") // 调用指定服务,@FeignClient("服务名")
@RequestMapping(value = "/provider")
public interface UserFeign {
@RequestMapping(value = "/getUserById/{id}")
public User getUserById(@PathVariable(value="id") Integer id);
}
3. 创建feign_consumer
org.springframework.boot
spring-boot-starter-web
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
com.sanjin
springcloud_common
1.0-SNAPSHOT
com.sanjin
feign_interface
1.0-SNAPSHOT
server: port: 80 spring: cloud: nacos: discovery: server-addr: 192.168.75.131:8848 #nacos注册地址 namespace: dev group: springcloud_parent application: name: feign-consumer
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private UserFeign userFeign;
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable("id") Integer id){
return userFeign.getUserById(id);
}
}
package com.sanjin;
@SpringBootApplication
@EnableDiscoveryClient // 向注册中心注册该服务并发现其他服务
//@EnableFeignClients(basePackages = "com.bjpowernode.feign") 扫描指定包
@EnableFeignClients // 开启feign注解扫描
public class FeignConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(FeignConsumerApplication.class, args);
}
}
1、扫描feign接口生成代理类并交给spring容器去管理
@EnableFeignClient开启feign注解扫描:FeignClientsRegistrar.registerFeignClients()扫描被@FeignClient标识的接口并生成代理类,再把代理类交给spring的容器去管理。
2、为接口的方法创建requestTemplate
当consumer调用feign接口的代理类时,会调用SynchronousMethodHandler.invoke()创建RequestTemplate(HttpMethod、UriTemplate、Body)。
3、发送请求
代理类会通过requestTemplate创建request对象,然后client(HttpClient、URLConnect、OkHttp)使用request发送请求。
restful风格:
feign接口:@PathVarible("id")
?传参:
feign接口:@RequestParam("id")
pojo:
feign接口:@RequestBody
案例:
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private UserFeign userFeign;
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable("id") Integer id){
return userFeign.getUserById(id);
}
@RequestMapping("/delUserById")
public User delUserById( Integer id){
return userFeign.delUserById(id);
}
@RequestMapping("/updateUser")
public User updateUser(User user){
return userFeign.updateUser(user);
}
@RequestMapping("/addUser")
public List addUser(){
List userList = new ArrayList<>();
userList.add(new User(1, "ljx", 18));
userList.add(new User(2, "mxx", 18));
return userFeign.addUser(userList);
}
@RequestMapping("/delUserByIds")
public Integer[] delUserByIds(Integer[] ids){
return userFeign.delUserByIds(ids);
}
}
@FeignClient("feign-provider") // 调用指定服务,@FeignClient("服务名")
@RequestMapping("/provider")
public interface UserFeign {
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable("id") Integer id);
@RequestMapping("/delUserById")
public User delUserById(@RequestParam("id") Integer id);
@RequestMapping("/updateUser")
public User updateUser(@RequestBody User user);
@RequestMapping("/addUser")
List addUser(@RequestBody List userList);
@RequestMapping("/delUserByIds")
Integer[] delUserByIds(@RequestParam("ids") Integer[] ids);
}
@RestController
@RequestMapping("/provider")
public class ProviderController {
@Autowired
private UserService userService;
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable Integer id){
return userService.getUserByUserId(id);
}
@RequestMapping("/delUserById")
public User delUserById(Integer id){
return userService.delUserById(id);
}
@RequestMapping("/updateUser")
public User updateUser(@RequestBody User user){
return userService.updateUser(user);
}
@RequestMapping("/addUser")
public List addUser(@RequestBody List userList){
return userService.addUser(userList);
}
@RequestMapping("/delUserByIds")
public Integer[] delUserByIds(Integer[] ids){
return userService.delUserByIds(ids);
}
}
public interface UserService {
User getUserByUserId(Integer id);
User delUserById(Integer id);
User updateUser(User user);
List addUser(List userList);
Integer[] delUserByIds(Integer[] ids);
}
@Service
public class UserServiceImpl implements UserService {
@Override
public User getUserByUserId(Integer id) {
return new User(id, "ljx-1", 18);
}
@Override
public User delUserById(Integer id) {
return new User(0-id, "ljx", -18);
}
@Override
public User updateUser(User user) {
return user;
}
@Override
public List addUser(List userList) {
return userList;
}
@Override
public Integer[] delUserByIds(Integer[] ids) {
return ids;
}
}
1. 开启feign日志
feign: client: config: # default: # 所有服务都生效 feign-provider: #指定服务生效 loggerLevel: full # 输出feign远程调用的详细信息 logging: level: com.sanjin.feign: debug
2. http连接池
仅需添加依赖即可
io.github.openfeign
feign-httpclient
效果图:
3.GZIP 压缩
server:
port: 80
compression:
enabled: true #开启浏览器<---->consumer的gzip压缩
feign:
compression: #开启feign<---->provider的gzip压缩
request:
enabled: true
response:
enabled: true
效果图:
4. feign超时
注意:当开启feign日志后,feign调用的时间会被延长,在一定时间内不会超时。
方式一:
ribbon:
ConnectionTimeout: 5000 #请求连接的超时时候
ReadTimeout: 5000 #请求响应的超时时间
方式二:
feign:
client:
config:
#default:
feign-provider:
ConnectionTimeout: 5000 #请求连接的超时时候
ReadTimeout: 5000 #请求响应的超时时间