Spring Cloud学习笔记16——微服务的消费

微服务的消费模式

基于http的客户端经常被用作微服务的消费者,因为http本身是平台无关的、语言无关的,所以基于http的客户端往往会被广大的社区支持

服务直连模式

特点:

  • 简洁明了,只要传入一个URL,就能直接连过去,获取到资源
  • 平台语言无关性,非常直白,不需要特定框架、技术,能实现平台无关、语言无关
  • 无法保证服务的可用性,当需要链接某个IP下的某个资源时,如果这个IP地址或这个IP地址所绑定的主机宕机了,这个资源就无法拿到,因为服务直连模式无法做到负载均衡,也就无法保证服务的可用性
  • 生产环境比较少用

客户端发现模式

  1. 服务实例启动后,将自己的位置信息提交到服务注册表
  2. 客户端从服务注册表进行查询,来获取可用的服务实例
  3. 客户端自行使用负载均衡算法从多个服务实例中选择出一个

在这里插入图片描述

服务端发现模式

与客户端发现模式最大的区别在于:负载均衡不是由客户端来做,而是在服务端实现,负载均衡器是独立部署在服务端的
在这里插入图片描述

常见微服务的消费者

Apache HttpClient

用来提供高效、功能丰富的http协议的客户端工具包,能支持http协议最新的版本和建议。Apache HttpClient能对JDK提供一些非常好的补充,方便开发人员测试基于http的接口,从而提高开发效率及代码健壮性

Apache HttpClient的用法

添加依赖

//依赖关系
dependencies {

	//添加Apache HttpClient依赖
	compile('org.apache.httpcomponents:httpclient:4.5.6')

}

注入restTemplate

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
//rest配置类,配置restTemplate
public class RestConfiguration {

	@Autowired
	private RestTemplateBuilder builder;
	
	@Bean
	public RestTemplate restTemplate() {
		return builder.build();
	}
	
}

使用

@Service
public class WeatherDataServiceImpl implements WeatherDataService {

	@Autowired
	private RestTemplate restTemplate;

	private WeatherResponse doGetWeather(String uri) {
		ResponseEntity<String> respString = restTemplate.getForEntity(uri, String.class);
		//...
	}
	//...
}

Ribbon

RibbonSpring Cloud中的一个组件,是基于Netflix Ribbon实现客户端负载均衡的一个工具,基于httpTCP来实现客户端的负载均衡

Ribbon的每个负载均衡器一起协作,可以根据需要与远程服务器进行交互,来获取包含命名客户端名词的集合,Ribbon经常与Eureka结合使用,在典型的分布式部署中,Eureka为所有的微服务实例提供服务注册,Ribbon提供服务消费的客户端

Ribbon有很多负载均衡的算法

Ribbon的用法

添加依赖

//依赖关系
dependencies {

	//添加Spring Cloud Starter Netflix Ribbon依赖
	compile('org.springframework.cloud:spring-cloud-starter-netflix-ribbon')

}

build.gradle完整代码如下:

//buildscript代码块中脚本优先执行
buildscript {

    //ext用于定义动态属性
	ext {
		springBootVersion = '2.0.0.M3'
	}

    //使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库)
    repositories {
        //mavenCentral()
        maven{ url "https://repo.spring.io/snapshot" }
        maven{ url "https://repo.spring.io/milestone" }
        maven{ url "http://maven.aliyun.com/nexus/content/groups/public/" }
    }

    //依赖关系
	dependencies {
        //classpath声明了在执行其余的脚本时,ClassLoader可以使用这些依赖项
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}

//使用插件
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

//指定了生成的编译文件的版本,默认是打成了jar包
group = 'com.study.spring.cloud'
version = '1.0.0'

//指定编译.java文件的JDK版本
sourceCompatibility = 1.8

//使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库)
repositories {
    //mavenCentral()
    maven{ url "https://repo.spring.io/snapshot" }
    maven{ url "https://repo.spring.io/milestone" }
    maven{ url "http://maven.aliyun.com/nexus/content/groups/public/" }
}

ext {
    springCloudVersion = 'Finchley.M2'
}

//依赖关系
dependencies {

    //该依赖用于编译阶段
	compile('org.springframework.boot:spring-boot-starter-web')

	//Eureka Client
    compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
	
	//添加Spring Cloud Starter Netflix Ribbon依赖
    compile('org.springframework.cloud:spring-cloud-starter-netflix-ribbon')
    
    //该依赖用于测试阶段
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

//Spring Cloud依赖管理
dependencyManagement{
    imports{
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

注入

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
@RibbonClient(name = "ribbon-client",configuration = RibbonConfiguration.class)
public class RestConfiguration {

	@Autowired
	private RestTemplateBuilder builder;
	
	@Bean
	@LoadBalanced
	public RestTemplate restTemplate() {
		return builder.build();
	}
	
}

配置

import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.PingUrl;
import org.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RibbonConfiguration {

	@Bean
	public ZonePreferenceServerListFilter serverListFilter(){
		ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter();
		filter.setZone("myZone");
		return filter;
	}

	@Bean
	public IPing ribbonPing(){
		return new PingUrl();
	}
}

使用

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class CityController {

	@Autowired
	private RestTemplate restTemplate;

	@GetMapping("/cities")
	public String listCity(){
		//通过应用名词来查找
		String body=restTemplate.getForEntity("http://msa-weather-city-eureka/cities", String.class).getBody();
		return body;
	}
}

应用配置application.properties

#应用名称
spring.application.name=micro-weather-eureka-client-ribbon

#指定Eureka服务器地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

Feign

Feign是一款声明式的Web服务客户端,这使得编写Web服务客户端更容易,同时它具有可拔插的注释支持,Spring CloudFeign有集成,在使用Feign的时候,Spring Cloud同时会集成RibbonEureka来提供负载均衡http客户端

集成Feign

开发环境

  • JDK8+
  • Gradle4+
  • Redis 3.2.100
  • Spring Boot 2.0.0.M3
  • Spring Cloud Starter Netflix Eureka Client Finchley.M2
  • Spring Cloud Starter OpenFeign Finchley.M2

创建项目

复制之前的micro-weather-eureka-client项目,将副本改名为micro-weather-eureka-client-feign
在这里插入图片描述

修改源码

修改build.gradle配置,添加Feign依赖:

//依赖关系
dependencies {

    //Eureka Client
    compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')

    //Feign
    compile('org.springframework.cloud:spring-cloud-starter-openfeign:2.0.0.M3')

    //该依赖用于测试阶段
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

此处要注意Feign依赖的版本,如果不加版本号,将默认下载2.0.0.M2版本,源码中是没有LoadBalancedRetryFactory的,运行会导致以下报错:

java.lang.ClassNotFoundException: org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory

修改com.study.spring.cloud.weather包下的Application类,加入@EnableFeignClients注解:

package com.study.spring.cloud.weather;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;

/*
 * @SpringBootApplication注解声明Spring Boot应用
 * 作用等同于@Configuration, @EnableAutoConfiguration, @ComponentScan,
 * 简化Spring配置
*/
@SpringBootApplication
//启用可发现的客户端
@EnableDiscoveryClient
//启用Feign
@EnableFeignClients
//Application类一定要处于整个工程的根目录下,这样它才能根据配置去扫描子节点下的Spring的Bean
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

新建com.study.spring.cloud.weather.service包,在包下新建接口CityClient

package com.study.spring.cloud.weather.service;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

//指明服务地址
@FeignClient("mas-weather-city-eureka")
public interface CityClient {

	@GetMapping("/cities")
	String listCity();
}

com.study.spring.cloud.weather.controller包下新建类CityController

package com.study.spring.cloud.weather.controller;

import com.study.spring.cloud.weather.service.CityClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

//用于处理rest请求的controller
@RestController
public class CityController {

	@Autowired
	private CityClient cityClient;

	@GetMapping("/cities")
	public String listCity() {
		//通过Feign客户端来查找
		String body=cityClient.listCity();
		return body;
	}
	
}

修改application.properties配置文件:

#应用名称
spring.application.name=micro-weather-eureka-client-feign

#注册服务器的URL
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

#请求服务时的超时时间
feign.client.config.feignName.connect-timeout=5000

#读数据时的超时时间
feign.client.config.feignName.read-timeout=5000

运行

  1. 先在IDE上运行micro-weather-eureka-server
  2. 再通过命令行运行msa-weather-city-eureka
    因为之前已经编译过,直接进入E:\workspace\workspace-study\springcloud-study\imooc-spring-cloud-study\msa-weather-city-eureka\build\libs目录,
    再通过命令java -jar msa-weather-city-eureka-1.0.0.jar --server.port=8081运行jar包即可
  3. IDE上运行micro-weather-eureka-client-feign,运行结果如下:
    在这里插入图片描述
  4. 访问http://localhost:8761页面,可以看到Eureka的管理页面:
    在这里插入图片描述
  5. 访问http://localhost:8080/cities页面:
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43415405/article/details/84028709