微服务技术架构学习

1.认识微服务架构:

当我们创建了自己的服务集群后,需要一系列的技术去监控维护配置它:如注册中心和配置中心就包含了集群里所有服务的配置和注册信息之类。
在这里插入图片描述

  • 单体架构:将所有的功能集成在一个项目内开发,打成一个包进行部署。
    优点:架构简单、部署成本低
    缺点:耦合性高
  • 分布式架构:根据功能将代码拆分在不同项目中,每个业务代码作为独立的模块进行开发,称为一个服务。
    优点:降低服务耦合、有利于服务的升级拓展
    缺点:会面临很多问题:比如服务的健康状态的判断、维护等
    在这里插入图片描述
    Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。也是最早的一款服务框架,技术尚不成熟。
    后来诞生了SpringCloud,他的服务远程调用使用的Feign是基于http协议也就是restful风格的,开发了配置中心和服务网关的技术。
    最后阿里巴巴在 springcloud 和dubbo 的基础上开发了 SpringCloudAlibaba ,他有自己的一套技术,并包含了 dubbo 和 springcloud
    在这里插入图片描述
    同时 SpringCloud 也集成了很多的服务功能组件,这是建立在springboot的自动装配基础上的,实现了开箱即用的效果
    在这里插入图片描述
    服务拆分:
    1.不同的微服务,不要重复开发相同的业务。
    2.微服务的数据独立,不要访问其他微服务的数据库(就是在微服务中,都是单表查询,即使一个数据库中使用到了其他数据库中的数据,也是通过端口远程查询获得相关数据后进行添加。)
    3.微服务可以将自己的业务暴露为接口,给其他的微服务调用。

黑马微服务拆分demo:
通过访问端口可以发现,查询Order时user为null,不符合我们的期望,而user和order是两个完全独立的数据库,所以实现方式就是在查询order时远程调用user。
在这里插入图片描述
使用 restTemplate 对远程端口进行http访问,并将返回的json转换为对应的对象

 @GetMapping("{orderId}")
    public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
        Order order = orderService.queryOrderById(orderId);
        String url = "http://localhost:8081/user/" + order.getUserId();
        User user = restTemplate.getForObject(url, User.class);
        order.setUser(user);
        // 根据id查询订单并返回
        return order;
    }

成功效果:
在这里插入图片描述

2.Eureka注册中心学习:

服务调用关系:
服务消费者:调用给其他微服务提供的接口
服务提供者:暴露接口给其他微服务使用
这两个关系是相对的,一个微服务针对不同的其他微服务有不同的角色。

问题:
在服务器集群中,不同的服务对应的地址是不同的,我们不能像以前一样写死为一个端口,那要怎样获得对应服务的接口?如果有多个提供者消费者要怎么选择?怎么知道提供者的健康状态?这些 Eureka 都能帮我们解决。

原理:
eureka分为两个部分:服务端 和 客户端。

  • 服务端:即注册中心,他保存了服务的信息,如果需要其他服务中的信息就在注册中心中拉取;并且提供者会每间隔30s给 注册中心 发一条消息,说明自己是健康的,如果超过时间还未收到提供者的信息,eureka-server 就会在保存的记录中把这个 提供者 的信息删除。
  • 客户端:消费者和提供者都属于客户端中:消费者会从eureka中获取信息,并做负载均衡来判断要使用哪个;提供者将自己的信息发送给eureka,并向它发送“心跳”保证健康状态。
    在这里插入图片描述

2.1 搭建注册中心:

  • 新建一个项目,添加 eureka 的依赖:
    注意:这里添加的依赖是 eureka 的服务端 server
	<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
  • 新建一个配置文件,编写eureka的配置信息:
    因为 eureka 自身就是一个微服务,所以也需要一个端口,同时在注册时也会先将自己注册进去
# 启动eureka的端口号
server:
  port: 1001
  
# eureka的服务名称
spring:
  application:
    name: eurekaServer
    
# eureka的地址信息
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:1001/eureka
  • 添加一个启动类:
    这里的 @EnableEurekaServer 注解就是开启 eureka 的,一定不要忘记加,还要注意是server 不是 client。
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class,args);
    }
}

输入我们写好的地址,最后效果如下:
在这里插入图片描述
注:如果遇到了任何报错问题,比如说找不到服务,一定要仔细看一遍配置信息,比如我自己就把 default 写成了 defalut ,结果报错了页面能打开但是注册不成功。

2.2 服务注册:

和上面的步骤一样:

  • 在需要注册的服务的pom文件中添加依赖,注意这次是添加 client 的依赖
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
  • 在需要注册的服务的配置文件中添加 eureka 的配置信息:
# eureka的服务名称
  application:
    name: userServer
# eureka的地址信息
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:1001/eureka

可见 服务已经被加载进来了:
在这里插入图片描述

2.3 服务发现:

  • 在消费者调用服务者的端口时不再采用硬编码的方式将接口写死在里面,而是替换为服务名称
//原
String url = "http://localhost:8081/user/" + order.getUserId();
//改后
String url = "http://userServer/user/" + order.getUserId();
  • 在application的启动类中的 restTemplate 方法上添加 LoadBalanced 注解实现负载均衡,eureka 会自己帮我们判断使用哪个微服务。
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

为了模拟多个实例,我们将user服务复制一份,并修改端口号
在这里插入图片描述
记住要为新开的服务设置不同的端口号:

在这里插入图片描述
运行即可

在这里插入图片描述

3. Ribbon:

为什么只输入微服务的名称就可以访问到对应的服务呢?这其中是ribbon帮我们去实现的,ribbon从 eureka 中获得服务列表,并实现负载均衡。
在这里插入图片描述
在这里插入图片描述
本质上是使用了 LoadBalancerInterceptor 方法,这是一个拦截器,发来的请求会被这个负载均衡拦截器拦截,获得服务名称。

	public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
	public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
        URI originalUri = request.getURI();
        String serviceName = originalUri.getHost();
        Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
        return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
    }
}

获得服务名称后最后执行的 loadBalancer 是 RibbonLoadBalancerClient ,因为它实现了 LoadBalancerClient 接口。

public class RibbonLoadBalancerClient implements LoadBalancerClient 

他其中有一个 execute 方法,可以看到上面调用的就是这个方法获得端口号。

	public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {
		//这一步获得了端口号
        ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
        //这一步在负载均衡
        Server server = this.getServer(loadBalancer, hint);

在同一服务名拥有多个端口号时,会进行负载均衡选择最佳的端口,这里负载均衡实际上是调用了rule的 choose 方法进行的

	public String choose(Object key) {
        if (this.rule == null) {
            return null;
        } else {
            try {
                Server svr = this.rule.choose(key);
                return svr == null ? null : svr.getId();

irule接口决定了负载均衡的策略,是负载均衡的规则,其中有roundRobin(轮训调度),randomRule(随机)等
在这里插入图片描述
我们默认的机制是 ZoneAvoidanceRule:
以区域可用的服务器为基础进行服务器的选择。使用zone对服务器进行分类,这个zone可以理解为一个机房。然后再对zone内的多个服务做轮询。

调整负载均衡的方案:
方案一:代码方法:在application启动文件中注入一个新的rule,这里针对的是所有的服务。

	@Bean
    public IRule randomRule(){
        return new RandomRule();
    }

方案二:配置文件:在yml配置文件中配置规则,这里只针对某一个服务。

userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

饥饿加载:
ribbon 默认是采用懒加载的,即第一次访问才会去创建 LoadBalanceClient,请求时间会很长,而饥饿加载会在项目启动时创建,降低第一次访问的耗时,可以通过配置来开启饥饿加载,并可以指定服务进行饥饿加载:

ribbon:
  eager-load:
    clients: userservice

4. nacos注册中心:

nacos 是阿里巴巴的产品,它相比于 eureka 功能更加丰富。

4.1 安装:

nacos安装过程:

  1. 在百度网盘中将nacos的安装包下载下来,在一个没有中文的路径下解压下来
  2. 在conf文件夹下,将nacos的数据库语句导入到我们自己的数据库中。(不要忘记了!)
    在这里插入图片描述
  3. 修改properties文件,注意点是一些文件里注释掉的需要加上。
    在这里插入图片描述
  4. 在bin文件中直接点击 startup.cmd 启动或者在目录下的 cmd 中
 .\startup.cmd -m standalone
  1. 访问 localhost:8848/nacos 可访问nacos,默认的账户名密码都是 nacos

4.2 入门:

  1. nacos 的快速使用:
    • 在父工程中添加依赖:因为 springcloud 整合alibaba的后来添加的,所以需要再导入一次父工程的 alibaba 的依赖。注释掉eureka的依赖
    • 在每个子工程中添加nacos的依赖。注释掉eureka的依赖
    • 添加每个子工程的配置文件中nacos的配置内容。注释掉eureka的配置
	<!--nacos父工程依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.5.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
	<!-- nacos客户端依赖包 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

注意:设置服务名称的地方需要保留

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  # 设置服务名称
  application:
    name: orderServer
  # nacos地址信息
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

最后,在浏览器中输入 http://localhost:8848/nacos 网址进入nacos的页面,可以清楚的看到我们配置的服务。还可以点击详细查看详细信息。
在这里插入图片描述

4.3 服务多级存储模型(集群):

nacos 引入了集群的概念,一个服务(比如说我们的用户功能的服务)下,不同的地域有不同的集群存储这个服务的实例(例如上海的某台部署了此服务的服务器)。
在这里插入图片描述
尽量的调用本地的集群,因为距离的原因所以速度更快,延迟也更低;同时一个地区的集群有问题,还可以调用其他地方的集群继续工作
集群的设置:
在配置文件中可以设置集群,只要在 server-addr 这个配置的同级添加配置即可:

  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: nj

集群的模拟:
将集群名称设置为sh,启动两个服务实例,再将集群的名称设置为nj,启动另外一个服务实例,在nacos的页面可以看到不同的集群实例了:
在这里插入图片描述
此时我们想要的效果是,服务消费者 orderserver 会优先调用和自己在同一地域的提供者实例,此时我们为 order 添加一个集群,使其集群名为 nj,并启动它后调用接口:
此时我们发现,只有user3的集群是nj,理想状态下应该只调用user3的服务,可是实际上集群为sh的1和2也被调用了,这是轮询调用的规则,并没有按照集群调用。
在这里插入图片描述
设置调用规则:
在 order服务的配置文件中设置调用服务的规则,这里的缩进是在第一个,注意第一行是需要调用的服务的名称:

#对服务名设置
userServer:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule

此时再运行可以发现,order服务只会调用同集群的 user3服务,不会再调用不同集群的user1和user2服务。
在这里插入图片描述
那如果user3服务关闭会怎么样呢?
可以发现,即使同集群的实例关闭了,order还是可以调用成功,此时控制台会报一个警告 warn,这里因为我调用了两次接口,所以它报了两次 warn 提示我们跨集群访问了。
在这里插入图片描述
确定了集群后,对于本地集群的实例,是采用随机的负载均衡策略来挑选实例的。

根据权重负载均衡:
在我们的生产中,可能会出现希望更少的调用某一个实例的情况,这时可以在nacos中设置权限,将权重降低,这样访问时会较少访问权重低的服务:
可以在具体实例的信息后点击编辑,权重范围在0到1之间
在这里插入图片描述
设置后我们进行试验可以发现,我们设置的user2权重较低,此时调用接口15次,只有3次调用了user2,其他都是调用了user3。达到了我们想要的效果:
在这里插入图片描述
如果我们将权重设置为0是什么效果呢?就是完全不会被访问到,可用于我们服务的更新。

环境隔离:
nacos 不仅是一个注册中心还是一个数据中心,前面我们做的服务划分,实例划分是基于业务的划分,但是在实际开发中我们还会有不同代码环境的划分:比如测试环境和生产环境,我们可以使用namespace对环境进行隔离:
在这里插入图片描述
首先在nacos的左侧菜单有一个命名空间的选项,默认是在public命名空间,我们可以自己新建一个命名空间,其中id可以不填可以随机生产。
在这里插入图片描述
然后在代码中修改服务的命名空间,注意这里填的namespace里不是名称,而是命名空间的 id。

  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: nj
        namespace: 8f4f1f3e-042b-40c9-8552-8c811770b1e0 #dev环境

此时回到nacos控制台可以看见有了一个新的命名空间,服务已经移动到新的命名空间了
在这里插入图片描述
此时我们再去调用 order 的接口发现报错了,他没法调用user的接口因为他们不是在一个命名空间里,他们被隔离开来了,报的是服务不可用。
在这里插入图片描述
与eureka的不同:
nacos和eureka的不同在于nacos会主动发送信息给服务;
1.服务消费者会定时的在nacos拉取服务,但是频繁的拉取也会给nacos带来负担,所以会有一个缓存列表来缓存服务信息,这个缓存每30s更新一次,但如果在没有更新的30秒内服务发生了变化怎么办呢?nacos会主动的推送服务提供者的变更消息给消费者,即使30秒内服务没有更新,也能知道变化的服务的变更消息。
2.对于服务的提供者,nacos将其分为了 :临时实例 和 非临时实例;对于临时实例,需要主动的向nacos发送自己的健康信息,这一点和 eureka 一样,但是对于非临时实例,nacos则会主动的询问其健康状态,同时这样的主动询问也会给nacos服务器带来压力。
在这里插入图片描述
在nacos中引入了 临时实例 的概念,可以通过代码在配置文件中手动设置ephemeral为false为非临时实例(默认是临时实例)

  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: nj
        namespace: 8f4f1f3e-042b-40c9-8552-8c811770b1e0 #dev环境
        ephemeral: false #是否是临时实例

在这里插入图片描述
并且,对于非临时实例,当服务关闭时在服务列表页面会标记为红色,显示没有健康的实例(还可以点进去查看详细);如果为临时实例,当服务关闭时直接在页面上消失了,nacos不会保留其信息。
在这里插入图片描述

4.4 nacos的配置管理:

随着微服务越来越多,如果遇到配置文件需要修改的情况,传统方法需要暂停服务,修改好后再发布到环境中,但是在实际生产的环境中,如果重启服务会带来很大的影响;并且如果服务很多的情况下,不同服务之间可能是关联的,修改一个后还需要修改其他的服务配置。
这时nacos的配置管理功能就起到了很大的作用,它不仅可以在页面上管理服务的配置信息,还可以提供热更新的功能,在不重启服务的情况下对配置信息进行修改和更新。
· 可以在nacos上直接新建:
在这里插入图片描述
注意配置内容不是将yml文件中的配置都填写在这上面,会给nacos带来压力,我们将一些常变化的配置写在这里面,固定的配置还是写在代码中。

在这里插入图片描述

加载配置的步骤:
原本我们先在application中获得配置,现在我们多了一个在nacos中获得配置文件,然后将两个配置文件相结合,我们需要知道nacos的地址和读取哪个nacos配置,就需要在读取application配置文件以前读取到nacos的信息。
此时我们使用 bootstrap.yml 来保存nacos的配置信息,因为它的优先级比application的高。
在这里插入图片描述
1.添加配置管理的依赖:

	<!-- nacos的配置管理依赖 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

2.在resource文件夹下添加bootstrap.yml配置文件,并将application配置文件中的相关信息删除

spring:
  application:
    name: orderservice #服务名
  profiles:
    active: test #环境
  cloud:
    nacos:
      server-addr: localhost:8848 #nacos地址
      config:
        file-extension: yaml #文件后缀名

在nacos中的配置信息:
在这里插入图片描述
代码中的写法:

	@Value("${pattern.dateformat}")
    private String dateformat;

    @GetMapping("now")
    public String now() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));
    }

运行结果:
可以看见获取到了nacos中的配置。
在这里插入图片描述
热更新:
我们知道,nacos有热更新的功能,但是我们修改了配置发布后再刷新,测试显示的却没有变化,这是因为还缺少了一点步骤。要想实现热更新,有两种实现方法:
1.在使用 value 注解注入配置的类上加上 @RefreshScope 注解:

@RestController
@RequestMapping("order")
@RefreshScope
public class OrderController {
    @Value("${pattern.dateformat}")
    private String dateformat;
    ...

配置好后,启动项目后,发布配置可以达到热更新的效果。
2.在类中配置:(推荐)
新建一个配置类patternProperties ,映射我们nacos中的配置。

@Data
@Component
@ConfigurationProperties(prefix = "pattern")
public class patternProperties {
    public String dateformat;
}
@RestController
@RequestMapping("order")
public class OrderController {
    @Autowired
    private patternProperties patternProperties;
    @GetMapping("now")
    public String now() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternProperties.getDateformat()));
    }
    ...

多环境配置共享
一个服务不管生产还是测试环境都用到了一些相同的配置,这时可以使用多环境的配置共享,即默认配置,来实现我们想要的效果。
如图,可以看出,上面一个是测试的配置环境,下面是通用的配置环境,区别是没有注明生产或者测试这样的环境。
在这里插入图片描述
优先级:
服务名-环境名.yaml > 服务名.yaml > 本地配置

5.Feign的使用:

以前我们会使用restTemplate进行远程调用,可以看到,restTemplate的参数需要我们进行手动拼接,非常的不灵活,而且一旦遇到参数很多的情况就很不灵活

	String url = "http://userServer/user/" + order.getUserId();
    User user = restTemplate.getForObject(url, User.class);

为了解决上面问题,我们提出了Feign,Feign是一个声明式的 HTTP客户端,就是把我们需要的东西声明出来,spring会帮我们去做后续的处理。
1.添加一个feign依赖:

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>acp-spring-cloud-starter-openfeign</artifactId>
        </dependency>

2.在启动类上添加注解:

@EnableFeignClients
public class OrderApplication {

3.添加一个接口UserClient,这里的写法类似我们mvc的写法,使用起来更为便捷。

@FeignClient("userServer")
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

在方法中的调用

    @Autowired
    private UserClient userClient;

    @GetMapping("{orderId}")
    public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
        Order order = orderService.queryOrderById(orderId);
        User user = userClient.findById(order.getUserId());
        order.setUser(user);
        // 根据id查询订单并返回
        return order;
    }

修改 feign 配置:
我们可以定义自定义配置来修改 feign 的配置,其中我们修改最多的是日志的配置,其他的修改使用较少。
在这里插入图片描述
打印日志的类型分为:NONE,BASIC,HEADERS,FULL,full 表示打印所有的日志,下面将以 full 为例显示效果。
修改日志配置有两种方法:

  • 通过配置文件修改
    • 修改全局配置:
      在配置文件中修改配置,使用 default 表示是默认的对所有的微服务都生效
feign:
  client:
    config:
      default:
        loggerLevel: FULL

在这里插入图片描述
可以看见打印了很多响应头和响应体的信息
- 修改局部配置:
在配置文件中修改配置,使用 微服务名 代替 default 代表只对某一个微服务生效

feign:
  client:
    config:
      userServer:
        loggerLevel: FULL
  • 通过 java 代码修改配置:

    • 修改全局配置:
      先声明一个配置类:
public class FeignClientConfiguration {
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC;
    }
}

因为这个配置类没有加载到spring容器中,所以我们需要将他放进 @EnableFeignClients 注解中,就是我们在启动类上写的注解。

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
@EnableFeignClients(defaultConfiguration = FeignClientConfiguration.class)
public class OrderApplication {
  1. 修改局部配置:
    如果要修改局部的配置信息,则在局部方法上的 @FeignClient 注解中表名这个配置:
    就是在我们添加的feign接口上面添加注解。
@FeignClient(value = "userServer",configuration = FeignClientConfiguration.class)
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

性能优化
Feign是将接口转换为http请求,但是发请求的操作还是根据底层的客户端实现:

  1. URLConnection:默认实现,不支持连接池
  2. Apache HttpClient:支持连接池
  3. OKHttp:支持连接池

优化点:

  1. 使用连接池代替默认的 URLConnection
  2. 日志级别的限制:最好使用basic或者none,打印详细的日志也会降低性能。

操作:这里以 HttpClient 代替底层为例
1.引入依赖:

        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>

2.添加配置文件:
可设置最大连接数 和 单个连接最大连接数

feign:
  httpclient:
    enabled: true # 开启连接池
    max-connections: 200
    max-connections-per-route: 50 # 单个连接的最大连接数

5.1 feign的最佳实践:

feign 客户端写法:
在这里插入图片描述
controller 写法:
在这里插入图片描述
可以发现,两者非常的类似,他们的请求方法、地址和参数都是相同的;并且他们必须是相同的,因为feign就是调用了userservice的这个接口实现的,如果两个在请求方法、地址和参数有任何一块有所不同,那就会产生错误。
这样,我们思考,为了防止错误,可不可以使用一个方法将共同部分提取出来;第一种就是采用接口实现和继承的方式:
在这里插入图片描述
通过写一个接口,让我们的 feign 客户端继承这个接口,让 userservice 实现这个接口的方法;这样达到了一个规范的效果,不过这样也有很多的缺点:
1.这使得服务和feign客户端强耦合了,如果api做了修改,那两块地方都需要做修改。
2.springmvc不支持这样的写法,父接口参数列表中的映射不会被继承。

还有一种抽取的方法:
是将 feign 抽取出来,直接打包成一个依赖,并把所有相关的类和信息都配置进这个模块中,如果有微服务需要直接作为一个依赖引入即可,这样解决了耦合的问题,但同时也会带来比如依赖包如果有改动就要重新打包、可能微服务只需要某一个方法但是依赖包中集成了很多的方法等问题。
在这里插入图片描述
代码实现第二种:
1.添加一个模块,并将其作为依赖导入到需要的微服务中,并将相应使用的类和方法添加进来,将调用此feign模块的类(例如:orderservice)中相关的类和方法移过来,并替换原来的地方:
在这里插入图片描述
并在新建的项目中添加依赖:

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>

将其作为一个依赖添加到其他的服务中:
在这里插入图片描述
启动后会报一个错误,原因是找不到 userClient 的bean对象。
在这里插入图片描述
这是什么原因呢,我们明明在oderservice的controller中引入了这个类,但是因为我们是调用的 feign-api这个模块中的方法,两个spring容器是不一样的。
就是说这个类加载进了feign-api的spring容器中,却没有加载到 orderservice 的spring容器中,所以当然搜索不到。

	@Resource
    private UserClient userClient;

这里我们有两种解决方法:
两者的区别是第一个加在了启动类上 ,会为扫描feign-clients中所有的包;而第二个是加在了指定的扫描的类,只将指定的类扫描进容器;
我们推荐使用第二种,需要哪个就扫描哪个。
在这里插入图片描述

@EnableFeignClients(clients = {UserClient.class})

6. Gateway网关:

我们发布的微服务,不是对所有用户都放行的,因为里面有很多隐私信息,所以我们需要一个组件来为我们做身份认证和权限校验,只有指定的用户才能访问我们的微服务。
这个组件就是我们的 Gateway 网关。
就像在我们的微服务前加了一道门来验证,同时它也有负载均衡的效果:来判断某一请求调用的是哪个微服务;同时它还可以进行请求限流,比如这个微服务只能承载 500 次请求,则在网关处进行判断限流。
在这里插入图片描述
网关的分类:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值