客戶端負載均衡: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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章