• 升级微服务架构3:服务发现及服务相互调用


      一个微服务架构的系统中,不同服务之间是会相互调用的,如一个订单服务需要取用户数据,则需要调用用户服务,有多个用户服务实例时,Eureka会负载均衡到其中一个服务实例,和上一章一样,我们先通过Java版的服务发现及调用服务来做例子并移植到.net core版本。

      1.Java版服务调用

      1.1创建订单服务

      和前面一样创建一个空的Maven项目,并改造成为一个Eureka客户端,修改下配置文件,服务名为userservice,端口设置为6661

      1.2使用Ribbon做客户端负载均衡

      添加ribbon的依赖,ribbon是一个客户端的负载均衡组件,服务间相互调用通过它来负载均衡  

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>

      创建一个OrderController,同样创建一个User实体(实际项目中如果有多处调用同一个实体可以独立出来一个实体模块),在启动类中创建一个方法restTemplate()来注入restTemplate,并加上@Bean配置注解, @LoadBalanced负载均衡注解  

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

      参考官网文档:http://cloud.spring.io/spring-cloud-static/Finchley.SR1/single/spring-cloud.html#_spring_resttemplate_as_a_load_balancer_client

      搜索:Spring RestTemplate as a Load Balancer Client

      

      

      1.3订单服务调用用户服务

      创建一个Service类用来封装调用其他服务,这里创建一个UserService类,封装userservice服务的方法,创建一个restTemplate变量加上@Autowired注解来实现自动扫描注入  

    package com.tz.orderservice;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.ParameterizedTypeReference;
    import org.springframework.http.HttpMethod;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.client.RestTemplate;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @Service
    public class UserService {
    
        @Autowired
        private RestTemplate restTemplate;
    
        public List<User> getAll() {
            ParameterizedTypeReference<List<User>> responseType = new ParameterizedTypeReference<List<User>>(){};
            ResponseEntity<List<User>> resp = restTemplate.exchange("http://userservice/user/getall",
                    HttpMethod.GET, null, responseType);
            List<User> list = resp.getBody();
            return list;
        }    
    }

       订单Controller中创建获取用户信息的方法

    @RestController
    @RequestMapping("/order")
    public class OrderController {
    
        @Autowired
        private UserService userService;
    
        @RequestMapping("/getalluser")
        public List<User> getAllUser(){
            return userService.getAll();
        }
    }

      启动Eureka Server,启动两个userservice实例,启动orderservice,刷新服务注册中心,发现订单服务orderservice已经注册成功

      

      浏览器访问订单服务的获取用户信息方法,可以看到成功调用了用户服务的方法

      

      2. .net core版服务调用

       2.1创建订单服务

       按照上一章的方法创建一个.net Core的微服务,端口设置为6660,创建一个IUserService的接口,这里使用异步方法   

    public interface IUserService
    {
        Task<List<User>> getAll() ;
    
        Task<string> getPort();
    }

       2.2订单服务调用用户服务

      创建一个UserService类,实现IUserService接口来调用服务

      参考:http://steeltoe.io/docs/steeltoe-discovery/#1-2-6-discovering-services

      Json序列化组件:Newtonsoft.Json  

    public class UserService : IUserService
    {
        DiscoveryHttpClientHandler _handler;
        private const string serviceUrl = "http://userservice/user";
        public UserService(IDiscoveryClient client)
        {
            _handler = new DiscoveryHttpClientHandler(client);
        }
        public async Task<List<User>> getAll()
        {
            var client = GetClient();
            var json= await client.GetStringAsync(serviceUrl+"/getall");
            List<User> list= JsonConvert.DeserializeObject<List<User>>(json);
            return list;
        }
    
        public async Task<string> getPort()
        {
            var client = GetClient();
            return await client.GetStringAsync(serviceUrl + "/getport");
        }
    private HttpClient GetClient()
        {
            var client = new HttpClient(_handler, false);
            return client;
        }
    }

      

      在Startup类的ConfigureServices中配置UserService的依赖注入

    public void ConfigureServices(IServiceCollection services)
    {
        //添加注入配置
        services.AddScoped<Controllers.IUserService, Controllers.UserService>();
        //判断是否能获取Eureka配置
        if (Configuration.GetSection("eureka").GetChildren().Any())
        {
            //添加Steeltoe服务发现客户端服务配置
            services.AddDiscoveryClient(Configuration);
        }
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

      

      创建一个OrderController,使用IUserService接口来调用,在构造方法中注入实例  

    [Route("[controller]")]
    [ApiController]
    public class OrderController : ControllerBase
    {
        private readonly IUserService userService;
        //构造方法来注入实例
        public OrderController(IUserService userService)
        {
            this.userService = userService;
        }
    
        [Route("getalluser")]
        [HttpGet]
        public async Task<List<User>> getAll()
        {
            List<User> list = await userService.getAll();
            return list;
        }
    
        [Route("getuserserviceport")]
        [HttpGet]
        public async Task<string> getUserServicePort()
        {
            var port = await userService.getPort();
            return port;
        }
    
    }

      启动项目,在刷新下Eureka Server,端口为6660的orderservice实例就注册到了服务中心

      

      在浏览器中输入:http://localhost:6660/order/getuserserviceport,来调用userservice的获取端口的方法,多刷新几次就可以看到端口会不断的切换,说明已经实现了负载均衡。

      

      

      .net core版的服务调用完成。

  • 相关阅读:
    使用Spring RestTemplate 发送 List<MultipartFile>,上传多个文件
    二分查找的非递归实现
    图的深度优先遍历和广度优先遍历
    快速排序学习
    szwl面试记录
    Mycat对Mysql进行分库分表
    Java使用队列解决约瑟夫问题
    pa_hzzx面试总结
    Linux pam 后门纪录root用户密码以及自己设置root密码登录root
    JSP线程安全
  • 原文地址:https://www.cnblogs.com/townsend/p/9531882.html
Copyright © 2020-2023  润新知