第一部分 SpringCloud概述
今日任务:SpringCloud
1、Eureka注册中心,ZooKeeper:分布式设计定理CAP
2、Ribbon负载均衡器,Nginx:前段负载均衡器
3、Feign封装REST,接口
为什么需要SpringCloud?
1、Dubbo阿里微服务框架【基于RPC实现微服务+Zk注册中心,dobbox:当当,携程,支持streaming流食编程】
2、Spring Cloud 是Spring的【EureKa注册中心、Ribbon复杂均衡、Feign支持REST封装、ZuulAPI网格gateway、Hystrix断路器、熔断器、Sidecar异构开发语言支持】
SpringCloud微服务框架主流,SpringCloud基于REST+JSON,性能RPC,dubbo基于RPC的最佳实践。Dubbo:SpringCloud子集,专注RPC解决方案。
什么是SpringCloud?
SpringCloud是构建分布式系统的工具集。 SpringCloud开发者全家桶,把业界主流最好的技术整合起来。
如:配置中心springcloud-config,服务发现eareka,断路器hystrix,智能路由(网关)zuul,微代理,控制总线(BUS)rabbitmq,令牌,分布式全局锁,选举,分布式session,集群状态
微服务优点?
小,独立,代码量小
-单体项目
-京淘:业务垂直拆分,水平拆分
-微服务
- 比JT的垂直拆分的粒度更细
- 故障隔离,比业务垂直拆分粒度更细
- 数据库就应该拆分
- 微服务不同服务器,网络传输,安全差,性能差。服务之间互相不应调用太频繁。
结合:垂直拆分+微服务(70%)
什么是CAP?
引入: MySQL的强一致性,设计数据库的三范式,3NF。
表必须有主键;表不能有重复列;列不能是加工而成)
主流数据库表的设计方式:反三范式,冗余设计(性能高。缺点:数据多,同步数据会有时间差,短暂数据不一致)
最终一致性,允许短暂时间内数据可以不一致,但是过了这个时间阈值,数据必须一致
可用性,zk主从设计,如果zk节点有一半点宕机或者有节点正在选举,此时zk集群不可用!
EureKa,peer to peer 点对对设计,每个点的信息都可以用户接入,每个点如果信息变化,它内部会自动同步所有的数据。Eureka即使所有节点都宕机,仍然能够提供服务。EurekaClien客户端缓存了所有的数据信息,也能找到服务的提供者。试一下。
业务:注册中心,动态维护(心跳机制)
1、服务提供者url
2、服务消费者url
注册中心信息会频繁发生变化吗?–> 信息不会频繁发生变化。
结论:
1、分布式设计定理CAP,P分区容错性必须实现
2、ZooKeeper基于CP设计,侧重一致性
3、Eureka基于AP设计,侧重可用性。
第二部分 SpringBoot构建Eureka
以上为常用选项。
Eureka包含两个组件:Eureka Server和Eureka Client。
调用关系说明:
1.服务提供者在启动时,向注册中心注册自己提供的服务。
2.服务消费者在启动时,向注册中心订阅自己所需的服务。
3.注册中心返回服务提供者地址给消费者。
4.服务消费者从提供者地址中调用消费者。
注意! 下面的服务端指:注册中心,客户端指:服务提供者和消费者
Eureka Server:
提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,包括主机与端口号、服务版本号、通讯协议等。这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka服务端支持集群模式部署,首尾相连形成一个闭环即可,集群中的的不同服务注册中心通过异步模式互相复制各自的状态,这也意味着在给定的时间点每个实例关于所有服务的状态可能存在不一致的现象。
Eureka Client:
主要处理服务的注册和发现。客户端服务通过注册和参数配置的方式,嵌入在客户端应用程序的代码中。在应用程序启动时,Eureka客户端向服务注册中心注册自身提供的服务,并周期性的发送心跳来更新它的服务租约。同时,他也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期行的刷新服务状态。
服务调用:
服务消费者在获取服务清单后,通过服务名可以获取具体提供服务的实例名和该实例的元数据信息。因为有这些服务实例的详细信息,所以客户端可以根据自己的需要决定具体调用哪个实例,在Ribbon中会默认采用轮询的方式进行调用,从而实现客户端的负载均衡。
作者:pengyuyancode
链接:https://www.jianshu.com/p/c18d140ad9f6
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
一、Eureka Server 服务
1、配置pom
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
父依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
设定字符编码格式,控制java版本
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
配置Eureka Server
<!-- springCloud要求增加对应依赖管理包 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
springCloud要求增加对应依赖管理包
2、resource文件下application.yaml文件
security:
basic:
enabled: true
user:
name: user
password: password123
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://user:password123@localhost:8761/eureka
logging:
level:
root: INFO
疑问:yaml文件属性配置咋搞的?
存疑,回家看书解答。
3、RunApplicationEureka
@SpringBootApplication
@EnableEurekaServer //标识EurekaServer
public class RunApplicationEurekaServer {
public static void main(String[] args) {
// TODO Auto-generated method stub
SpringApplication.run(RunApplicationEurekaServer.class, args);
}
}
4、运行结果
二、Eureka Provider 提供者
1、pom配置
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- springCloud要求增加对应依赖管理包 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2、yml配置
server:
port: 7900
spring:
application:
name: provider-user
eureka:
client:
serviceUrl:
defaultZone: http://user:password123@localhost:8761/eureka
logging:
level:
root: INFO
3、RunApplication配置
@SpringBootApplication
@EnableEurekaClient//启动Eureka客户端
public class RunApplicationProviderUser {
public static void main(String[] args) {
// TODO Auto-generated method stub
SpringApplication.run(RunApplicationProviderUser.class, args);
}
}
4、运行
相同与不同:
1、pom的不同
- server的依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
- client的依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2、yml的相同与不同
不同:
- 服务端会有安全访问设置,需要用户名密码才能登陆。客户端没有
- 服务端和客户端端口号不一样
相同:
服务端与客户端service-url是一致的,而且都规定了用户名和密码。
3、runApplication的不同
@EnableEurekaServer //标识EurekaServer
@EnableEurekaClient //启动Eureka客户端
案例:提供者2 代码综合如下:
1、pom与provide1完全相同
2、与provide1端口号不同,spring:application: name:一样
3、run入口与provide1完全相同
4、controller返回提示不同其他完全相同
三、Eureka Client 消费者
1、pom配置
Client 消费者pom文件配置 与 提供者pom配置一致。
2、yml配置
server:
port: 8010
spring:
application:
name: consumer-user
eureka:
client:
serviceUrl:
defaultZone: http://user:password123@localhost:8761/eureka
logging:
level:
root: INFO
端口号和服务名称需要改动。
访问的url还是server的url
3、controller配置
@RestController
public class HelloController {
@Autowired//通过模板对象去调用另一个服务器请求,结构和httpClient相似
private RestTemplate restTemplate;
// 调用服务提供者
@RequestMapping("/hello/{name}")
public String name(@PathVariable String name) {
String url ="http://localhost:7900/hello/"+name;//服务提供者访问的地址 provider
return restTemplate.getForObject(url, String.class);
}
}
此处的不同:
- restTemplate.getForObject(url, responseType)
- 其中url是provider的访问地址
- responseType是数据封装返回的类型,由 provider对应方法的类型
- 使用@Autowired 添加模板对象RestTemplate 去调用另一个服务器请求 【所以在入口类应有方法初始化RestTemplate 】
4、入口类配置
@SpringBootApplication
@EnableEurekaClient
public class RunApplicationConsumerClient {
@Bean //让spring创建模板对象
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
SpringApplication.run(RunApplicationConsumerClient.class, args);
}
}
5、运行结果【需在server运行、provide也运行的情况下】
server
provider
client
如何确定client是依靠provider访问呢?
停掉provider进行访问,如下图:
注:如果两个Provider的yaml中命名一样,不影响。还可以通过此配置设置负载均衡轮询。
为什么要两台Provider?让Client访问实现负载均衡。
========================================================
支持负载均衡Ribbon
1、支持能通用访问
url=“http://provider-user/hello/”+name;
2、配置要让这个Application.name进行解析,到EureKa换成对应的地址,在入口类中添加注解@LoadBalance,支持负载均衡
运行结果:
server 8761
provider 7900
provider 7901
client 是否轮询了
EureKa自带Ribbon实现负载均衡【可在依赖中查找】
=======================================
Ribbon和Nginx比较?
如果实现负载均衡后,在运行过程中,停掉provider其中之一,那么在访问的过程中,短时间内不会停止轮询,仍然可以访问到provider的服务,显示页面未找到。
如果又启动了provider,那么会很快恢复访问正常显示页面。
1、Nginx基于C语言,快速,性能高5W
2、Redis 5W/秒。RibbatMQ 1.2万/秒。ApacheActiveMQ 0.6万每秒 业务系统。Kafka 20~50万每秒大数据。Zuul 200万每秒。
负载均衡、反向代理,代理后端服务器。隐藏真实地址,防火墙,真实地址外网不能直接访问,保证安全性。
3、Ribbon负载均衡,前端,客户端开始导向(转向)
【Nginx需要路由,消费者不可用Nginx并不知道反馈。但Ribbon却可以将EureKaClient有本地缓存就可同步到RibbonClient,直接将信息发往提供者,选择了最佳路由,性能更高】
第三部分 Feign
一、基本概念
1、Feign封装rest支持
声明式的web service客户端。web service属于J2ee框架中的JAX-WS,主流最佳实践ApacheCXD,解决异构开发语言直接调用。已被市场淘汰。WS基于HTTP协议,之上SOAP简单对象访问协议,HTTP+header,基于XML,异构语言传递,xml本身标签过多,传输无用信息过多,效率低,转换不同语言对象结构非常浪费时间,被淘汰。取而代之:JSon,HttpClient+REST+JSon
2、Feign写ws程序更加简单。创建接口和注释。RS RESTFul是ws子集。Feign实现了URL和解码,中文乱码仿版解决。程序传递时没有类型,request.getParameter(“name”)得到的是String。HttpMessageConverters对象会强传类型,如果转换失败,会报404错误。
RequestMapping get/post通用
SpringMvcb高版本又出现了新的注解
@GetMapping
@PostMapping
二、Cilent Feign
springcloud没有直接使用NetFlix公司原生hystrix,使用javanica封装过的
配置
1、pom与client的完全一样
2、yaml文件,端口号改为9001
spring:
application:
name: consumer-feign
3、Feign接口
//feign的接口
@FeignClient("provider-user")//找到提供者,通过EureKa
public interface HelloFeign {
//对提供者调用
@RequestMapping("/hello/{name}")
public String hello(@PathVariable("name") String name);
}
4、Controller
@RestController
public class HelloController {
//添加与Fine的关联,实现Fine接口
@Autowired
private HelloFeign helloFeign;
@RequestMapping("/hello/{name}")
public String hello(@PathVariable String name) {
return helloFeign.hello(name);
}
}
5、入口函数
//添加Feign标志
@SpringCloudApplication
@EnableFeignClients//client - feign
public class RunApplicationClientFeign {
public static void main(String[] args) {
// TODO Auto-generated method stub
SpringApplication.run(RunApplicationClientFeign.class, args);
}
}
结果: