SpringCloud远程调用服务 - 01

SpringCloud远程调用服务

使用DiscoveryClient
@Autowired
DiscoveryClient client;

注意导的包是: org.springframework.cloud.client.discovery.DiscoveryClient;

// 查看注册的实例
List<String> services = client.getServices();
// 通过服务serviceId获取服务实例,可能配置多个(分布式)
List<ServiceInstance> serviceInstances = client.getInstances("providerclinet");
// 获取主机地址和端口
String host = ins.getHost();
int port = ins.getPort();
// 在补充上服务地址即可调用相关服务
// hi
String url = "http://"+hostName + ":"+port + "/hi";
RestTemplate restTemplate = new RestTemplate();
// RestTemplate调用微服务
String repsStr = restTemplate.getForObject(url, String.class);
使用EurekaClient
@Autowired
EurekaClient client2;

导包是: com.netflix.discovery.EurekaClient;

// 通过Eureka中注册的服务Id,获取实例信息
List<InstanceInfo> instanceInfos = client2.getInstancesByVipAddress("providerclinet", false);
// 获取单个实例
InstanceInfo instanceInfo = instanceInfos.get(0);
// 获取主机地址和端口
String hostName = instanceInfo.getHostName();
int port = instanceInfo.getPort();
// 获取实例
InstanceInfo.InstanceStatus status = instanceInfo.getStatus();
if (status== InstanceInfo.InstanceStatus.UP) {
    String url = "http://"+hostName + ":"+port + "/hi";
    RestTemplate restTemplate = new RestTemplate();
    // RestTemplate调用微服务
    String repsStr = restTemplate.getForObject(url, String.class);
    System.out.println("repsStr: "+repsStr);
 }

Ribbon负载均衡

现在Ribbon的依赖直接增加到了Eureka Clinet的依赖中了。

ribbon的使用:

通过注入

@Autowired
LoadBalancerClient lb;
// ribbon 完成负载均衡,过滤掉down了的节点
ServiceInstance instance = lb.choose("providerclinet");
String url ="http://" + instance.getHost() +":"+ instance.getPort() + "/hi";
// 通过RestTemplate调用
String respStr = restTemplate.getForObject(url, String.class);
ribbon的特点

ribbon是客户端负载均衡,就是根据自己的情况做负载。在客户端负载均衡中,所有的客户端节点都有一份自己要访问的服务端代理的地址,服务代理则知道所有服务端的地址。

ribbon作为Spring Cloud的负载均衡机制的实现:
  1. Ribbon可以单独使用,作为一个独立的负载均衡组件。只是需要我们手动配置服务地址列表。
  2. Ribbon与Eureka配合使用时,Ribbon可自动从EurekaServer获取服务提供者地址列表(DiscoveryClient),并基于负载均衡算法,请求其中一个服务提供者实例。
  3. Ribbon与OpenFeign和RestTemplate进行无缝对接,让二者具有负载均衡的能力。OpenFeign默认集成了ribbon。
ribbon的负载均衡算法
  1. ZoneAvoidanceRule: 区域权衡策略,复合判断Server所在区域的性能和Server的可用性,轮询选择服务。
  2. BestAvailableRule:最低并发策略,过滤掉由于多次访问故障而处于断路器跳闸装的服务,再选择一个并发量最小的服务。
  3. RoundRobinRule:轮询策略,按顺序循环选择一个server。
  4. RandomRule:随机策略,随机选择一个服务器。
  5. AvailabilityFilteringRule:过滤策略,会先过滤掉多次访问故障而处于断路器跳闸状态的服务和过滤并发的连接数量超过阀值得服务,然后对剩余的服务列表安装轮询策略进行访问。
  6. WeightedResponseTimeRule:响应时间加权策略。根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大,容易被选中的概率就越高。
  7. RetryRule:重试策略。按照RoundRobinRule(轮询)的策略,获取某个服务失败则在指定的时间会进行重试,直到超时。
如何进行切换负载均衡的策略
注解方式:
	@Bean
	public IRule myRule(){
		//return new RoundRobinRule();
		//return new RandomRule();
		return new RetryRule(); 
    }
配置文件:

针对服务定ribbon策略:

provider.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

给所有服务定ribbon策略:

ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
Ribbon脱离Eureka
ribbon.eureka.enabled=false
# 指定服务端的地址
ribbon.listOfServers=localhost:80,localhost:81

RestTemplate的使用

getForObject(url,classType,params)

请求返回一个指定类型的数据;参数传递占位符则指定多个,也可以传递Map来封装参数。

例子:

	@Autowired
    RestTemplate restTemplate;
	
	@GetMapping("/test1")
    public void test1(){
        String url = "http://providerclinet/hi";
        String res = restTemplate.getForObject(url, String.class);
        System.out.println(res);
    }

这里边的RestTemplate是注入到Spring容器中的:

	@Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate;
    }

@LoadBalanced: Ribbon实现客户端负载均衡

参数传递:

	@GetMapping("/test2")
    public void test2(){
        String url = "http://providerclinet/hi?name={1}";
        String res = restTemplate.getForObject(url, String.class,"韩梅梅");
        System.out.println(res);
    }

	@GetMapping("/test3")
    public void test3(){
        // 在url上拼接上参数
        String url = "http://providerclinet/hi?name={name}";
        Map<String,String> map = new HashMap<>();
        // 再用map封装参数
        map.put("name","韩梅梅");
        String res = restTemplate.getForObject(url, String.class,map);
        System.out.println(res);
    }
getForEntity(url,classType,params)

参数用法和上个差不多,这个返回值是一个ResponseEntity;包装一些haaders,status,body信息。

例子:

	@GetMapping("/client12")
    public void client12(){
        String url = "http://providerclinet/getMap";
        ResponseEntity<Map> entity = restTemplate.getForEntity(url, Map.class);
        // 在body中包装返回的内容
        System.out.println(entity.getBody());
    }
	/*
		返回的是对象
	*/
	@GetMapping("/client13")
    public void client13(){
        String url = "http://providerclinet/getPerson";
        ResponseEntity<Person> entity = restTemplate.getForEntity(url, Person.class);
        System.out.println("respStr"+ 		ToStringBuilder.reflectionToString(entity.getBody()));
    }

传递参数方式与"getForObject"类似

psot方式调用

例子:

	@GetMapping("/client16")
    public void client16(){
        String url = "http://providerclinet/postParam";
        String name = "abc";
        ResponseEntity<Person> entity = restTemplate.postForEntity(url,name,Person.class);
        System.out.println("respStr"+ ToStringBuilder.reflectionToString(entity.getBody()));
    }
postForLocation: 重定向
	@GetMapping("/client17")
    public Object client17(HttpServletResponse response) throws Exception {
        String url = "http://providerclinet/postForLocation";
        Map<String, String> map = Collections.singletonMap("name", " abc");
        URI location = restTemplate.postForLocation(url, map);
        System.out.println(location);
        response.sendRedirect(location.toURL().toString());
        return null;
    }

提供服务:

@PostMapping("/postForLocation")
    public URI postForLocation (@RequestBody Person person, HttpServletResponse response) throws URISyntaxException {
        URI uri = new URI("https://www.baidu.com/s?wd="+person.getName().trim());
        // 需要设置头信息,不然返回的是null
        response.addHeader("Location",uri.toString());
        return uri;
    }
在RestTemplate设置拦截器

实现ClientHttpRequestInterceptor接口来实现拦截器

例子:

public class LoggingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        // 拦截的请求进行操作
        System.out.println("拦截请求!!!");
        System.out.println(request.getURI());
        ClientHttpResponse execute = execution.execute(request, body);
        System.out.println(execute.getHeaders());
        return execute;
    }
}

在刚才写的RestTemplate增加拦截器:

	@Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        // 增加实现的拦截器
        restTemplate.getInterceptors().add(new LoggingClientHttpRequestInterceptor());
        return restTemplate;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值