一、概念:
1、单体应用与微服务的区别:
单体应用 | 分布式/微服务 |
一个应用项目中的所有模块业务都在一个项目中,打包为一个WAR包,通过一个服务器部署。 | 把一个大的项目,按照业务或模块拆分成多个小服务,每个小服务能够拥有独立的进程,可以有自己的数据库。每个微服务只需要关注某一个业务即可,它只需要向往暴露接口,服务与服务之间通过网络协议进行通信。 |
优点:部署容易 |
1、复杂的可控 2、技术选型多样容易 3、每个服务独立部署,独立运行 4、扩展容易 5、容错效果好 |
1、当体量大时,维护困难, 2、项目大时,部署慢 3、部署到一个服务器,性能差,不利于扩展 4、一个模块崩溃,整个项目就崩溃,安全性差 5、责任不分离,增加开发难度 6、技术选型单一 7、数据库选型单一 | 缺点后补 |
2、微服务介绍:
①、实现微服务的架构 技术
Springboot+springCloud
Dubbo
Dubbox
SpringcloudAlibaba
②、springcloud与dubbo的区别:
springcloud | dobbo |
Springboot+springCloud (全球 国际) 在github上面活跃的人数是比较多,更新也是比较频繁,最主要是spring进行无缝衔接,现在使用的人是越来越多,对整体服务的注册,监控,配置 等操作提供了一套解决方案 |
Dubbo早期的时候,很厉害,针对国内互联网的公司,属于阿里巴巴,由于是商业性的公司,维护上面没有这么方便。后来才访问apache进行开源--国内。 |
全家桶,功能齐全。 | RPC框架,主要解决通信问题,需要与其他框架整合 |
基于HTTP通信协议,这方面比dubbo差 | 基于TCP/IP协议 |
二、SpringCloud:
1、认识:
一个基于Spring Boot实现的服务治理工具包。一系列框架的有序集合
2、五大神兽(常用五大组件,除了这些还有很多组件):
服务发现——Netflix Eureka
客服端负载均衡——Netflix Ribbon/Feign
服务网关——Netflix Zuul
断路器——Netflix Hystrix
分布式配置——Spring Cloud Config
三、初始环境搭建:
1、创建父项目,导入springboot+springcloud版本控制依赖:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.SR2</spring-cloud.version>
<springboot.version>2.0.6.RELEASE</springboot.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>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2、单机配置注册中心(依赖-yml配置-启动类):
<!--springboot支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--Eureka服务端支持-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
server:
port: 7001
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false #是否要注册到eureka
fetchRegistry: false #表示是否从Eureka Server获取注册信息
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #单机配置
@SpringBootApplication
@EnableEurekaServer//标识是eureka服务端
public class EnrekaServerApplication_7001 {
public static void main(String[] args) {
SpringApplication.run(EnrekaServerApplication_7001.class);
}
}
3、服务注册与发现:
①、每一个服务都需要注册到注册中心去,服务提供方为服务提供者,调用服务方为消费者,消费者也需要注册到注册中心 去,获取服务清单,根据请求调用具体服务进行消费。
②、消费者与提供者通过,RestTmplate进行调用,springcloud提供基于restful风格的HTTP工具连接来实现服务的调用。
③、服务提供者
server:
port: 2000
eureka:
instance:
prefer-ip-address: true #是否显示客户端IP
client:
serviceUrl:
defaultZone: http://eurekaserver1000:1000/eureka/
/**
* 服务提供者提供服务
*/
@RestController
public class ProviderUserController {
@Autowired
private IUserService userService;
@RequestMapping("/user/{id}")
public User findAll(@PathVariable("id") Long id){
return userService.findAll(id);
}
}
④、消费者
server:
port: 3000
eureka:
instance:
prefer-ip-address: true #是否显示客户端IP
client:
serviceUrl:
defaultZone: http://eurekaserver1000:1000/eureka/
/**
* 调用服务提供者接口
*/
@Configuration
public class ConfigBean {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
/**
* 消费者端--浏览器端调用
*/
@RestController
public class ConsumerUserController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/user/{id}")
public User findAll(@PathVariable("id") Long id){
String url = "http://localhost:2000/user/"+id;
User user = restTemplate.getForObject(url, User.class);
return user;
}
}
4、注册中心集群配置:
①、解决单节点故障问题,减轻单节点注册中心压力。
②、创建两个配置一样,端口不一样的注册中心模块,服务端双方都注册到对方注册中心。
server:
port: 1000
eureka:
instance:
hostname: eurekaserver1000
client:
registerWithEureka: false #是否要注册到eureka
fetchRegistry: false #表示是否从Eureka Server获取注册信息
serviceUrl:
defaultZone: http://eurekaserver1001:1001/eureka/
server:
port: 1001
eureka:
instance:
hostname: eurekaserver1001
client:
registerWithEureka: false #该注册中心不需要向自己注册
fetchRegistry: false #注册中心自己不需要去拉取访问的地址清单
serviceUrl: #注册中心的注册地址
defaultZone: http://eurekaserver1000:1000/eureka/
四、负载均衡:
1、负载均衡器介绍:
①、硬负载:硬件(路由器) ②、软负载:软件(服务端:Nginx,客户端:ribbon,feign)
2、ribbon实现负载均衡( @LoadBalanced //开启负载均衡):
@Configuration
public class CfgBean {
@Bean
@LoadBalanced //开启负载均衡
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
@RestController
@RequestMapping("/consumer")
public class UserController {
//多个方法调用只需改一处就ok
//public static final String URL_PREFIX = "http://localhost:1000";
public static final String URL_PREFIX ="http://PROVIDER"; //通过服务名从注册中心获取服务列表,通过负载均衡调用
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/user/{id}")
public User getUser(@PathVariable("id")Long id){
//调用远程服务 http请求
String url = URL_PREFIX+"/user/"+id;
return restTemplate.getForObject(url,User.class );
}
}
负载均衡提供了很多均衡策略
//随机策略
@Bean
public IRule myRule(){
return new RandomRule();
}
3、feign实现负载均衡:
①、让远程调用本地化,底层基于ribbon+resttemplate,接口方式进行调用。
<!--feign的支持-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
写一个接口
//调用服务名字
@FeignClient(value = "PROVIDER")
public interface UserCilent {
@RequestMapping("/user/{id}") //user/1
User getUser(@PathVariable("id") Long id);
}
消费端 fegin调用
@RestController
public class UserController {
@Autowired
private UserCilent userCilent;
@RequestMapping("/user/{id}")
public User getUser(@PathVariable("id")Long id){
return userCilent.getUser(id);
}
}