负载均衡Ribbon&声明式服务调用Feign
1.负载均衡Ribbon
1.1.创建服务提供者
1.1.1.创建工程

1.1.2.application.yml分别改为
server:
port: 9090
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.241.131:8848
application:
name: ribbon-provider
server:
port: 9091
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.241.131:8848
application:
name: ribbon-provider
1.1.3.service实现类分别改为
@Service
public class UserServiceImpl implements UserService {
@Override
public User getUserById(Integer id) {
return new User(id, "自来也_1", 25);
}
}
@Service
public class UserServiceImpl implements UserService {
@Override
public User getUserById(Integer id) {
return new User(id, "自来也_2", 25);
}
}
1.2.创建服务消费者
1.2.1.创建工程

1.2.2.application.yml
server:
port: 80
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.241.131:8848
application:
name: ribbon-consumer
1.2.3.controller
package com.bjpowernode.controller;
import com.bjpowernode.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
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 ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable("id") Integer id){
List<ServiceInstance> serverList = discoveryClient.getInstances("ribbon-provider");
String url = "http://ribbon-provider/provider/getUserById/" + id;
return restTemplate.getForObject(url, User.class);
}
}
1.2.4.修改BeanConfig
在方法名上加上@LoadBalanced注解
@Bean
@LoadBalanced
public RestTemplate RestTemplate(){
return new RestTemplate();
}
1.3.测试
浏览器访问http://127.0.0.1/cousumer/getUserById/25通过不断的刷新会轮询出现自来也_1和自来也_2
2.声明式服务调用Feign
2.1.背景
当我们通过RestTemplate调用其它服务的API时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还可以忍受,一旦有多个参数的话,这时拼接请求字符串就会效率低下,并且显得好傻。
那么有没有更好的解决方案呢?答案是确定的有,Netflix已经为我们提供了一个框架:Feign。
2.2.Feign入门
2.2.1.创建服务提供者
2.2.1.1.创建工程

2.2.1.2.application.yml
server:
port: 8090
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.241.131:8848
namespace: dev
group: springcloud_parent
application:
name: feign-provide
2.2.2.创建feign接口
2.2.2.1.创建工程

2.2.2.2.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>springcloud_parent</artifactId>
<groupId>com.bjpowernode</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>feign_interface</artifactId>
<dependencies>
<!--Spring Cloud OpenFeign Starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>springcloud_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
2.2.2.3.创建消费者

2.2.2.4.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>springcloud_parent</artifactId>
<groupId>com.bjpowernode</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ribbon_consumer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>springcloud_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--feign接口-->
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>feign_interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
2.2.2.5.application.yml
server:
port: 80
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.241.131:8848
namespace: dev
group: springcloud_parent
application:
name: feign-consumer
2.2.2.6.Consumer.Controller
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private UserServiceFeign userServiceFeign;
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable Integer id){
return userServiceFeign.getUserById(id);
}
@RequestMapping("/editUser")
public User editUser(User user){
return userServiceFeign.editUser(user);
}
@RequestMapping("/delUserById")
public User delUser(Integer id){
return userServiceFeign.delUser(id);
}
@RequestMapping("/addUser")
public List<User> addUser(){
List<User> userList = new ArrayList<>();
userList.add(new User(1, "张三", 20));
userList.add(new User(2, "李四", 20));
userList.add(new User(3, "王五", 20));
userList.add(new User(4, "赵六", 20));
userList.add(new User(5, "钱七", 20));
return userServiceFeign.addUser(userList);
}
@RequestMapping("/delUserByIds")
public Integer[] delUserByIds(Integer[] ids){
return userServiceFeign.delUserByIds(ids);
}
}
2.2.2.7.FeignConsumerApp
@SpringBootApplication
@EnableDiscoveryClient //允许 注册服务和发现服务
@EnableFeignClients //开启feign注解扫描
public class FeignConsumerApp {
public static void main(String[] args) {
SpringApplication.run(FeignConsumerApp.class, args);
}
}
2.2.2.8.feign_interface(feign_interface相当于浏览器,会代替我们发送请求)
package com.bjpowernode.feign;
import com.bjpowernode.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@FeignClient("feign-provider")
@RequestMapping("/provider")
public interface UserServiceFeign {
@RequestMapping("/getUserById/{id}") //发送请求:provider/getUserById/id
User getUserById(@PathVariable("id") Integer id);
@RequestMapping("/editUser") //发送请求:provider/editUser
User editUser(@RequestBody User user); //@RequestBody:pojo-->json
@RequestMapping("/delUserById") //发送请求:provider/delUserById?id=?
User delUser(@RequestParam("id") Integer id);
@RequestMapping("/addUser") //发送请求:provider/addUser
List<User> addUser(@RequestBody List<User> userList);
@RequestMapping("/delUserByIds") //发送请求:provider/delUserByIds
Integer[] delUserByIds(@RequestParam("ids") Integer[] ids);
}
2.2.2.9.feign_provider.Controller
@RestController
@RequestMapping("/provider")
public class ProviderController {
@Autowired
private UserService userService;
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable("id") Integer id){
return userService.getUserById(id);
}
@RequestMapping("/editUser")
public User editUser(@RequestBody User user){
return userService.editUser(user);
}
@RequestMapping("/delUserById")
public User delUser(Integer id){
return userService.delUser(id);
}
@RequestMapping("/addUser")
public List<User> addUser(@RequestBody List<User> userList){
return userService.addUser(userList);
}
@RequestMapping("/delUserByIds")
public Integer[] delUserByIds(Integer[] ids){
return userService.delUserByIds(ids);
}
}
2.2.2.10.feign_provider.service
public interface UserService {
User getUserById(Integer id);
User editUser(User user);
User delUser(Integer id);
List<User> addUser(List<User> userList);
Integer[] delUserByIds(Integer[] ids);
}
2.2.2.11.feign_provider.serviceImpl
@Service
public class UserServiceImpl implements UserService {
@Override
public User getUserById(Integer id) {
return new User(id, "自来也", 25);
}
@Override
public User editUser(User user) {
return user;
}
@Override
public User delUser(Integer id) {
return new User(0-id, "佐助", -16);
}
@Override
public List<User> addUser(List<User> userList) {
return userList;
}
@Override
public Integer[] delUserByIds(Integer[] ids) {
return ids;
}
}
2.3.Feign参数传递
传参方式:
- restful风格:
feign接口:@PathVarible【拼接restful形式的url】
- ?传参
feign接口:@RequestParam【拼接?形式的url】
- pojo参数
provider: @RequestBody User user【获取请求体中的json串】
2.4.测试
2.4.1.浏览器访问不同的url
一、访问 localhost/cousumer/getUserById/25

二、访问 localhost/consumer/delUserById?id=3

三、访问 localhost/consumer/editUser?id=1&name=鸣人&age=16

四、访问 localhost/consumer/addUser

五、访问 localhost/consumer/delUserByIds?ids=1,2,3,4,5

2.5.Feign优化
2.5.1.开启Feign日志
feign:
client:
config:
#dfault:
feign-provider:
loggerLevel: full #输出feign远程调用的详细信息
logging:
level:
com.bjpowernode.feign: debug #log4j的日志级别
2.5.2.Http连接池
HTTP协议是全双工的协议,所以建立连接与断开连接是要经过三次握手与四次挥手的。显然在这种设计中,每次发送Http请求都会消耗很多的额外资源,即连接的建立与销毁。
于是,HTTP协议的也进行了发展,通过持久连接的方法来进行socket连接复用。
只需加入下面依赖便可以开启Http连接池
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
2.5.3.GZIP压缩
server:
port: 80
compression:
enabled: true #开启浏览器<---->consumer的gzip压缩
feign:
compression: #开启feign<---->provider的gzip压缩
request:
enabled: true
response:
enabled: true

2.5.4.Feign超时(feign默认超时时间是1秒)
方式一:
ribbon:
ConnectionTimeout: 5000 #请求连接的超时时候
ReadTimeout: 5000 #请求响应的超时时间
方式二:
feign:
client:
config:
#default:
feign-provider:
ConnectionTimeout: 5000 #请求连接的超时时候
ReadTimeout: 5000 #请求响应的超时时间
#### 2.5.4.Feign超时(feign默认超时时间是1秒)
```yaml
方式一:
ribbon:
ConnectionTimeout: 5000 #请求连接的超时时候
ReadTimeout: 5000 #请求响应的超时时间
方式二:
feign:
client:
config:
#default:
feign-provider:
ConnectionTimeout: 5000 #请求连接的超时时候
ReadTimeout: 5000 #请求响应的超时时间
本文介绍如何使用Ribbon实现负载均衡及Feign声明式服务调用,包括配置和服务间通信流程。
168万+

被折叠的 条评论
为什么被折叠?



