Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。
参考文档:http://cloud.spring.io/spring-cloud-static/Dalston.SR5/single/spring-cloud.html#spring-cloud-ribbon 第16节
项目环境:https://blog.csdn.net/wufewu/article/details/84646382
Ribbon调用
Main方法处添加负载均衡
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
RestTemplate的用法
RestTemplate的四种请求:
GET请求 getForEntity POST请求 postForEntity PUT请求 put DELETE请求 delete
客户端请求:
Book book = new Book(); book.setName(“红楼梦”); ResponseEntity<Book> responseEntity = restTemplate.postForEntity(“http://服务名/路径", book, Book.class); return responseEntity.getBody();
服务端接收
@PostMapping(value = "/getbook2")
public Book book2(@RequestBody Book book) {}
其中具体的例子可以查看:https://blog.csdn.net/wufewu/article/details/84646382 里面的SPRINGCLOUD_USERUI模块
其中默认的是RoundRobinRule(轮循查询),如果想要更改算法,直接在Main方法添加一个Bean类,如:
@Bean // 支持负载均衡功能(默认使用Ribbon实现负载均衡) @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }
// 指定负载均衡算法 // 所有调用的微服务都想是同一个规则就放在这里 // 全局配置 @Bean public RandomRule randomRule() { return new RandomRule(); } public static void main(String[] args) { new SpringApplicationBuilder(UserUi.class).web(true).run(args); }<strong>解释</strong>:我将负载均衡算法改为了一个RandomRule算法(随机算法),<br>
模拟环境:在注册中心建立一个微服务的两个实例,然后在客户端建立一个调用微服务的方法的方法,然后输出结果。这里就不展示了
注意:在Main方法里更改算法,所有的调用微服务的算法都会变成更改后的算法
建立自定义的负载均衡规则:
定义规则类
package com.ps.rule; import java.util.List; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.Server; public class MyRule extends AbstractLoadBalancerRule{ @Override public Server choose(Object key) { // 取到当前的负载均衡器,由父类提供 可以拿到对应的要调用微服务后的服务器 ILoadBalancer loadBalancer = this.getLoadBalancer(); // 取到所有可以访问的服务器 List<Server> reachableServers = loadBalancer.getReachableServers(); return reachableServers.get(0); } @Override public void initWithNiwsConfig(IClientConfig arg0) { // TODO Auto-generated method stub } }
然后在Main方法指定算法:
@Bean public IRule rhle() { return new MyRule(); }
- 1
- 2
- 3
- 4
解释:在这里调用微服务的实例只能调用第一个
当调用微服务不使用全局配置,即调用指定的微服务时是随机,调用其他的微服务是默认(轮徇)的
自定义类:
@RibbonClient(value="USERSERVICE",configuration=MyRule.class) public class MyRule {
@Bean public IRule randomRul() { return new RoundRobinRule(); }
然后在application.yml资源文件中加:
# 放在这里是指针对不同的微服务调用不同的负载均衡规则 USERSERVICE: ribbon: NFLoadBalancerRuleClassName: com.ps.rule.MyRule
解释:
USERSERVICE:指微服务的名字
com.ps.rule.MyRule:指定义的类的路径
二.Feign简介
Feign是从Netflix中分离出来的轻量级项目,能够在类接口上添加注释,成为一个REST API 客户端,(面向对象,更优雅,更适合普通的开发者人员)
参考文档:http://cloud.spring.io/spring-cloud-static/Dalston.SR5/single/spring-cloud.html#spring-cloud-feign 第17节
项目环境:https://blog.csdn.net/wufewu/article/details/84646382我现在根据项目环境来演示一下feign的调法,查看项目环境中的SPRINGCLOUD_USERSERVICE模块,添加一个EmpController.java与一个实体类,如下:
代码如下:
EmpController.javapackage com.ps.controller; import java.util.ArrayList; import java.util.List; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import com.ps.entity.Emp; import com.ps.entity.Result; @RestController public class EmpController { @GetMapping("/emp/{id}") public Result queryEmp(@PathVariable("id") String id) { Emp emp = new Emp(); emp.setId("1"); emp.setName("张三"); Result re = new Result(); List<Emp> list = new ArrayList<>(); list.add(emp); re.setCode(1); re.setData(list); return re; } // post请求因为参数带有对象,所以必须添加@RequestBody @PostMapping("/emp") public Result saveEmp(@RequestBody Emp emp) { Result re = new Result(); re.setCode(1); re.setMsg("增加应该成功了"); return re; } @DeleteMapping("/emp/{id}") public Result delEmp(@PathVariable String id) { Result re = new Result(); re.setCode(1); re.setMsg("删除应该成功了"); return re; } @PutMapping("/emp/{id}") public Result delEmp(@PathVariable String id,@RequestBody Emp emp) { Result re = new Result(); re.setCode(1); re.setMsg("修改应该成功了"); return re; } }
@Data public class Emp { private String id; private String name; }
- 1
- 2
- 3
- 4
- 5
然后再在项目中加一个模块(方便演示)SPRINGCLOUD_USERUI_FEIGN,如:
在pom.xml文件添加依赖:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- 小辣椒 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
<!-- 开发者工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- 导入Feign依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
</dependencies>
application.yml资源文件:
#界面一般是80端口
server:
port: 80
#给登录微服务设置一个名字
spring:
application:
name: useruifeign
eureka:
instance:
prefer-ip-address: true
hostname: localhost
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka/
entity包下的两个实体类:
Emp.java:
@Data
public class Emp {
private String id;
private String name;
}
Result.java
@Data
public class Result {
private int code;
private String msg;
private List<Emp> data;
}
EmpFeign.java
// 客户端的接口根远程service做了绑定,假如在这个类跳用queryEmp方法就相当与调用远程微服务
// 指定要调用的微服务
@FeignClient(name=“USERSERVICE”)
public interface EmpFeign {
@GetMapping("/emp/{id}")
public Result queryEmp(@PathVariable(“id”) String id) ;
@PostMapping("/emp")
public Result saveEmp(@RequestBody Emp emp) ;
@DeleteMapping("/emp/{id}")
public Result delEmp(@PathVariable("id") String id) ;
@PutMapping("/emp/{id}")
public Result delEmp(@PathVariable("id") String id,@RequestBody Emp emp) ;
}
UserUiFeing.java
@SpringBootApplication
// 启用eureka的服务
@EnableEurekaClient
// 表示启用Feign
@EnableFeignClients
public class UserUiFeign {
public static void main(String[] args) {
new SpringApplicationBuilder(UserUiFeign.class).web(true).run(args);
}
}
controlloer包下的EmpcController.java
@RestController public class EmpcController { @Autowired EmpFeign empFeign;
@GetMapping("/query") public List<Emp> query() { String id = "1"; Result queryEmp = empFeign.queryEmp(id); return queryEmp.getData(); } @GetMapping("/save") public String save() { Result queryEmp = empFeign.saveEmp(new Emp()); return queryEmp.getMsg(); } @GetMapping("/del") public String del() { Result delEmp = empFeign.delEmp("1"); return delEmp.getMsg(); } @GetMapping("/aaa") public String a() { String a = empFeign.a(); return a; }
}
运行结果: