SpringCloud
(1)什么是SpringCloud
Spring Cloud是将现在非常流行的一些技术整合到一起,实现了诸如:配置管理,服务发现,智能路由, 负载均衡,熔断器,控制总线,集群状态等功能
(2)SpirngCloud能做什么事
协调分布式环境中各个系统,为各类服务提供模板性配置。
(3)如何实现,怎么做
微服务架构:
微服务虽小,五脏俱全。
解决的问题:微服务与微服务之间的系统调用
RPC:多个服务器之间通过网络调用的一种协议
Remote Produce Call远程过程调用,RPC基于Socket,工作在会话层。自定义数据格式,速度快,效 率高。早期的webservice,现在热门的dubbo,都是RPC的典型代表
Socket / ServerSocket
Webservice
…
HTTP: 没有语言限制
http其实是一种网络传输协议,基于TCP,工作在应用层,规定了数据传输的格式。现在客户端浏览器 与服务端通信基本都是采用Http协议,也可以用来进行远程服务调用。缺点是消息封装臃肿,优势是对服务的 提供和调用方没有任何技术限定,自由灵活,更符合微服务理念。
HttpClient
OkHttp
public class MyTest {
//测试类中发送请求从http://localhost:8081/user/findById/4获取数据
//HttpClient
//1.导入对应的jar包
/*
org.apache.httpcomponents
httpclient
*/
//2.编写API实现远程调用
@Test
public void testHttpClient() throws Exception{
//1.创建HttpClient对象
HttpClient client = HttpClients.createDefault();
//2.创建一个请求对象
HttpGet httpGet = new HttpGet("http://localhost:8081/user/findById/4");
//3.发送请求
HttpResponse response = client.execute(httpGet);
//4.获取结果
String result = EntityUtils.toString(response.getEntity());
//5.将结果打印到控制台
System.out.println("====>"+result);
}
//okHttp
//1.导入对应的jar包
/*
com.squareup.okhttp3
okhttp
3.9.1
*/
//2.编写API实现远程调用
@Test
public void testOkHttp() throws Exception{
//1.创建一个OkHttpClient对象
OkHttpClient client = new OkHttpClient();
//2.创建一个请求对象
Request request = new Request.Builder().url("http://localhost:8081/user/findById/4").build();
//3.发送请求,获取结果
Response response = client.newCall(request).execute();
//4.解析结果
String result = response.body().string();
System.out.println("--->"+result);
}
}
封装:RestTemplate
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
@Autowired
private RestTemplate restTemplate;
@Test
public void test(){
User user = restTemplate.getForObject("http://localhost:8081/user/findById/4", User.class);
System.out.println(user);
System.out.println("========================");
ResponseEntity<User> entity = restTemplate.getForEntity("http://localhost:8081/user/findById/4", User.class);
System.out.println(entity.getStatusCodeValue());
System.out.println(entity.getBody());
}
RestTemplate默认使用的是HttpClient
如何让RestTemplate底层使用OkHttp来发送请求? 【据说OkHttpClient是目前效率最高的一种Http客户端】
@Bean
public RestTemplate restTemplate(){
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
SpringCloud
SpringCloud目的:治理/管理微服务。
SpringCloud不是一个具体的框架,而是很多组件的集合总成。
Spring / SpringBoot /SpringCloud
Eureka:注册中心(***)
父工程
聚合:
统一管理子项目的相关操作
继承:
管理子项目所依赖jar包的版本管理
pom.xml
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
<mapper.starter.version>2.1.5</mapper.starter.version>
<mysql.version>5.1.46</mysql.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>${mapper.starter.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
服务提供者
根据用户ID从数据库表中查询用户的基本信息。
(1)创建一个数据库,创建一个表
(2)搭建一个Maven(SpringBoot->jar)
(3)Controller–>ServiceInterface–>ServiceImpl–>Mapper[通用Mapper]–>domain
需求:可以访问http://localhost:9091/user/8输出用户数据
实现步骤:
添加启动器依赖(web、通用Mapper);
创建启动引导类和配置文件;
修改配置文件中的参数;
编写测试代码(UserMapper,UserService,UserController);
测试
服务的消费者
(1)搭建一个Maven(SpringBoot->jar)
(2)Controller–>RestTemplate远程调用服务提供者–>domain
EurekaServer
EurekaClient
EurekaServer的环境搭建
(1)创建一个maven项目(springboot/jar)
(2)pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
spring-cloud-starter-netflix-eureka-server 服务端
spring-cloud-starter-netflix-eureka-client 客户端
(3)引导类上(启动类)
@EnableEurekaServer 服务端
@EnableDiscoveryClient 客户端
(4)application.yml
spring:
application:
name: eureka-server #当前应用的名称,一般和项目名保持一致
server:
port: 10086 #项目的端口
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka #EurekaServer的访问地址
register-with-eureka: false #是否要将自己注册到EurekaServer,默认是true
fetch-registry: false # 是否从EurekaServer中拉取服务地址,默认是true
Eureka的高可用环境搭建。
执行流程:
服务消费方根据EurekaServer上注册的服务名称ServerName,根据ServerName找到服务提供者的服务列表,找到服务列表后,从服务列表中获取一个具体的服务对应的IP和端口,然后进行远程调用。
@RestController
@RequestMapping("/client")
public class ClientController {
/**
* 注入restTemplate
*/
@Autowired
private RestTemplate restTemplate;
/**
* 注入discoveryClient 可以使用discoveryClient根据服务名称获取指定的服务
*/
@Autowired
private DiscoveryClient discoveryClient;
/**
* 使用restful风格书写请求路径
* @param id 参数id
* @return user对象
*/
@RequestMapping("{id}")
public User findUserById(@PathVariable long id){
// 使用discoveryClient的方法根据服务名称获取指定的服务
List<ServiceInstance> instances = discoveryClient.getInstances("userService");
// 因为客户端目前没有搭建集群,所以可以使用get(0)获取其中的userService服务
ServiceInstance serviceInstance = instances.get(0);
// 拼接请求url
String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/user/" + id;
// 使用getForObject可以返回指定的响应体数据,使用getForEntity可以返回服务器响应的详细数据
return restTemplate.getForObject(url,User.class);
}
}
优点:可以动态的获取服务端的ip以及端口号,
缺点: 往往会开启很多个 user-service 的集群。此时获取的服务列表中就会有多个,到底该访问哪一个 ,====>>> 引入ribbon 进行负载均衡
EurekaServer的高可用环境搭建
eureka:
instance:
prefer-ip-address: true
ip-address: 127.0.0.1
Ribbon [不用 Feign] (*)
当服务的提供者注册到EurekServer以后,服务的消费者会根据服务注册的名称来获取服务提供者的服务列表。从服务列表中根据【对应的算法来获取一个具体的IP和端口】,获取到IP和端口后就可以实现远程调用。
Ribbon: 轮询、随机
怎么用?
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate():
}
ip:port使用注册在EurekaServer上的服务名称来获取
restTemplate.getForObject(“http://ServerName/…”,返回类型.class);
想看源码
LoadBalancerInterceptor