赞
踩
spring-cloud-starter-netflix-eureka-client 3.0以上默认不再集成Ribbon而改为集成spring-cloud-starter-loadbalancer。这里只是简单介绍一下之前的ribbon使用。
Ribbon是基于HTTO和TCP协议的,主要功能是实现客户端软件的负载均衡算法。
Spring Cloud中Ribbon就是基于NetFix公司的Ribbon实现的,不需要单独部署,但是却存在于整个微服务中。前面学习的Eureka里面有Ribbon,后面学习的OpenFeign也是基于RibbOn实现的。
所有的项目都会注册到Eureka中,Eureka允许不同项目的spring.application.name相同。当相同时会认为这些项目一个集群,所以同一个项目部署多次时都是设置应用程序名相同。
Application Client会从Eureka中根据spring.application.name加载Application Service的列表。根据设定的负载均衡算法,从列表中取出一个URL,到此Ribbon事情就结束了。
下面的事情就是由程序员自己进行技术选型,选择一个HTTP协议工具,通过这个URL调用Application Service。
在客户端和服务端中间使用独立的负载均衡设施,有硬件的(比如 F5),也有软件的(比如 Nginx)。由该设施负责把访问请求通过某种策略转发至服务端。也叫服务端负载均衡。
将负载均衡逻辑集成到客户端组件中,客户端组件从服务注册中心获取有哪些地址可用,然后自己再从这些地址中选择一个合适的服务端发起请求。Ribbon就是一个进程内的负载均衡实现。也叫客户端负载均衡。
创建好Eureka注册中心(端口8761)和服务提供者(端口9090)
另外再多开两个服务提供者主类,端口设置为9091---9092,使用编辑配置比较快,否则也可以自己多创建2个模块,写一样的代码。
服务消费者
在这里选择springboot版本为2.3.7.RELEASE,创建spring模块的时候,更改服务器URL为ailiyun.com。因为spring.io里面都是最新版本的springboot。
spring-cloud-starter-netflix-eureka-client 3.0以上默认不再集成Ribbon而改为集成spring-cloud-starter-loadbalancer。
查看依赖项
2.3.7版本的springboot匹配2.2.6版本的eureka,里面包含有ribbon
application.properties
# 应用名称
spring.application.name=consumer
# 应用服务 WEB 访问端口
server.port=8080
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
主类加上@EnableEurekaClient注解
控制类
@RestController
public class ConsumerController {
@Autowired
private ConsumerService consumerService;
@RequestMapping("/consumer")
public String consumer(){
return consumerService.client();
}
}
接口和接口实现类
package com.weiwei.consumer1.service;
public interface ConsumerService {
String client();
}
package com.weiwei.consumer1.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.stereotype.Service;
@Service
public class ConsumerServiceImpl implements ConsumerService{
@Autowired
//ribbon的负载均衡工具
private LoadBalancerClient loadBalancerClient;
@Override
public String client() {
//loadBalancerClient.choose("服务提供者的spring.application.name"); ServiceInstance serviceInstance = loadBalancerClient.choose("provide"); //得到被调用提供者的Url和端口号,清楚分给了哪个服务端
System.out.println("Url===="+serviceInstance.getUri()+"Port===="+serviceInstance.getPort());
return null;
}
}
可以发现,ribbon负载均衡是轮循规则。
RestTemplate是spring-web-xxx.jar包中提供的Http协议实现类。导入spring-web-xxx.jar包就可以直接使用RestTemplate类。
在该类中有主要针对6类请求方式封装的方法。
Http method | RestTemplate method |
DELETE | delete |
GET | getForObject |
getForEntity | |
POST | postForObject |
postForLocation | |
HEAD | headForHeaders |
PUT | put |
OPTIONS | optionsForAllow |
any(不管什么协议) | 万能的 exchange execute |
请求参数方式1:
@RequestMapping("/demo2")
public String demo2(String name, Integer age) {
return "name:" + name + "age:" + age;
}
对应测试类:
@Test
void test2() {
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("http://localhost:8080/demo2?name=zhangsan&age=12", String.class);
System.out.println(result);
}
@Test
void test3() {
String name="zhangsan";
Integer age=23;
RestTemplate restTemplate = new RestTemplate();
//地址使用字符串拼接方式传参数,这样容易写错
//String result = restTemplate.getForObject("http://localhost:8080/demo2?name="+name+"&age="+age, String.class);
//新写法使用占位符,第三个参数往后赋值
String result = restTemplate.getForObject("http://localhost:8080/demo2?name={1}&age={2}", String.class,name,age);
System.out.println(result);
}
@Test
void test4() {
//使用map方式
RestTemplate restTemplate = new RestTemplate();
HashMap<String, Object> map = new HashMap<>();
map.put("name","lisisi");
map.put("age",23);
String result = restTemplate.getForObject("http://localhost:8080/demo2?name={name}&age={age}", String.class,map);
System.out.println(result);
}
请求参数方式2:
@RequestMapping("/demo3/{name}/{age}")
public String demo3(@PathVariable String name,@PathVariable Integer age) {
return "name:" + name + "age:" + age;
}
对应测试类:
@Test
void test11() {
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("http://localhost:8080/demo3/zhangsan/22", String.class);
System.out.println(result);
}
@Test
void test12() {
String name="zhangsan";
Integer age=23;
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("http://localhost:8080/demo3/{1}/{2}", String.class,name,age);
System.out.println(result);
}
@Test
void test13() {
//使用map方式
RestTemplate restTemplate = new RestTemplate();
HashMap<String, Object> map = new HashMap<>();
map.put("name","lisisi");
map.put("age",23);
String result = restTemplate.getForObject("http://localhost:8080/demo3/{name}/{age}", String.class,map);
System.out.println(result);
}
getForEntity()区别在返回值
@Test
void test21() {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> entity = restTemplate.getForEntity("http://localhost:8080/demo2?name=zhangsan%age=234", String.class);
System.out.println(entity.getStatusCode());
System.out.println(entity.getStatusCodeValue());
System.out.println(entity.getBody());
System.out.println(entity.getHeaders());
}
输出:
200 OK
200
name:zhangsan%age=234age:null
[Content-Type:"text/plain;charset=UTF-8", Content-Length:"29", Date:"Tue, 12 Apr 2022 17:27:22 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive"]
发post请求一般是传递请求体数据
@RequestMapping("/demo4")
public String demo3(String name, Integer age, @RequestBody HashMap<String,Object> map) {
System.out.println(map);
return "name:" + name + "age:" + age;
}
@Test
void PostForObject1(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","zhangsan");
map.put("age",33);
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.postForObject("http://localhost:8080/demo4?name=zhangsan&age=234", map, String.class);
System.out.println(result);
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。