springcloud系列(3) - ribbon的使用
首先也是基于前面两个博客的继续往下写的
在使用ribbon之前,先介绍下ribbon,ribbon是客户端负载均衡,就是说,每一个微服务都会将eureka注册中心的信息获取存在本地,然后调用的时候使用一定的算法进行调用(各种算法,比如轮询,随机等)
负载均衡肯定要讲下ngnix,这个是服务端负载均衡,就是说,请求转发给ngnix服务器,然后由ngnix服务器来帮你转发(基于相关的配置,但是这个只适合于单模块多实例的服务,不适合多模块的微服务,如果要使用ngnix在多模块中,那么相当于每个模块都要配置一个ngnix服务器进行负载均衡)
一样的,首先创建一个order-service订单服务,pom.xml同样不需要引入什么,因为父工程中已经有了。
在resource中创建application.yml文件,内容:
spring:
application:
name: order-service
server:
port: 8801
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8888/eureka/
instance:
prefer-ip-address: true
创建包名和OrderServiceApplication.java
@SpringBootApplication
@EnableDiscoveryClient
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class,args);
}
}
然后创建ribbon的配置类:RestTemplateConfig.java
@Configuration //标明是配置类
public class RestTemplateConfig {
@Bean // 放入spring容器中管理
@LoadBalanced // 开启负载均衡,如果没有这个那么将不能通过微服务的名称去调用别的服务,但可以通过ip和端口号去调用
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
现在首先要实现远程调用,举个列子: 使用订单服务去调用用户服务获取用户的信息
首先在用户模块(user-service)创建一个接口controller: UserController:
@RequestMapping("/v1")
@Controller
public class UserController {
@RequestMapping(value = "/user")
public ResponseEntity<?> getUserInfo(){
UserInfoResp userInfos= new UserInfoResp();
userInfos.setNickName("cara liu0");
userInfos.setPk(1L);
userInfos.setPhoneNumber("18814098957");
return new ResponseEntity<>(userInfos, HttpStatus.OK);
}
}
UserInfoResp.java:
package cn.yishijie.apibean.v1;
/**
* @author jeffchan 2020/03/10
*/
public class UserInfoResp {
private long pk;
private String nickName;
private String phoneNumber;
public long getPk() {
return pk;
}
public void setPk(long pk) {
this.pk = pk;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
跑起来看能不能调通接口: 调用 GET http://localhost:8800/v1/user
返回信息:
{
"pk": 1,
"nickName": "cara liu0",
"phoneNumber": "18814098957"
}
接口没问题了,那么接着就是写订单服务那边的代码:创建 OrderController
@Controller
@RequestMapping("/v1")
public class OrderController {
@Autowired
private RibbonUserService ribbonUserService;
@RequestMapping(value = "/order",method = RequestMethod.GET)
public ResponseEntity<?> getOrder(){
UserInfoResp userInfoResp = ribbonUserService.getUserInfo();
return new ResponseEntity<>(userInfoResp, HttpStatus.OK);
}
}
创建 RibbonUserService 和 相应实现类:RibbonUserServiceImpl ,同样需要上述的UserInfoResp(直接拷贝上述的即可)类:
public interface RibbonUserService {
UserInfoResp getUserInfo();
}
@Service
public class RibbonUserServiceImpl implements RibbonUserService {
@Autowired
private RestTemplate restTemplate;
@Override
public UserInfoResp getUserInfo() {
UserInfoResp userInfoResp = null;
String url = "http://USER-SERVICE/v1/user";
try {
//远程调用
ResponseEntity<UserInfoResp> result = restTemplate.getForEntity(url,UserInfoResp.class);
userInfoResp = result.getBody();
}catch (Exception e){
System.out.println(e.getMessage());
}
return userInfoResp;
}
}
启动项目,访问 GET http://localhost:8801/v1/order 返回结果跟用户服务是一样的。
验证ribbon的默认负载均衡规则
copy一个用户模块,修改端口号,同时修改用户的昵称为 cara liu1(为了验证调用的是不同的实列)启动即可:如下图
有了两个实列,然后你调用订单的那个接口,发现会轮询的返回不同的昵称
当然也可以修改这个规则,注入一个对应的IRule类型的实列即可(可以使用依赖中已经提供的策略,也可以自己定义,同时还可以为特定的一个微服务提供一个特定的规则,比如说我订单服务还要调用其他直播服务啥的,那么可以为分别为用户服务和直播服务设置不同的均衡规则)