一、如何简单地理解SpringCloud - 基于Spring Boot实现的服务治理工具包,用于微服务架构中管理和协调服务
微服务,顾名思义,可以简单地理解成“微小的服务”,即是将一个完整的功能服务进行拆分。如一家饭店只有一个厨师,他的工作是洗菜、切菜和炒菜,那么在客人<访问量>多了之后,必然会存在忙不过来和忙中出错的情况。
那怎么解决这个问题呢?明显是可以通过招厨师的方式来解决。而招来厨师之后,又可有两种方式来分配工作任务:
1. 将总工作拆分,再将各项工作分工。比如专门让1个厨师来洗菜、1个厨师来切菜、1个厨师来炒菜,即是将一套完整的厨师工作(此处假设厨师就这三项工作)拆分后分配出去。而在代码中,这就叫“分布式”,简单地理解就是要记住“拆分”二字。
例如,一个订单服务,假设在完整时包含了订单生成、订单结算和订单日志三项业务,在应对高并发时<访问量大>,我们将完整的服务一分为三,每项业务单成项目,这就是“分布式”。
2. 将职务分配。比如招来3个厨师,每个厨师都从事相同且完整的工作,即是每人厨师都要洗菜、切菜和炒菜。在代码中,这就叫“集群”,简单地理解就是“一气化三清”(神话乱入)。
例如,还是一个订单服务,完整时包含了订单生成、订单结算和订单日志三项业务,在应对高并发时<访问量大>,我们将完整的服务复制成三份,真就来个“一气化三清”,个个都一样,也就是“集群”。
从上面我们不难看出,微服务就是分布式的一种实现,上大佬原话:
Martin Fowler : 就目前而言,对于微服务业界并没有一个统一的、标准的定义(While there is no precise definition of this architectural style ) 。但通常而言, 微服务架构是一种架构模式或者说是一种架构风格,它提倡将单一应用程序划分成一组小的服务,每个服务运行独立的自己的进程中,服务之间互相协调、互相配合,为用户提供最终价值。服务之间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 RESTful API ) 。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等。
另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建,可以有一个非常轻量级的集中式管理来协调这些服务。可以使用不同的语言来编写服务,也可以使用不同的数据存储。
二、微服务的优缺点
1)优点:简而言之,即是实现了解耦、支持高并发、扩展能力强、单个服务业务简单等。
2)缺点:一个字,贵;两个字,麻烦。贵在开发成本、运维成本、技术成本等。麻烦在部署麻烦等方面。
三、EurekaServer基础案例实现
1)微服务的常用组件的简单图解:
而本次我们要实现的就是EurekaServer基础案例,EurekaServer是用来实现动态添加、删除和管理微服务的通信地址,你就可以简单地理解成一个专门储存和管理民众信息的档案局。
2)上操作
①建项目:
②导依赖:
在parent项目中
<!--1. 管理 SpringBoot 的 jar 包 --> <!--SpringBoot--> <parent> <groupId> org.springframework.boot </groupId> <artifactId> spring-boot-starter-parent </artifactId> <version> 2.2.5.RELEASE </version> </parent> <!--2. 管理 SpringCloud 的 jar 包 --> <dependencyManagement> <dependencies> <dependency> <groupId> org.springframework.cloud </groupId> <artifactId> spring-cloud-dependencies </artifactId> <version> Hoxton.SR3 </version> <type> pom </type> <scope> import </scope> </dependency> </dependencies> </dependencyManagement> <!--3. 这里是所有子项目都可以用的 jar 包 --> <dependencies> <dependency> <groupId> junit </groupId> <artifactId> junit </artifactId> <version> 4.12 </version> <scope> test </scope> </dependency> <dependency> <groupId> org.projectlombok </groupId> <artifactId> lombok </artifactId> </dependency>
在eureka项目中
<!--spring-cloud-starter-netflix-eureka-server --> <dependency> <groupId> org.springframework.cloud </groupId> <artifactId> spring-cloud-starter-netflix-eureka-server </artifactId> </dependency> <dependency> <groupId> org.springframework.boot </groupId> <artifactId> spring-boot-starter-web </artifactId> </dependency>
在order项目中
<dependency> <groupId> junit </groupId> <artifactId> junit </artifactId> <version> 3.8.1 </version> <scope> test </scope> </dependency> <!--spring-cloud-starter-netflix-eureka-server --> <dependency> <groupId> org.springframework.cloud </groupId> <artifactId> spring-cloud-starter-netflix-eureka-client </artifactId> </dependency> <dependency> <groupId> org.springframework.boot </groupId> <artifactId> spring-boot-starter-web </artifactId> </dependency> <!-- 公共的实体类 --> <dependency> <groupId> com.jinitaimei </groupId> <artifactId> springcloud-netflix-pojo-user </artifactId> <version> 1.0-SNAPSHOT </version> </dependency> <!-- 集成 Ribbon--> <dependency> <groupId> org.springframework.cloud </groupId> <artifactId> spring-cloud-starter-netflix-ribbon </artifactId> </dependency>
在service-user项目中
<!--spring-cloud-starter-netflix-eureka-server --> <dependency> <groupId> org.springframework.cloud </groupId> <artifactId> spring-cloud-starter-netflix-eureka-client </artifactId> </dependency> <dependency> <groupId> org.springframework.boot </groupId> <artifactId> spring-boot-starter-web </artifactId> </dependency> <!-- 公共的实体类 --> <dependency> <groupId> com.jinitaimei </groupId> <artifactId> springcloud-netflix-pojo-user </artifactId> <version> 1.0-SNAPSHOT </version> </dependency>
③建实体类 - 在pojo-user中
public class User { private Long id ; private String username ; private String desc ; public User () { } public User (Long id , String username , String desc) { this . id = id ; this . username = username ; this . desc = desc ; } public Long getId () { return id ; } public void setId (Long id) { this . id = id ; } public String getUsername () { return username ; } public void setUsername (String username) { this . username = username ; } public String getDesc () { return desc ; } public void setDesc (String desc) { this . desc = desc ; } }
④配置文件 - pojo-user项目只需要一个实体类就行了,无需导依赖和配置文件
在eureka项目中 - application.yml
server : port : 10010 eureka : instance : hostname : localhost client : registerWithEureka : false fetchRegistry : false serviceUrl : defaultZone : http://localhost:10010/eureka/ server : enable-self-preservation : false
在order项目中 - application.yml
eureka : client : serviceUrl : defaultZone : http://localhost:10010/eureka/ instance : prefer-ip-address : true instance-id : order-server:10020 spring : application : name : order-server server : port : 10020
在service-user项目中 - application.yml
eureka : client : serviceUrl : defaultZone : http://localhost:10010/eureka/ instance : prefer-ip-address : true instance-id : user-server1:10031 spring : application : name : user-server server : port : 10031
⑤controller接口 - 这个案例是order调user
order项目中
@RestController public class OrderController { // 需要配置成 Bean @Autowired private RestTemplate restTemplate ; // 用作负载均衡 // 浏览器调用该方法 @RequestMapping (value = "/order/{id}" , method = RequestMethod. GET ) public User getById ( @PathVariable ( "id" )Long id){ // 发送 http 请求调用 user 的服务,获取 user 对象 : RestTemplate //user 的 ip,user 的端口, user 的 Controller 路径 //String url = "http://localhost:1020/user/"+id; String url = "http://user-server/user/" +id ; // 发送 http 请求 return restTemplate .getForObject(url , User. class ) ; } }
service-user项目中
// 用户服务:暴露接口给订单访问 @RestController public class UserController { // 读取 application.yml 文件的端口号 @Value ( "${server.port}" ) private int port ; // 订单服务来调用这个方法 http://localhost:1020/user/10 @GetMapping (value = "/user/{id}" ) public User getById ( @PathVariable ( "id" ) Long id) { return new User(id , "id:" + id , " 我的 port:" + port ) ; // 端口随 User 返回 } }
⑥开启service-user项目启动类集群功能
先在service-user项目的启动类启动之后,修改这两处数据
然后按步骤点开(如果idea版本不一样,位置可能不一样)
(idea右上角) (选择需要集群的启动类)
(弹框的右侧偏上处)
(勾上这个并确认更改)
最后,在不关闭之前已经开启的service-user的启动类,再次启动一次,效果在Services中预览如下:
(两个UserApp启动类)
最后的最后,去浏览器看成果
和
就这样吧,如果对您有帮助,鄙人不胜荣幸!