
//质检部门环境配置。等同线上布局。

服务注册与发现是分为注册和发现两个关键的步骤。
服务注册:服务进程在注册中心注册自己的元数据信息。通常包括主机和端口号,有时还有身份验证信息,协议,版本号,以及运行环境的信息。
服务发现:客户端服务进程向注册中心发起查询,来获取服务的信息。服务发现的一个重要作用就是提供给客户端一个可用的服务列表。
服务注册有两种形式:客户端注册和代理注册。
客户端注册(调用方实现)
客户端注册是服务自己要负责注册与注销的工作。当服务启动后注册线程向注册中心注册,当服务下线时注销自己。

这种方式的缺点是注册注销逻辑与服务的业务逻辑耦合在一起,如果服务使用不同语言开发,那需要适配多套服务注册逻辑。
代理注册
代理注册由一个单独的代理服务负责注册与注销。当服务提供者启动后以某种方式通知代理服务,然后代理服务负责向注册中心发起注册工作。

这种方式的缺点是多引用了一个代理服务,并且代理服务要保持高可用状态。
服务发现也分为客户端发现和代理发现。
客户端发现(调用方实现)
客户端发现是指客户端负责向注册中心查询可用服务地址,获取到所有的可用实例地址列表后客户端根据负载均衡算法选择一个实例发起请求调用。

这种方式非常直接,客户端可以控制负载均衡算法。但是缺点也很明显,获取实例地址、负载均衡等逻辑与服务的业务逻辑耦合在一起,如果服务发现或者负载平衡有变化,那么所有的服务都要修改重新上线。
代理发现
代理发现是指新增一个路由服务负责服务发现获取可用的实例列表,服务消费者如果需要调用服务A的一个实例可以直接将请求发往路由服务,路由服务根据配置好的负载均衡算法从可用的实例列表中选择一个实例将请求转发过去即可,如果发现实例不可用,路由服务还可以自行重试,服务消费者完全不用感知。

如果服务有多个实例,其中一个实例出现宕机,注册中心是可以实时感知到,并且将该实例信息从列表中移出,也称为摘机。
如何实现摘机?业界比较常用的方式是通过心跳检测的方式实现,心跳检测有主动和被动两种方式。
被动检测是指服务主动向注册中心发送心跳消息,时间间隔可自定义,比如配置5秒发送一次,注册中心如果在三个周期内比如说15秒内没有收到实例的心跳消息,就会将该实例从列表中移除。

上图中服务A的实例2已经宕机不能主动给注册中心发送心跳消息,15秒之后注册就会将实例2移除掉。
主动检测是注册中心主动发起,每隔几秒中会给所有列表中的服务实例发送心跳检测消息,如果多个周期内未发送成功或未收到回复就会主动移除该实例。

相信大家平时开发的时候没少碰见,在微服务架构中需要调用很多服务才能完成一项功能。这时候,如何互相调用就变成微服务架构中的一个关键问题。在这里我介绍三个常用的方法
- @Bean
- public RestTemplate getRestTemplate(){
- return new RestTemplate();
- }
服务的消费者(order)调用服务的提供者(Goods)
- @Autowired
- private RestTemplate restTemplate;
-
- @GetMapping("/createOrder/{gid}/{number}")
- public Order order(@PathVariable("gid") Integer id,@PathVariable("number") Integer number){
- log.info("用户开始下单,调用商品系统,查询{}号商品信息",id);
- Goods goods = restTemplate.getForObject("http://localhost:9002/goods/getGoods/" + id, Goods.class);
- log.info("商品信息查询完毕:"+ JSON.toJSONString(goods));
-
- log.info("开始下单:");
- Order order = new Order();
- order.setUid(1);
- order.setUname("测试用户");
- order.setGid(goods.getId());
- order.setGname(goods.getGoodsName());
- order.setNumber(number);
-
- orderService.createOrder(order);
- log.info("下单成功");
- return order;
- }
通过上面的方式我们解决了微服务之间的相互调用,但是存在硬编码的问题,如果服务提供者的地址发生变化,就需要手工修改代码;如果有多个服务提供者,无法实现服务的负载均衡;如果服务增多,人工调用会变得更加的复杂。
这个时候就会需要服务治理,服务治理是微服务架构最核心的问题,用于实现各个微服务的自动化注册与发现。在这里选择Nacos。
1.在服务的提供者与消费者的pom文件中引入依赖
- <!--nacos客户端-->
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
- </dependency>
2.在application.yml中添加配置
- spring:
- cloud:
- nacos:
- discovery:
- server-addr: 192.168.206.151:8848
3.在对应的微服务上添加
@EnableDiscoveryClient
4.代码
- @Autowired
- private RestTemplate restTemplate;
- @Autowired
- private DiscoveryClient discoveryClient;
-
- @GetMapping("/createOrder2/{gid}/{number}")
- public Order order2(@PathVariable("gid") Integer id,@PathVariable("number") Integer number){
- log.info("用户开始下单,调用商品系统,查询{}号商品信息",id);
- //从nacos中获取服务地址
- ServiceInstance service = discoveryClient.getInstances("goods-service").get(0);
- String url = service.getHost() + ":" + service.getPort();
- //通过restTemplate调用
- Goods goods = restTemplate.getForObject("http://"+url+"/goods/getGoods/" + id, Goods.class);
- log.info("商品信息查询完毕:"+ JSON.toJSONString(goods));
-
- log.info("开始下单:");
- Order order = new Order();
- order.setUid(1);
- order.setUname("测试用户");
- order.setGid(goods.getId());
- order.setGname(goods.getGoodsName());
- order.setNumber(number);
-
- orderService.createOrder(order);
- log.info("下单成功");
- return order;
- }
注:DiscoveryClient是专门负责服务注册和发现的,我们可以通过它获取到注册到注册中心的所有服务
Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务一样简单, 只需要创建一个接口并添加一个注解即可。
Nacos很好的兼容了Feign, Feign默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负载均衡的效果。
在服务消费者上进行以下操作
1.添加依赖
- <!--fegin组件-->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-openfeign</artifactId>
- </dependency>
2.在启动类上添加注解
@EnableFeignClients
3.新建client包,并创建接口(把服务提供者controller对应的方法名复制过来,注意路径要完整。
- @FeignClient("goods-service")
- public interface GoodsService {
-
- @RequestMapping("/goods/getGoods/{id}")
- public Goods goods(@PathVariable("id") Integer id);
- }
4.代码
- @Autowired
- private GoodsService goodsService;
-
- @GetMapping("/createOrder3/{gid}/{number}")
- public Order order3(@PathVariable("gid") Integer id,@PathVariable("number") Integer number){
- log.info("用户开始下单,调用商品系统,查询{}号商品信息",id);
-
- //通过feign调用商品微服务
- Goods goods = goodsService.goods(id);
- log.info("商品信息查询完毕:"+ JSON.toJSONString(goods));
-
- log.info("开始下单:");
- Order order = new Order();
- order.setUid(1);
- order.setUname("测试用户");
- order.setGid(goods.getId());
- order.setGname(goods.getGoodsName());
- order.setNumber(number);
-
- orderService.createOrder(order);
- log.info("下单成功");
- return order;
- }
在基于微服务架构下开发,由于服务数量巨多、在高可用性的驱使下要进行集群时,众多节点及服务的配置管理,变得苦不堪言,简直成了体力活,稍微不细心将会出现配置错误。为了方便服务配置信息的统一集中化管理,实时更新,SpringCloud中Spring Cloud Config组件(配置中心),就用来解决这类问题,以达到配置集中化管理,让你可以把配置集中放到远程服务器,集中化管理集群配置。
Spring Cloud Config 是 Spring Cloud 家族中最早的配置中心,虽然后来又发布了 Consul 可以代替配置中心功能,但是 Config 依然适用于 Spring Cloud 项目,通过简单的配置即可实现功能。
配置文件是我们再熟悉不过的了,尤其是 Spring Boot 项目,除了引入相应的 maven 包之外,剩下的工作就是完善配置文件了,例如 mysql、redis 、security 相关的配置。除了项目运行的基础配置之外,还有一些配置是与我们业务有关系的,比如说七牛存储、短信相关、邮件相关,或者一些业务上的开关。
对于一些简单的项目来说,我们一般都是直接把相关配置放在单独的配置文件中,以 properties 或者 yml 的格式出现,更省事儿的方式是直接放到 application.properties 或 application.yml 中。但是这样的方式有个明显的问题,那就是,当修改了配置之后,必须重启服务,否则配置无法生效。
目前有一些用的比较多的开源的配置中心,比如携程的 Apollo、蚂蚁金服的 disconf 等,对比 Spring Cloud Config,这些配置中心功能更加强大。有兴趣的可以拿来试一试。
更多。。。Spring Cloud Config 实现配置中心,看这一篇就够了 - 风的姿态 - 博客园
Spring Cloud Config可以完美的支持以上所有的需求。
Spring Cloud Config项目是一个解决分布式系统的配置管理方案。它包含了Client和Server两个部分,server提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client通过接口获取数据、并依据此数据初始化自己的应用。Spring cloud使用git或svn存放配置文件,默认情况下使用git,我们先以git为例做一套示例。
当微服务部署的实例越来越多,逐个修改微服务配置,显然不现实,而且很容易出错。我们需要一种统一配置管理方案,可以集中管理所有实例的配置,他就是 Nacos 。
我们服务中配置如果都放在代码中或者项目里的配置文件中,那么逐个修改微服务配置,提交上线,重启服务,那么将十分不科学,如果我们使用统一配置管理,就可以在服务启动的时候从配置管理服务读取配置,启动后,修改配置后,也会主动通知我们的服务。
详见...
SpringCloud 配置中心(Nacos)的简单使用_大三的土狗的博客-CSDN博客
另见...
SpringCloud 配置管理:Nacos_小道士写程序的博客-CSDN博客
在微服务架构中,一个系统往往由多个微服务组成,而这些服务可能部署在不同机房、不同地区、不同域名下。这种情况下,客户端(例如浏览器、手机、软件工具等)想要直接请求这些服务,就需要知道它们具体的地址信息,例如 IP 地址、端口号等。
这种客户端直接请求服务的方式存在以下问题:
我们可以通过 API 网关来解决这些问题,下面就让我们来看看什么是 API 网关。
API 网关是一个搭建在客户端和微服务之间的服务,我们可以在 API 网关中处理一些非业务功能的逻辑,例如权限验证、监控、缓存、请求路由等。
API 网关就像整个微服务系统的门面一样,是系统对外的唯一入口。有了它,客户端会先将请求发送到 API 网关,然后由 API 网关根据请求的标识信息将请求转发到微服务实例。

两种服务访问方式对比
对于服务数量众多、复杂度较高、规模比较大的系统来说,使用 API 网关具有以下好处:
常见的 API 网关实现方案主要有以下 5 种:
pring Cloud Gateway 是 Spring Cloud 团队基于 Spring 5.0、Spring Boot 2.0 和 Project Reactor 等技术开发的高性能 API 网关组件。
Spring Cloud Gateway 旨在提供一种简单而有效的途径来发送 API,并为它们提供横切关注点,例如:安全性,监控/指标和弹性。
Spring Cloud Gateway 是基于 WebFlux 框架实现的,而 WebFlux 框架底层则使用了高性能的 Reactor 模式通信框架 Netty。
Spring Cloud Gateway 核心概念
Spring Cloud GateWay 最主要的功能就是路由转发,而在定义转发规则时主要涉及了以下三个核心概念,如下表。
| 核心概念 | 描述 |
|---|---|
| Route(路由) | 网关最基本的模块。它由一个 ID、一个目标 URI、一组断言(Predicate)和一组过滤器(Filter)组成。 |
| Predicate(断言) | 路由转发的判断条件,我们可以通过 Predicate 对 HTTP 请求进行匹配,例如请求方式、请求路径、请求头、参数等,如果请求与断言匹配成功,则将请求转发到相应的服务。 |
| Filter(过滤器) | 过滤器,我们可以使用它对请求进行拦截和修改,还可以使用它对上文的响应进行再处理。 |
注意:其中 Route 和 Predicate 必须同时声明。
Spring Cloud Gateway 的特征
Spring Cloud Gateway 具有以下特性:
Spring Cloud Gateway 工作流程如下图。

Spring Cloud Gateway 工作流程
更多...... Gateway:Spring Cloud API网关组件(非常详细)
Zipkin是一个分布式链路跟踪系统,可以采集时序数据来协助定位延迟等相关问题。数据可以存储在cassandra,MySQL,ES,mem中。分布式链路跟踪是个老话题,国内也有类似的框架,比如阿里的skywalking。 zipkin目前和SpringCloud生态结合紧密,有相关的支持。