写点什么

三、Spring Cloud 之软负载均衡 Ribbon,mysql 架构

用户头像
极客good
关注
发布于: 刚刚

<version>1.0.0</version>


<name>ribbon-provider-9004</name>


<description>ribbon-provider-9004 服务提供者</description>


<dependencies>


<dependency>


<groupId>org.springframework.boot</groupId>


<artifactId>spring-boot-starter-web</artifactId>


</dependency>


<dependency>


<groupId>org.springframework.cloud</groupId>


<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>


</dependency>


</dependencies>


主要就是引入了 eureka-client 可以注册到注册中心去,然后启动类加上 @EnableEurekaClient 注解



在配置文件中加上配置如下:


server.port=9004


spring.application.name=ribbon-provider


eureka.client.service-url.defaultZone=http://localhost:8000/eureka/


我们在创建一个测试类:HelloController


@RestController


@Slf4j


public class HelloController {


@Value("${server.port}")


private String port;


@RequestMapping("/hello")


public String hello(){


log.info(port);


return "hello "+port;


}


}


这样我们一个服务提供者就弄好了,为了看出负载均衡的效果,我们还需要创建一个一样的服务提供者。或者不同的端口启动。我们将端口改为 9005.其他的和上面一样。


服务消费者




服务提供者有了,我们再来创建一个服务消费者的模块。pom.xml 较服务提供者就多了一个 ribbon 的依赖


<dependency>


<groupId>org.springframework.cloud</groupId>


<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>


</dependency>


然后启动类中加上 @EnableEurekaClient 和 RestTemplate


@SpringBootApplication


@EnableEurekaClient


public class RibbonConsumerApplication {


@Bean


@LoadBalanced


public RestTemplate restTemplate(){


return new RestTemplate();


}


public static void main(String[] args) {


SpringApplication.run(RibbonConsumerApplication.class, args);


}


}


@LoadBalanced 注解就是来实现客户端负载均衡的。


配置文件中加入如下配置:


server.port=9003


#服务名,在注册时所用


spring.application.name=ribbon-consumer


eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/


最后我们来写一个调用服务提供者的接口,创建一个 IndexController 类,内容如下


@RestController


public class IndexController {


private static final String applicationName = "ribbon-provider";


@Autowired


private RestTemplate restTemplate;


@RequestMapping("/index")


public String getHello(){


String url = "http://"+ applicationName +"/hello";


return restTemplate.getForObject(url,String.class);


}


}


测试




我们现在来启动服务中心,两个服务提供者,一个服务消费者。启动之后我们输入:


http://localhost:8000/


![在这里插入图片描述](https://img-blog.csdnimg.cn/20200114131431914.p


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


ng?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9xdWVsbGFuYW4uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70)


重点看下 ribbon-provider 有两个端口,分别对应的我们的两个服务提供者。他们的 appliaction.name 是相同的。


再来调下面接口看看


http://localhost:9003/index



可以看到每次调用访问了不同的服务提供者,两个服务端提供者是轮寻调用的。从而实现客户端的负载均衡


RestTemplate


===========================================================================


上面说的负载均衡,其实还是 RestTemplate 对象加上 @LoadBalanced 来实现的。并且前面只是简单的调用,没有涉及参数和请求方式,接下来我们看看常见的请求方式和有参数的调用。


Get 请求




其实我们之前写的就是 get 请求的方式,我们在来写一个有参数的请求


@RequestMapping("index2")


public String getHello2(){


String url = "http://"+ applicationName +"/hello2?name={1}";


return restTemplate.getForObject(url,String.class,"quellanan");


}


可以看到 url 中请求的参数有占位符代替,getForObject 或者 getForEntity 的第三个参数就是我们实际传的参数。这里说明一下 getForObject 是直接获取返回的内容,而 getForEntity 返回的是一个 http 对象,包含相应状态码,想要回去内容需要 getForEntity().getBody() 才行。


那如果多个参数的呢?


多个参数的常用的有两种方式,一个是和上面一样,直接在后面加参数就好了如下:


@RequestMapping("index3")


public String getHello3(){


//多个参数拼接


String url = "http://"+ applicationName +"/hello3?name={1}&age={2}";


return restTemplate.getForObject(url,String.class,"quellanan","18");


}


还有一种方式就是将参数封装到 map 中,传过去。一样的也可以解析


@RequestMapping("index4")


public String getHello4(){


//多参数组装


Map<String,String> parms=new HashMap<>();


parms.put("name","quellanan");


parms.put("age","18");


String url = "http://"+ applicationName +"/hello3?name={name}&age={age}";


return restTemplate.getForObject(url,String.class,parms);


}


我们在提供者中写两个方法便于测试


@RequestMapping("/hello2")


public String hello2(@RequestParam("name") String name){


log.info(name);


return "hello "+name+port;


}


@RequestMapping("/hello3")


public String hello3(@RequestParam("name") String name,@RequestParam("age") String age){


log.info(name+age);


return "hello "+name+age+port;


}


我们启动来看下结果



可以看到参数是传递成功的啦。


Post 请求




post 请求和 get 请求差不多,我这里就将参数封装到 map 中了


postForEntity


@RequestMapping("index6")


public String getHello6(){


//postForEntity


JSONObject params=new JSONObject();


params.put("name","quellanan");


params.put("age","18");


HttpHeaders headers = new HttpHeaders();


headers.setContentType(MediaType.APPLICATION_JSON);


HttpEntity request = new HttpEntity(params.toJSONString(), headers);


String url = "http://"+ applicationName +"/hello4";


return restTemplate.postForEntity(url,request,String.class).getBody();


}


postForObject


@RequestMapping("index7")


public String getHello7(){


//postForObject


JSONObject params=new JSONObject();


params.put("name","quellanan");


params.put("age","18");


HttpHeaders headers = new HttpHeaders();


headers.setContentType(MediaType.APPLICATION_JSON);


HttpEntity request = new HttpEntity(params.toJSONString(), headers);


String url = "http://"+ applicationName +"/hello4";


return restTemplate.postForObject(url,params,String.class);


}


主要是先将参数封装在 JSONObject 中,然后设置 HttpHeaders 和 HttpEntity ,然后请求。


我们采用的 application/json 的格式,我们在服务提供者中加一个方法。用来接收 json 格式的参数。


@RequestMapping("/hello4")


public String hello4(@RequestBody Map<String, Object> parms){


return "hello "+parms.get("name")+parms.get("age")+port;


}


现在我们启动看下效果。



证明都是可以正常传递的。


Feign 简化微服务调用


============================================================================


上面我们可以看到,我们进行微服务调用,不管是使用 get 或者 post 方法,带有参数过多就会导致代码变得很臃肿,所以我们就可以使用同样是 netflix 推出的 Feign 来简化微服务调用,Feign 结合了 Ribbon 以及 Hystrix.Ribbon 的功能它都有,并且还进行了封装,更加方便我们使用。所以我们使用的时候,只用引入 Feign 的依赖就可以。


那我们现在对上面的这些进行调整一下。

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
三、Spring Cloud之软负载均衡 Ribbon,mysql架构