传统架构其实就是SSH架构或者SSM架构,属于单点应用,把整个业务模块都会在一个项目进行开发,分为MVC架构,会拆分为控制层,业务逻辑层,数据库访问层.
缺点:一般只适合于一个人或者小团队开发,耦合度太高,一旦某个模块导致服务不可用,可能会影响到其他项目
分布式架构
假如100人都在一个项目进行开发,可能会产生哪些问题--->代码冲突,任务不好分配,容易引起代码冲突
分布式架构是基于传统架构演变而来的,将传统的项目以项目模块进行拆分n多个子项目,比如会员模块,订单模块,优惠券模式,支付项目等;每个项目之中都有自己独立数据库,独立的redis等 ;
服务表达意思:包含业务员逻辑和视图层
服务表达意思:只包含业务逻辑层,没有视图层
分布式和传统架构的区别
项目粒度分的更加细,慢慢开始适合于互联网的开发,耦合度降低.
maven聚合项目一定是分布式项目吗?--->不一定,取决于你最后的打包,是否是一个包
SOA架构
SOA架构即面向服务架构,俗称服务化,可以理解为面向业务逻辑层.将共同的业务代码进行抽取出来,提供给其他接口进行调用,服务与服务之间通讯采用RPC远程调用技术
服务所代表的含义:将共同的业务逻辑进行一个拆分,拆分成一个独立的项目进行部署,可以把它理解为接口.
RPC远程调用技术框架:
httpclient,springcloud,dubbo,grpc 核心底层socket技术或者netty技术实现.
SOA架构特点:底层基于SOAP或者ESB(消息总线)实现,底层使用http或者https协议+重量级XML数据交换格式进行通讯.
WebService底层是采用Http协议+xml(SOAP),RPC是远程调用技术,两个或者多个实现远程调用.
微服务
微服务架构从SOA架构演变过来,比SOA架构上粒度更加的精细,让专业的人做专业的事情,目的是为了提高效率,每个服务与服务之间互不影响,每个服务必须独立部署(独立数据库,独立的redis),微服务架构更加体现轻量级,采用restful风格提供API,也就是http协议+JSON格式,更加轻巧,更加适合于互联网公司敏捷开发,快速迭代产品
微服务架构产生的原因
首先微服务架构是基于SOA架构演变过来的,
其中SOA架构的缺点有
1.依赖与中心化服务发现机制
2.因为SOA架构采用SOAP协议(http+xml),因为xml传输协议比较占宽带,整个xml报文中有非常大的冗余,所以在微服务里采用Json的格式来代替xml提文传输
3.服务管理非常混乱,缺少服务管理和治理设施十分的不完善
Eureka
服务注册和发现
RPC远程调用框架核心框架 核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的依赖关系
服务治理
传统的RPC远程调用框架中,管理每个服务与服务之间的之间的依赖关系比较复杂,如下图,随着服务的增多,对于服务之间的依赖关系变的更为复杂,使用服务治理技术,可以解决这个问题,可以实现负载均衡,服务的注册与发现,容错等;
在服务注册与发现中,有一个注册中心,当服务器启动的时候,会把当前自己服务器的信息 比如 服务地址通讯地址等以别名方式注册到注册中心上。
另一方(消费者|服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,让后在实现本地rpc调用远程。
目录结构
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> </parent> <!-- 管理依赖 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.M7</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!--SpringCloud eureka-server --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> <!-- 注意: 这里必须要添加, 否者各种依赖有问题 --> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/libs-milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
###服务端口号 server: port: 8100 ###eureka 基本信息配置 eureka: instance: ###注册到eurekaip地址 hostname: 127.0.0.1 client: serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ ###因为自己是为注册中心,不需要自己注册自己 register-with-eureka: false ###因为自己是为注册中心,不需要检索服务 fetch-registry: false
@SpringBootApplication /** * @EnableEurekaServer 表示这个类作为注册中心 */ @EnableEurekaServer public class EurekaServiceApplication { public static void main(String[] args) { SpringApplication.run(EurekaServiceApplication.class); } }
看到这个界面说明注册中心搭建成功
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> </parent> <!-- 管理依赖 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.M7</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- SpringBoot整合Web组件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- SpringBoot整合eureka客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <!-- 注意: 这里必须要添加, 否者各种依赖有问题 --> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/libs-milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
###服务启动端口号 server: port: 8000 ###服务名称(服务注册到eureka名称) spring: application: name: app-itmayiedu-member ###服务注册到eureka地址 eureka: client: service-url: defaultZone: http://localhost:8100/eureka ###因为该应用为注册中心,不会注册自己 register-with-eureka: true ###是否需要从eureka上获取注册信息 fetch-registry: true
@SpringBootApplication /** * @EnableEurekaClient 代表他注册到注册中心 */ @EnableEurekaClient public class ApplicationProvider { public static void main(String[] args) { SpringApplication.run(ApplicationProvider.class); } }
@RestController public class ProviderController { @RequestMapping("getMessage") public String getMessage(){ return "你好傻傻"; } }
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> </parent> <!-- 管理依赖 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.M7</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- SpringBoot整合Web组件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- SpringBoot整合eureka客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <!-- 注意: 这里必须要添加, 否者各种依赖有问题 --> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/libs-milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
###服务启动端口号 server: port: 8002 ###服务名称(服务注册到eureka名称) spring: application: name: app-itmayiedu-order ###服务注册到eureka地址 eureka: client: service-url: defaultZone: http://localhost:8100/eureka ###因为该应用为注册中心,不会注册自己 register-with-eureka: true ###是否需要从eureka上获取注册信息 fetch-registry: true
@SpringBootApplication @EnableEurekaClient public class ApplicationConsumer { public static void main(String[] args) { SpringApplication.run(ApplicationConsumer.class); } /** * *在这里如果不把RestTemplate注入到Spring容器,提供方启动便会报错 **/ @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
/** * 调用的第一种方式 */ @RestController public class ConsumerController { @Autowired private RestTemplate restTemplate; @RequestMapping("/getOrder") public String getOrder(){ String memeberUrl = "http://127.0.0.1:8000/getMessage"; String result = restTemplate.getForObject(memeberUrl, String.class); System.out.println("会员服务调用订单服务,result:" + result); return result; } }
@Autowired private RestTemplate restTemplate; @RequestMapping("/getOrder") public String getOrder(){ String memeberUrl = "http://app-itmayiedu-member/getMessage"; String result = restTemplate.getForObject(memeberUrl, String.class); System.out.println("会员服务调用订单服务,result:" + result); return result; }
在进行第二种别名启动的时候,其实程序会报错,报错信息如下
其原因在于如果想要以别名的方式,进行访问,其依赖Ribbon的依赖.此时我们需要在RestTemplate前加上@LoadBalanced注解,表示开启负载均衡
@Bean /** * 别名访问,依赖Ribbon,需要使用该注解,开启负载均衡 */ @LoadBalanced public RestTemplate getRestTemplate(){ return new RestTemplate(); }
@RestController public class ProviderController { @Value("${server.port}") private String serverPort; //利用端口号进行区别 @RequestMapping("getMessage") public String getMessage(){ return "你好傻傻"+serverPort; } }
依次进行通过服务方访问提供方,其结果动态变化
同样的道理,Eureka8100 (8100指的是端口号,下文也是如此) 连接 Eureka8200
此时进入注册中心,看见此效果则代码集群搭建成功
为了防止EurekaServer与EurekaClient在网络不通的情况下,EurekaServer误将EurekaClient服务进行剔除自我保护机制:默认情况下我EurekaClient定时的向EurekaServer发送心跳包,以检测EurekaClient的状态,如果EurekaServer在一定的时间内没有收到EurekaClient心跳包的化,此时便会直接便会从注册列表进行服务剔除,默认是90s,但是如果在短时间内丢了大量的服务实例心跳,这时候EurekaServer端会开启自我保护机制,不会区剔除该服务
在本机环境中,禁止开启自我保护机制,因为自己本地进行代码的修改的时候,会频繁的开启自我保护机制
利用以上的配置的信息,既可以对Eureka的自我保护,进行设置
问题引出:如果服务器真的宕机,而不是网络影响,我们该如何解决呢? 本地应有有重试机制,保证接口网络延迟的幂等性,做好服务降级等功能,或者轮训到下一台服务器做Master主机
.