客户端负载均衡:Spring Cloud Ribbon

Spring Cloud Ribbon是一个基于http和tcp的客户端负载均衡工具,基于Netflix Ribbon实现。Spring Cloud Ribbon虽然是Spring cloud的一个组件,但不需要像注册中心,配置中心等独立部署,它几乎存在于每一个spring cloud构建的微服务中。

负载均衡是系统架构中一个非常重要的内容,它是对系统进行高可用,缓解网络压力和处理能力扩容的重要手段。服务端负载均衡一般使用硬件设备或者nginx实现。在spring cloud中,客户端负载均衡需要配合注册中心实现,。

关于Ribbon,重要的是RestTemplate对象的使用。通过RestTemplate,配合注册中心,可以很容易地实现不同服务之间的数据交互(须在同一个或一组注册中心下)。

下面的两个服务已经分别向同一个Eureka服务端注册,具体参见上一篇博客。

1.涉及到的实体类:

public class Data {
    private String id;
    private String name;
    private Integer age;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
public class User {
    private String id;
    private String name;
    private Integer age;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

}

这两个类属性的名称是相同的,一个对应于服务提供者,一个对应于服务消费者。

2.服务提供者

@RestController
public class HelloController {

    @RequestMapping(value = "/getUserForEntity",method = RequestMethod.GET)
    public User getUserForEntity(User user){
        return  user;
    }

    /**
     * post接口
     * @param @RequestBody 注解必须有
     * @return
     */
    @RequestMapping(value = "/postUserForEntity",method=RequestMethod.POST)
    public User postUserForEntity(@RequestBody User user){
        if(!StringUtils.isEmpty(user.getId())){
            user.setId(user.getId()+"_post");
        }

        if(!StringUtils.isEmpty(user.getName())){
            user.setName(user.getName()+"_post");
        }
        return  user;
    }

    /**
     * post接口
     */
    @RequestMapping(value = "/postUserForEntity2",method=RequestMethod.POST)
    public User postUserForEntity2(@RequestBody User user,String mingzi){
        if(!StringUtils.isEmpty(mingzi)){
            user.setName(mingzi);
        }
        return  user;
    }

    /**
     * put接口
     * @param
     */
    @RequestMapping(value = "/putUser",method=RequestMethod.PUT)
    public void putUser( @RequestBody User user){
        System.err.println(user);
        //输出:User{id='null', name='null', age=13}
    }
}

服务提供者的服务名为“HELLO-SERVICE

3.服务消费者,Ribbon

@RestController
public class ConsumerController {
    @Resource
    private RestTemplate restTemplate;
    @RequestMapping(value = "ribbon-consumer",method = RequestMethod.GET)
    public String helloConsumer(){
        //HELLO-SERVICE
        return restTemplate.getForEntity("http://HELLO-SERVICE/hello",String.class).getBody();

    }

    /**
     * 请求get类型的接口,占位符形式
     * @param name
     * @return
     */
    @RequestMapping(value = "getUser1",method = RequestMethod.GET)
    public Data getUser1(String name){
        //第一个参数为请求接口的url,用占位符的方式定义get请求附带的参数,第二个参数为要返回的数据类型,最后一个参数为占位符的具体值
        ResponseEntity<Data> entity=restTemplate.getForEntity("http://HELLO-SERVICE/getUserForEntity?name={1}",Data.class,name);

        return entity.getBody();
    }

    /**
     * 请求get类型的接口,map形式
     * @param age
     * @return
     */
    @RequestMapping(value = "getUser2",method = RequestMethod.GET)
    public Data getUser2(Integer age){
        Map<String,Integer>map=new HashMap<>();
        map.put("age",age);
        //第一个参数为请求的url,第二个参数为要返回的数据类型,第三个参数为请求参数,使用map方式
        ResponseEntity<Data> entity=restTemplate.getForEntity("http://HELLO-SERVICE/getUserForEntity?age={age}",Data.class,map);

        return entity.getBody();
    }

    /**
     * 请求get类型的接口,URI形式(URI是java.net包下的一个类,表示统一资源标示符)
     * @param id
     * @return
     */
    @RequestMapping(value = "getUser3",method = RequestMethod.GET)
    public Data getUser3(String  id,String name){
        /**
         * expand(...)方法可以传入多个参数
         */
        UriComponents uriComponents= UriComponentsBuilder.fromUriString("http://HELLO-SERVICE/getUserForEntity?id={id}&name={name}")
                .build()
                .expand(id,name)
                .encode();
        URI uri=uriComponents.toUri();
        //第一个参数为uri,第二个参数为响应内容的类型定义
        ResponseEntity<Data> entity=restTemplate.getForEntity(uri,Data.class);
        return entity.getBody();
    }

    /**
     * 对getForEntity的进一步封装,直接返回包装好的对象
     * 下面是这三个方法的重载
     *
     * getForObject(String url, Class responseType, Object... variables)
     * getForObject(String url, Class responseType, Map variables)
     * getForObject(URI uri, Class variables)
     *
     */


    /**
     * 请求post类型的接口
     * @return 接口响应的数据
     */
    @RequestMapping(value = "postUser1",method = RequestMethod.GET)
    public Data postUser1(){
        Data data=new Data();data.setAge(42); data.setName("张飞");
        /**
         * 第一个参数是访问接口的地址,第二个参数为提交的body内容,第三个参数是请求响应返回的body类型
         */
        ResponseEntity<Data> entity=restTemplate.postForEntity("http://HELLO-SERVICE/postUserForEntity",data,Data.class);

        return entity.getBody();
    }

    /**
     *
     * @param mingzi
     * @return
     */
    @RequestMapping(value = "postUser2",method = RequestMethod.GET)
    public Data postUser2(String mingzi){
        Data data=new Data();data.setAge(22);
        /**
         * 在post请求的url中附带了get请求参数
         */
        ResponseEntity<Data> entity=restTemplate.postForEntity("http://HELLO-SERVICE/postUserForEntity2?mingzi={1}",data,Data.class,mingzi);

        return entity.getBody();
        //返回结果:{"id":null,"name":"lisi","age":22}
    }

    /**
     *  其他两种形式,和get请求比较类似
     *
     * postForEntity(String url, Object request, Class responseType, Map variables)
     * postForEntity(URI var1, Object request, Class responseType)
     *
     */


    /**
     * postForObject方法的三种重载,直接将请求响应的body内容包装成对象
     *
     *  postForObject(String url, Object request, Class responseType, Object... variables)
     *  postForObject(String url, Object request, Class responseType, Map variables)
     *  postForObject(URI uri, Object request, Class  variables)
     */



    /**
     * post 方式提交资源,并返回资源的URI,下面是三种方法的重载:
     * URI
     *  postForLocation(String url, Object request, Object... variables)
     *  postForLocation(String url, Object request, Map variables)
     *  postForLocation(URI url, Object request)
     */

    /**
     * put请求,put方法为void类型,没有返回内容
     */
    @RequestMapping(value = "putUser",method = RequestMethod.GET)
    public void putUser(){
        Data data=new Data();data.setAge(13);
        restTemplate.put("http://HELLO-SERVICE/putUser",data);
    }
    /**
     * put方法的三种重载方式
     * put(String url, Object request, Object... variables)
     * put(String url, Object request, Map variables)
     * put(URI uri, Object variables)
     */

    /**
     * delete(String url, Object... variables)
     * delete(String url, Map variables)
     * delete(URI uri)
     */

}

参考博客:https://blog.csdn.net/keehom/article/details/80721599

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值