微服务拆分与ribbon的配置

发布时间 2023-04-13 22:20:54作者: Liku007

微服务思想【个人拙见】:将面向流程的业务转成面向业务的业务,也就是将业务划分为各个业务之间相互调用,从网关进入,通过网关实现微服务的转发与调用。

服务拆分

创建两个模块,一个是user,一个是order,但是一个订单对应一个用户,一个用户对应多个订单,创建以下实体类:在创建订单类的时候发现需要在订单业务里面创建用户实体用户接收对应的用户信息

@Data
public class Order {
    private Long id;
    private Long price;
    private String name;
    private Integer num;
    private Long userId;
    private User user;//在该服务里面需要user实体类,否则没办法接收用户信息
}
@Data
public class User {
    private Integer id;
    private String username;
    private String address;
}

编写对应的mapper、service、controller,实现最简单的一个业务:根据编号查询单个实体信息

…忽略编写过程

开启服务器,调用对应的接口…

调用order的时候发现,查询不到用户的全部信息,但是微服务的思想是:独立服务器,独立业务,独立数据库。因此,想在订单的查询业务里面同时查询出用户信息,可以通过调用用户端的查询单个的地址【例如:在order的控制层去调用http://localhost:8080/user/1方法】

实现步骤

在order启动类中添加restTemplate:

@SpringBootApplication
@MapperScan(basePackages = {"org.example.mapper"})
public class OrderApp {
    public static void main(String[] args) {
        SpringApplication.run(OrderApp.class, args);
    }
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

order控制层调用由微服务封装的user接口:

@RestController
@RequestMapping("order")
public class OrderController {
    @Autowired
    private OrderService orderService;
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("{orderId}")
    public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
        // 根据id查询订单并返回
        Order order = orderService.queryOrderById(orderId);
        //获取用户id,并且获取查询用户信息的地址
        String url = "http://localhost:8080/user/" + order.getUserId();
        //利用restTemplate发送http请求,查询用户【getForObject用于发get请求并返回一个对象,postForObject发post请求,以此类推】
        User forObject = restTemplate.getForObject(url, User.class);
        //给order的user赋值
        order.setUser(forObject);
        return order;
    }
}

重启服务器,发现成功获取user信息,实现微服务远程调用成功~ 服务调用关系: 服务提供者【user暴露接口给其他微服务调用】、服务消费者【order调用其他微服务提供的接口】

eureka

上面的微服务接口地址是固定的,因此每次换环境或者接口都可能发生改变,下面用到eureka

导入依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
</dependencies>

在启动类中添加注解:

@SpringBootApplication
@EnableEurekaServer
public class EurekaApp {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApp.class,args);
    }
}

配置文件配置信息:

server:
  port: 10086
spring:
  application:
    name: eurekaserver # 服务名称
eureka:
  client:
    service-url: # eureka的地址信息 多个用逗号隔开
      defaultZone: http://127.0.0.1:10086/eureka

以上就完成了eureka的服务端的注册

将user端注册到eureka

导入依赖

<!--客户端依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

编写配置文件:

eureka:
  client:
    service-url: # eureka的地址信息 多个用逗号隔开
      defaultZone: http://127.0.0.1:10086/eureka

实现负载均衡:

创建了两个user应用,【ctrl+d】复制应用,然后-Dserver.port=8082,在order服务里面配置负载均衡:

@Bean
@LoadBalanced//实现负载均衡
public RestTemplate restTemplate() {
    return new RestTemplate();
}

直接通过应用名称调用接口:【两个应用名称都是userservice】

@GetMapping("{orderId}")
public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
    Order order = orderService.queryOrderById(orderId);
    //直接调用应用名
    String url = "http://userservice/user/" + order.getUserId();
    User forObject = restTemplate.getForObject(url, User.class);
    order.setUser(forObject);
    return order;
}

地址栏输入查询order业务的方法,order服务远程调用user服务,发现开始轮询【负载均衡的一种方法】调用服务

Ribbon负载均衡

负载均衡策略

通过定义IRlue,修改负载均衡规则,两种方式:

  1. 代码方式:在order-service中的启动类中定义一个新的IRlue

    @Bean
    public IRule randomRule() {
        return new RandomRule();
    }
    
  2. 配置文件方式:在orderservice的application.yml文件中,添加新的配置也可以修改规则

    userservice: #针对某个微服务
      ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #新的负载均衡规则
    

饥饿加载

ribbon默认是采用懒加载,即第一次访问时才去创建LoadBalanceClient,请求时间会很长,而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

ribbon:
  eager-load:
    clients: #指定饥饿加载的服务名称
      - userservice