一個微服務架構的系統中,不同服務之間是會相互調用的,如一個訂單服務需要取用戶數據,則需要調用用戶服務,有多個用戶服務實例時,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(); }
搜索: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版的服務調用完成。
