RPC是远程过程调用(Remote Procedure Call)的缩写形式。SAP系统RPC调用的原理其实很简单,有一些类似于三层构架的C/S系统,第三方的客户程序通过接口调用SAP内部的标准或自定义函数,获得函数返回的数据进行处理后显示或打印。
例如我们平台需要获取到天气预报,就可以直接调用中国天气预报接口。
接口名称:http://wthrcdn.etouch.cn/weather_mini?city=北京
返回接口信息:
实现了所有 HTTP 的方法(GET、POST、PUT、HEAD、DELETE、HEAD、OPTIONS 等)
支持 HTTPS 协议
支持代理服务器(Nginx等)等
支持自动(跳转)转向
<dependencies>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpclientartifactId>
<version>4.5.5version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.66version>
dependency>
dependencies>
package com.demo.utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author: JYC
* @Title: HttpClientUtils
* @Description: TODO
* @Date: 2022/4/20 23:10
*/
public class HttpClientUtils {
private static final CloseableHttpClient httpClient;
public static final String CHARSET = "UTF-8";
private static final Log log = LogFactory.getLog(HttpClientUtils.class);
// 采用静态代码块,初始化超时时间配置,再根据配置生成默认httpClient对象
static {
RequestConfig config = RequestConfig.custom().setConnectTimeout(60000).setSocketTimeout(15000).build();
httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
}
public static String doGet(String url, Map<String, String> params) {
return doGet(url, params, CHARSET);
}
public static String doPost(String url, Map<String, String> params) throws IOException {
return doPost(url, params, CHARSET);
}
/**
* HTTP Get 获取内容
*
* @param url 请求的url地址 ?之前的地址
* @param params 请求的参数
* @param charset 编码格式
* @return 页面内容
*/
public static String doGet(String url, Map<String, String> params, String charset) {
try {
if (params != null && !params.isEmpty()) {
List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());
for (Map.Entry<String, String> entry : params.entrySet()) {
String value = entry.getValue();
if (value != null) {
pairs.add(new BasicNameValuePair(entry.getKey(), value));
}
}
// 将请求参数和url进行拼接
url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
}
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = httpClient.execute(httpGet);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
httpGet.abort();
throw new RuntimeException("HttpClient,error status code :" + statusCode);
}
HttpEntity entity = response.getEntity();
String result = null;
if (entity != null) {
result = EntityUtils.toString(entity, "utf-8");
}
EntityUtils.consume(entity);
response.close();
return result;
} catch (Exception e) {
log.error("请求服务器端出错:" + e);
return null;
}
}
/**
* HTTP Post 获取内容
*
* @param url 请求的url地址 ?之前的地址
* @param params 请求的参数
* @param charset 编码格式
* @return 页面内容
* @throws IOException
*/
public static String doPost(String url, Map<String, String> params, String charset)
throws IOException {
List<NameValuePair> pairs = null;
if (params != null && !params.isEmpty()) {
pairs = new ArrayList<NameValuePair>(params.size());
for (Map.Entry<String, String> entry : params.entrySet()) {
String value = entry.getValue();
if (value != null) {
pairs.add(new BasicNameValuePair(entry.getKey(), value));
}
}
}
HttpPost httpPost = new HttpPost(url);
if (pairs != null && pairs.size() > 0) {
httpPost.setEntity(new UrlEncodedFormEntity(pairs, CHARSET));
}
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
httpPost.abort();
throw new RuntimeException("HttpClient,error status code :" + statusCode);
}
HttpEntity entity = response.getEntity();
String result = null;
if (entity != null) {
result = EntityUtils.toString(entity, "utf-8");
}
EntityUtils.consume(entity);
return result;
} catch (ParseException e) {
log.error("请求服务器端出错:" + e);
return null;
} finally {
if (response != null)
response.close();
}
}
}
public class HttpClientUtilsTest {
public static void main(String[] args) {
String url = "http://wthrcdn.etouch.cn/weather_mini";
HashMap<String, String> params = new HashMap<String, String>();
params.put("city", "北京");
String result = HttpClientUtils.doGet(url, params);
System.out.println("result:" + result);
}
}
package com.demo.controller;
import com.alibaba.fastjson.JSONObject;
import com.demo.utils.HttpClientUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
/**
* @Author: JYC
* @Title: WeatherController
* @Description: TODO
* @Date: 2022/4/21 9:37
*/
@RestController
public class WeatherController {
@RequestMapping("/getWeather")
public Object getWeather(String city) {
String url = "http://wthrcdn.etouch.cn/weather_mini";
HashMap<String, String> params = new HashMap<String, String>();
params.put("city", city);
String jsonStr = HttpClientUtils.doGet(url, params);
// 转化成json
JSONObject jsonObject = JSONObject.parseObject(jsonStr);
// 获取今天天气
return jsonObject.getJSONObject("data").getJSONArray("forecast");
}
}
启动类:
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Author: JYC
* @Title: App
* @Description: TODO
* @Date: 2022/4/21 9:47
*/
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class);
}
}
在RPC远程调用过程中,服务与服务之间依赖关系非常大,服务Url地址管理非常复杂,所以这时候需要对我们服务的url实现治理,通过服务治理可以实现服务注册与发现、负载均衡、容错等。
生产者----提供接口
消费者----调用生产者提供的接口
生产者:提供接口
消费者:调用生产者提供的接口
服务的注册:当我们服务启动时会将服务的ip和端口注册存放在注册中心上
容器:存放服务的接口IP和端口号码
服务的发现:消费者如果调用接口时根据服务名称去服务注册中心查找该对应服务接口地址,在本地实现RPC远程调用
demo-order-consumer----订单服务 消费者 调用会员服务的接口
demo-member-producer—会员服务 生产者 提供接口
<modules>
<module>demo-member-producermodule>
<module>demo-order-consumermodule>
modules>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<version>2.4.1version>
dependency>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpclientartifactId>
<version>4.5.5version>
dependency>
dependencies>
package com.demo.service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author: JYC
* @Title: MemberService
* @Description: TODO
* @Date: 2022/4/21 13:57
*/
@RestController
public class MemberService {
/**
* 会员服务提供接口
* @return
*/
@RequestMapping("/getMember")
public String getMember() {
return "我是会员服务接口";
}
}
package com.demo.service;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Author: JYC
* @Title: com.demo.service.AppMember
* @Description: TODO
* @Date: 2022/4/21 13:59
*/
@SpringBootApplication
public class AppMember {
public static void main(String[] args) {
SpringApplication.run(AppMember.class);
}
}
server:
port: 8080
package com.demo.service;
import com.demo.utils.HttpClientUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author: JYC
* @Title: OrderToMemberService
* @Description: TODO
* @Date: 2022/4/21 14:04
*/
@RestController
public class OrderToMemberService {
/**
* 订单服务,调用 会员服务接口
*/
@RequestMapping("/orderToMember")
public String OrderToMember() {
// HttpClient 工具类 实现RPC远程调用
String memberUrl = "http://192.168.66.1:8080/getMember";
return HttpClientUtils.doGet(memberUrl, null);
}
}
package com.demo.utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Author: JYC
* @Title: OrderToMemberService
* @Description: TODO
* @Date: 2022/4/21 14:04
*/
public class HttpClientUtils {
private static final CloseableHttpClient httpClient;
public static final String CHARSET = "UTF-8";
private static final Log log = LogFactory.getLog(HttpClientUtils.class);
// 采用静态代码块,初始化超时时间配置,再根据配置生成默认httpClient对象
static {
RequestConfig config = RequestConfig.custom().setConnectTimeout(60000).setSocketTimeout(15000).build();
httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
}
public static String doGet(String url, Map<String, String> params) {
return doGet(url, params, CHARSET);
}
public static String doPost(String url, Map<String, String> params) throws IOException {
return doPost(url, params, CHARSET);
}
/**
* HTTP Get 获取内容
*
* @param url 请求的url地址 ?之前的地址
* @param params 请求的参数
* @param charset 编码格式
* @return 页面内容
*/
public static String doGet(String url, Map<String, String> params, String charset) {
try {
if (params != null && !params.isEmpty()) {
List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());
for (Map.Entry<String, String> entry : params.entrySet()) {
String value = entry.getValue();
if (value != null) {
pairs.add(new BasicNameValuePair(entry.getKey(), value));
}
}
// 将请求参数和url进行拼接
url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
}
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = httpClient.execute(httpGet);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
httpGet.abort();
throw new RuntimeException("HttpClient,error status code :" + statusCode);
}
HttpEntity entity = response.getEntity();
String result = null;
if (entity != null) {
result = EntityUtils.toString(entity, "utf-8");
}
EntityUtils.consume(entity);
response.close();
return result;
} catch (Exception e) {
log.error("请求服务器端出错:" + e);
return null;
}
}
/**
* HTTP Post 获取内容
*
* @param url 请求的url地址 ?之前的地址
* @param params 请求的参数
* @param charset 编码格式
* @return 页面内容
* @throws IOException
*/
public static String doPost(String url, Map<String, String> params, String charset)
throws IOException {
List<NameValuePair> pairs = null;
if (params != null && !params.isEmpty()) {
pairs = new ArrayList<NameValuePair>(params.size());
for (Map.Entry<String, String> entry : params.entrySet()) {
String value = entry.getValue();
if (value != null) {
pairs.add(new BasicNameValuePair(entry.getKey(), value));
}
}
}
HttpPost httpPost = new HttpPost(url);
if (pairs != null && pairs.size() > 0) {
httpPost.setEntity(new UrlEncodedFormEntity(pairs, CHARSET));
}
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
httpPost.abort();
throw new RuntimeException("HttpClient,error status code :" + statusCode);
}
HttpEntity entity = response.getEntity();
String result = null;
if (entity != null) {
result = EntityUtils.toString(entity, "utf-8");
}
EntityUtils.consume(entity);
return result;
} catch (ParseException e) {
log.error("请求服务器端出错:" + e);
return null;
} finally {
if (response != null)
response.close();
}
}
}
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Author: JYC
* @Title: AppOrder
* @Description: TODO
* @Date: 2022/4/21 14:10
*/
@SpringBootApplication
public class AppOrder {
public static void main(String[] args) {
SpringApplication.run(AppOrder.class);
}
}
server:
port: 8070
http://locahost:8070/orderToMember
Eureka、Zookeeper、Consule、Nacos、Redis 等。
Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。
SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。
Eureka包含两个组件:Eureka Server和Eureka Client。
Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client是一个java客户端,用于简化与Eureka Server的交互,客户端同时也就是一个内置的、使用轮询(round-robin)负载算法的负载均衡器。
在应用启动后,将会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
Eureka Server之间通过复制的方式完成数据的同步,Eureka还提供了客户端缓存机制,即使所有的Eureka Server都挂掉,客户端依然可以利用缓存中的信息消费其他服务的API。综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Finchley.RC2version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<repositories>
<repository>
<id>spring-milestonesid>
<name>Spring Milestonesname>
<url>https://repo.spring.io/milestoneurl>
<snapshots>
<enabled>falseenabled>
snapshots>
repository>
repositories>
server:
port: 9090 #服务注册中心端口号
spring:
application:
name: spring-cloud-eureka-server
eureka:
instance:
hostname: 127.0.0.1 #服务注册中心IP地址
client:
registerWithEureka: false #是否向服务注册中心注册自己
fetchRegistry: false #是否检索服务
serviceUrl: #服务注册中心的配置内容,指定服务注册中心的位置
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @Author: JYC
* @Title: AppEurekaServer
* @Description: TODO
* @Date: 2022/4/21 18:46
*/
@SpringBootApplication
@EnableEurekaServer
public class AppEurekaServer {
public static void main(String[] args) {
SpringApplication.run(AppEurekaServer.class);
}
}
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Finchley.RC2version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<repositories>
<repository>
<id>spring-milestonesid>
<name>Spring Milestonesname>
<url>https://repo.spring.io/milestoneurl>
<snapshots>
<enabled>falseenabled>
snapshots>
repository>
repositories>
server:
port: 8080
spring:
application:
name: demo-member #服务名称 在注册中心展示服务名称
eureka:
client:
service-url: # 服务注册中心地址
defaultZone: http://127.0.0.1:9090/eureka/
package com.demo.service;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @Author: JYC
* @Title: com.demo.service.AppMember
* @Description: TODO
* @Date: 2022/4/21 13:59
*/
@SpringBootApplication
@EnableEurekaClient
public class AppMember {
public static void main(String[] args) {
SpringApplication.run(AppMember.class);
}
}
<dependencies>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpclientartifactId>
<version>4.5.5version>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Finchley.RC2version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<repositories>
<repository>
<id>spring-milestonesid>
<name>Spring Milestonesname>
<url>https://repo.spring.io/milestoneurl>
<snapshots>
<enabled>falseenabled>
snapshots>
repository>
repositories>
server:
port: 8070
spring:
application:
name: demo-order #服务名称 在注册中心展示服务名称
eureka:
client:
service-url: # 服务注册中心地址
defaultZone: http://127.0.0.1:9090/eureka/
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @Author: JYC
* @Title: AppOrder
* @Description: TODO
* @Date: 2022/4/21 14:10
*/
@SpringBootApplication
@EnableDiscoveryClient
public class AppOrder {
public static void main(String[] args) {
SpringApplication.run(AppOrder.class);
}
}
package com.demo.service;
import com.demo.utils.HttpClientUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Author: JYC
* @Title: OrderToMemberService
* @Description: TODO
* @Date: 2022/4/21 14:04
*/
@RestController
public class OrderToMemberService {
@Autowired
private DiscoveryClient discoveryClient;
/**
* 订单服务,调用 会员服务接口
*/
@RequestMapping("/orderToMember")
public String OrderToMember() {
// HttpClient 工具类 实现RPC远程调用
// String memberUrl = "http://192.168.66.1:8080/getMember";
/**
* 根据服务名称,从注册中心获取会员的接口地址
*/
List<ServiceInstance> instances = discoveryClient.getInstances("demo-member");
ServiceInstance serviceInstance = instances.get(0);
// 会员服务的ip和端口
String memberUrl = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/" + "getMember";
return "订单服务调用会员服务:" + HttpClientUtils.doGet(memberUrl, null);
}
}
package com.demo.utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Author: JYC
* @Title: OrderToMemberService
* @Description: TODO
* @Date: 2022/4/21 14:04
*/
public class HttpClientUtils {
private static final CloseableHttpClient httpClient;
public static final String CHARSET = "UTF-8";
private static final Log log = LogFactory.getLog(HttpClientUtils.class);
// 采用静态代码块,初始化超时时间配置,再根据配置生成默认httpClient对象
static {
RequestConfig config = RequestConfig.custom().setConnectTimeout(60000).setSocketTimeout(15000).build();
httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
}
public static String doGet(String url, Map<String, String> params) {
return doGet(url, params, CHARSET);
}
public static String doPost(String url, Map<String, String> params) throws IOException {
return doPost(url, params, CHARSET);
}
/**
* HTTP Get 获取内容
*
* @param url 请求的url地址 ?之前的地址
* @param params 请求的参数
* @param charset 编码格式
* @return 页面内容
*/
public static String doGet(String url, Map<String, String> params, String charset) {
try {
if (params != null && !params.isEmpty()) {
List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());
for (Map.Entry<String, String> entry : params.entrySet()) {
String value = entry.getValue();
if (value != null) {
pairs.add(new BasicNameValuePair(entry.getKey(), value));
}
}
// 将请求参数和url进行拼接
url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
}
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = httpClient.execute(httpGet);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
httpGet.abort();
throw new RuntimeException("HttpClient,error status code :" + statusCode);
}
HttpEntity entity = response.getEntity();
String result = null;
if (entity != null) {
result = EntityUtils.toString(entity, "utf-8");
}
EntityUtils.consume(entity);
response.close();
return result;
} catch (Exception e) {
log.error("请求服务器端出错:" + e);
return null;
}
}
/**
* HTTP Post 获取内容
*
* @param url 请求的url地址 ?之前的地址
* @param params 请求的参数
* @param charset 编码格式
* @return 页面内容
* @throws IOException
*/
public static String doPost(String url, Map<String, String> params, String charset)
throws IOException {
List<NameValuePair> pairs = null;
if (params != null && !params.isEmpty()) {
pairs = new ArrayList<NameValuePair>(params.size());
for (Map.Entry<String, String> entry : params.entrySet()) {
String value = entry.getValue();
if (value != null) {
pairs.add(new BasicNameValuePair(entry.getKey(), value));
}
}
}
HttpPost httpPost = new HttpPost(url);
if (pairs != null && pairs.size() > 0) {
httpPost.setEntity(new UrlEncodedFormEntity(pairs, CHARSET));
}
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
httpPost.abort();
throw new RuntimeException("HttpClient,error status code :" + statusCode);
}
HttpEntity entity = response.getEntity();
String result = null;
if (entity != null) {
result = EntityUtils.toString(entity, "utf-8");
}
EntityUtils.consume(entity);
return result;
} catch (ParseException e) {
log.error("请求服务器端出错:" + e);
return null;
} finally {
if (response != null)
response.close();
}
}
}
Eureka 常用配置解析(点击跳转)
浏览器访问:http://127.0.0.1:9090/
出现如下界面表示服务端启动成功
浏览器访问:http://127.0.0.1:9090/
在界面中能看到"DEMO-MEMBER"表示启动成功
浏览器访问:http://127.0.0.1:9090/
在界面中能看到"DEMO-ORDER"表示启动成功
在浏览器中输入:http://127.0.0.1:8070/orderToMember
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
*由阿里巴巴推出,Java语言编写
Nacos官网: https://nacos.io/zh-cn/docs/what-is-nacos.html
服务(Service)是 Nacos 世界的一等公民。Nacos 支持几乎所有主流类型的“服务”的发现、配置和管理:
Kubernetes Service
gRPC & Dubbo RPC Service
Spring Cloud RESTful Service
Nacos 的关键特性包括:
服务发现和服务健康监测
Nacos 支持基于 DNS 和基于 RPC 的服务发现。服务提供者使用 原生SDK、OpenAPI、或一个独立的Agent TODO注册 Service 后,服务消费者可以使用DNS TODO 或HTTP&API查找和发现服务。
Nacos 提供对服务的实时的健康检查,阻止向不健康的主机或服务实例发送请求。Nacos 支持传输层 (PING 或 TCP)和应用层 (如 HTTP、MySQL、用户自定义)的健康检查。 对于复杂的云环境和网络拓扑环境中(如 VPC、边缘网络等)服务的健康检查,Nacos 提供了 agent 上报模式和服务端主动检测2种健康检查模式。Nacos 还提供了统一的健康检查仪表盘,帮助您根据健康状态管理服务的可用性及流量。
动态配置服务
动态配置服务可以让您以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。
动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。
配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。
Nacos 提供了一个简洁易用的UI (控制台样例 Demo) 帮助您管理所有的服务和应用的配置。Nacos 还提供包括配置版本跟踪、金丝雀发布、一键回滚配置以及客户端配置更新状态跟踪在内的一系列开箱即用的配置管理特性,帮助您更安全地在生产环境中管理配置变更和降低配置变更带来的风险。
动态 DNS 服务
动态 DNS 服务支持权重路由,让您更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单DNS解析服务。动态DNS服务还能让您更容易地实现以 DNS 协议为基础的服务发现,以帮助您消除耦合到厂商私有服务发现 API 上的风险。
Nacos 提供了一些简单的 DNS APIs TODO 帮助您管理服务的关联域名和可用的 IP:PORT 列表.
服务及其元数据管理
Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 以及最首要的 metrics 统计数据。
服务注册中心 如何设计
Nacos 下载地址:https://github.com/alibaba/nacos/releases
进入到:nacos-server-2.0.3\nacos\bin startup.cmd 启动即可。
访问:127.0.0.1:8848/nacos
默认账户密码:nacos/nacos
1.实现服务注册
发送post请求:
‘http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=mayikt-member&ip=20.18.7.10&port=8080’
2.实现服务发现
http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=mayikt-member
详细步骤操作:https://nacos.io/zh-cn/docs/quick-start.html
注意:发送请求类型是为Post类型
一直刷新观察控制台,大概要等到30s才会把实例剔除(大概15s设置不健康)
该知识点设计服务续约问题
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.0.0.RELEASEversion>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.66version>
dependency>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpclientartifactId>
<version>4.5.5version>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
<version>0.2.2.RELEASEversion>
dependency>
dependencies>
server:
port: 8080
spring:
application:
name: demo-member #服务名称 在 注册中心展示服务名称 --
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # nacos服务注册中心Server端 地址
package com.demo.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author: JYC
* @Title: MemberService
* @Description: TODO
* @Date: 2022/4/21 13:57
*/
@RestController
public class MemberService {
@Value("${server.port}")
private String serverPort;
/**
* 会员服务提供接口
* @return
*/
@RequestMapping("/getMember")
public String getMember() {
return "我是会员服务接口...端口:" + serverPort;
}
}
package com.demo.service;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Author: JYC
* @Title: com.demo.service.AppMember
* @Description: TODO
* @Date: 2022/4/21 13:59
*/
@SpringBootApplication
public class AppMember {
public static void main(String[] args) {
SpringApplication.run(AppMember.class);
}
}
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
<version>0.2.2.RELEASEversion>
dependency>
dependencies>
server:
port: 8070
spring:
application:
name: demo-order #服务名称 在注册中心展示服务名称
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # nacos服务注册中心Server端 地址
package com.demo.service;
import com.demo.utils.HttpClientUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Author: JYC
* @Title: OrderToMemberService
* @Description: TODO
* @Date: 2022/4/21 14:04
*/
@RestController
public class OrderToMemberService {
@Autowired
private DiscoveryClient discoveryClient;
/**
* 订单服务,调用 会员服务接口
*/
@RequestMapping("/orderToMember")
public String OrderToMember() {
// HttpClient 工具类 实现RPC远程调用
// String memberUrl = "http://192.168.66.1:8080/getMember";
/**
* 根据服务名称,从注册中心获取会员的接口地址
*/
List<ServiceInstance> instances = discoveryClient.getInstances("demo-member");
ServiceInstance serviceInstance = instances.get(0);
// 会员服务的ip和端口
String memberUrl = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/" + "getMember";
return "订单服务调用会员服务:" + HttpClientUtils.doGet(memberUrl, null);
}
}
package com.demo.utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Author: JYC
* @Title: OrderToMemberService
* @Description: TODO
* @Date: 2022/4/21 14:04
*/
public class HttpClientUtils {
private static final CloseableHttpClient httpClient;
public static final String CHARSET = "UTF-8";
private static final Log log = LogFactory.getLog(HttpClientUtils.class);
// 采用静态代码块,初始化超时时间配置,再根据配置生成默认httpClient对象
static {
RequestConfig config = RequestConfig.custom().setConnectTimeout(60000).setSocketTimeout(15000).build();
httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
}
public static String doGet(String url, Map<String, String> params) {
return doGet(url, params, CHARSET);
}
public static String doPost(String url, Map<String, String> params) throws IOException {
return doPost(url, params, CHARSET);
}
/**
* HTTP Get 获取内容
*
* @param url 请求的url地址 ?之前的地址
* @param params 请求的参数
* @param charset 编码格式
* @return 页面内容
*/
public static String doGet(String url, Map<String, String> params, String charset) {
try {
if (params != null && !params.isEmpty()) {
List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());
for (Map.Entry<String, String> entry : params.entrySet()) {
String value = entry.getValue();
if (value != null) {
pairs.add(new BasicNameValuePair(entry.getKey(), value));
}
}
// 将请求参数和url进行拼接
url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
}
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = httpClient.execute(httpGet);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
httpGet.abort();
throw new RuntimeException("HttpClient,error status code :" + statusCode);
}
HttpEntity entity = response.getEntity();
String result = null;
if (entity != null) {
result = EntityUtils.toString(entity, "utf-8");
}
EntityUtils.consume(entity);
response.close();
return result;
} catch (Exception e) {
log.error("请求服务器端出错:" + e);
return null;
}
}
/**
* HTTP Post 获取内容
*
* @param url 请求的url地址 ?之前的地址
* @param params 请求的参数
* @param charset 编码格式
* @return 页面内容
* @throws IOException
*/
public static String doPost(String url, Map<String, String> params, String charset)
throws IOException {
List<NameValuePair> pairs = null;
if (params != null && !params.isEmpty()) {
pairs = new ArrayList<NameValuePair>(params.size());
for (Map.Entry<String, String> entry : params.entrySet()) {
String value = entry.getValue();
if (value != null) {
pairs.add(new BasicNameValuePair(entry.getKey(), value));
}
}
}
HttpPost httpPost = new HttpPost(url);
if (pairs != null && pairs.size() > 0) {
httpPost.setEntity(new UrlEncodedFormEntity(pairs, CHARSET));
}
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
httpPost.abort();
throw new RuntimeException("HttpClient,error status code :" + statusCode);
}
HttpEntity entity = response.getEntity();
String result = null;
if (entity != null) {
result = EntityUtils.toString(entity, "utf-8");
}
EntityUtils.consume(entity);
return result;
} catch (ParseException e) {
log.error("请求服务器端出错:" + e);
return null;
} finally {
if (response != null)
response.close();
}
}
}
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Author: JYC
* @Title: AppOrder
* @Description: TODO
* @Date: 2022/4/21 14:10
*/
@SpringBootApplication
public class AppOrder {
public static void main(String[] args) {
SpringApplication.run(AppOrder.class);
}
}
在Nacos的服务管理界面中看到刚刚启动的两个服务,表示两个服务均启动成功。
访问接口:http://127.0.0.1:8070/orderToMember
RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。RestTemplate 继承自 InterceptingHttpAccessor 并且实现了 RestOperations 接口,其中 RestOperations 接口定义了基本的 RESTful 操作,这些操作在 RestTemplate 中都得到了实现。接下来我们就来看看这些操作方法的使用。
底层是基于HttpClient封装的
package com.demo.service;
import com.demo.utils.HttpClientUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* @Author: JYC
* @Title: OrderToMemberService
* @Description: TODO
* @Date: 2022/4/21 14:04
*/
@RestController
public class OrderToMemberService {
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private RestTemplate restTemplate;
/**
* 订单服务,调用 会员服务接口
*/
@RequestMapping("/orderToMember")
public String OrderToMember() {
// HttpClient 工具类 实现RPC远程调用
// String memberUrl = "http://192.168.66.1:8080/getMember";
/**
* 根据服务名称,从注册中心获取会员的接口地址
*/
List<ServiceInstance> instances = discoveryClient.getInstances("demo-member");
ServiceInstance serviceInstance = instances.get(0);
// 会员服务的ip和端口
String memberUrl = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/" + "getMember";
ResponseEntity<String> response = restTemplate.getForEntity(memberUrl, String.class);
return "订单服务调用会员服务:" + response.getBody();
}
}
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @Author: JYC
* @Title: AppOrder
* @Description: TODO
* @Date: 2022/4/21 14:10
*/
@SpringBootApplication
public class AppOrder {
public static void main(String[] args) {
SpringApplication.run(AppOrder.class);
}
/**
* 将restTemplate注入到spring ioc容器
* @return
*/
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
package com.demo.loadbalance;
import org.springframework.cloud.client.ServiceInstance;
public interface LoadBalance {
/**
* 负载均衡算法:给我多个地址,负载均衡会取出一个地址返回使用
* @param serviceId
* @return
*/
ServiceInstance getInstances(String serviceId);
}
package com.demo.loadbalance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Author: JYC
* @Title: RoundLoadBalance
* @Description: TODO
* @Date: 2022/4/22 11:23
*/
@Component
public class RoundLoadBalance implements LoadBalance {
@Autowired
private DiscoveryClient discoveryClient;
private AtomicInteger atomicCount = new AtomicInteger(0);
@Override
public ServiceInstance getInstances(String serviceId) {
// 1. 根据服务的名称,获取该服务集群地址列表
List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
// 2. 判断是否为null
if (instances == null || instances.size() == 0) {
return null;
}
// 3. 使用负载均衡算法
int index = atomicCount.incrementAndGet();
return instances.get(index);
}
}
package com.demo.service;
import com.demo.loadbalance.RoundLoadBalance;
import com.demo.utils.HttpClientUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Author: JYC
* @Title: OrderToMemberService
* @Description: TODO
* @Date: 2022/4/21 14:04
*/
@RestController
public class OrderToMemberService {
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private RoundLoadBalance roundLoadBalance;
/**
* 订单服务,调用 会员服务接口
*/
@RequestMapping("/orderToMember")
public String OrderToMember() {
// HttpClient 工具类 实现RPC远程调用
// String memberUrl = "http://192.168.66.1:8080/getMember";
/**
* 根据服务名称,从注册中心获取会员的接口地址
*/
// List instances = discoveryClient.getInstances("demo-member");
// ServiceInstance serviceInstance = instances.get(0);
ServiceInstance serviceInstance = roundLoadBalance.getInstances("demo-member");
// 会员服务的ip和端口
String memberUrl = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/" + "getMember";
return "订单服务调用会员服务:" + HttpClientUtils.doGet(memberUrl, null);
}
}
package com.demo.loadbalance;
import org.springframework.cloud.client.ServiceInstance;
public interface LoadBalance {
/**
* 负载均衡算法:给我多个地址,负载均衡会取出一个地址返回使用
* @param serviceId
* @return
*/
ServiceInstance getInstances(String serviceId);
}
package com.demo.loadbalance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Random;
/**
* @Author: JYC
* @Title: RandomLoadBalance
* @Description: TODO
* @Date: 2022/4/22 11:37
*/
@Component
public class RandomLoadBalance implements LoadBalance{
@Autowired
private DiscoveryClient discoveryClient;
@Override
public ServiceInstance getInstances(String serviceId) {
// 1. 根据服务的名称,获取该服务集群地址列表
List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
// 2. 判断是否为null
if (instances == null || instances.size() == 0) {
return null;
}
// 生成随机数范围
Random random = new Random();
int index = random.nextInt(instances.size());
return instances.get(index);
}
}
package com.demo.service;
import com.demo.loadbalance.RandomLoadBalance;
import com.demo.loadbalance.RoundLoadBalance;
import com.demo.utils.HttpClientUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Author: JYC
* @Title: OrderToMemberService
* @Description: TODO
* @Date: 2022/4/21 14:04
*/
@RestController
public class OrderToMemberService {
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private RoundLoadBalance roundLoadBalance;
@Autowired
private RandomLoadBalance randomLoadBalance;
/**
* 订单服务,调用 会员服务接口
*/
@RequestMapping("/orderToMember")
public String OrderToMember() {
// HttpClient 工具类 实现RPC远程调用
// String memberUrl = "http://192.168.66.1:8080/getMember";
/**
* 根据服务名称,从注册中心获取会员的接口地址
*/
// List instances = discoveryClient.getInstances("demo-member");
// ServiceInstance serviceInstance = instances.get(0);
// ServiceInstance serviceInstance = roundLoadBalance.getInstances("demo-member");
ServiceInstance serviceInstance = randomLoadBalance.getInstances("demo-member");
// 会员服务的ip和端口
String memberUrl = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/" + "getMember";
return "订单服务调用会员服务:" + HttpClientUtils.doGet(memberUrl, null);
}
}
package com.demo.service;
import com.demo.loadbalance.RandomLoadBalance;
import com.demo.loadbalance.RoundLoadBalance;
import com.demo.utils.HttpClientUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Author: JYC
* @Title: OrderToMemberService
* @Description: TODO
* @Date: 2022/4/21 14:04
*/
@RestController
@Slf4j
public class OrderToMemberService {
@Autowired
private DiscoveryClient discoveryClient;
/**
* 订单服务,调用 会员服务接口
*/
@RequestMapping("/orderToMember")
public String OrderToMember() {
/**
* 根据服务名称,从注册中心获取会员的接口地址
*/
List<ServiceInstance> instances = discoveryClient.getInstances("demo-member");
for (int i = 0; i < instances.size(); i++) {
try {
ServiceInstance serviceInstance = instances.get(i);
// 会员服务的ip和端口
String memberUrl = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/" + "getMember";
}catch (Exception e) {
log.error("[rpc远程调用发生了故障,开始故障转移,切换下一个地址调用 e:{}]", e);
}
}
return "fail";
}
}
package com.demo;
import com.demo.loadbalance.LoadBalance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Author: JYC
* @Title: WeightLoadBalance
* @Description: TODO
* @Date: 2022/4/22 14:38
*/
@Component
public class WeightLoadBalance implements LoadBalance {
@Autowired
private DiscoveryClient discoveryClient;
private AtomicInteger countAtomicInteger = new AtomicInteger(0);
@Override
public ServiceInstance getInstances(String serviceId) {
// 1.根据服务Id名称,获取该接口多个实例
List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
if (instances == null) {
return null;
}
List<ServiceInstance> newInstances = new ArrayList<>();
// 循环遍历该服务名称,对应的多个实例
instances.forEach((service) -> {
// 获取该服务实例对应的权重比例
Double weight = Double.parseDouble(service.getMetadata().get("nacos.weight"));
for (int i = 0; i < weight; i++) {
newInstances.add(service);
}
});
// 线程安全
return newInstances.get(countAtomicInteger.incrementAndGet() % newInstances.size());
}
}
package com.demo.service;
import com.demo.WeightLoadBalance;
import com.demo.loadbalance.RandomLoadBalance;
import com.demo.loadbalance.RoundLoadBalance;
import com.demo.utils.HttpClientUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Author: JYC
* @Title: OrderToMemberService
* @Description: TODO
* @Date: 2022/4/21 14:04
*/
@RestController
@Slf4j
public class OrderToMemberService {
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private WeightLoadBalance weightLoadBalance;
/**
* 订单服务,调用 会员服务接口
*/
@RequestMapping("/orderToMember")
public String OrderToMember() {
/**
* 根据服务名称,从注册中心获取会员的接口地址
*/
// List instances = discoveryClient.getInstances("demo-member");
// ServiceInstance serviceInstance = instances.get(0);
ServiceInstance serviceInstance = weightLoadBalance.getInstances("demo-member");
// 会员服务的ip和端口
String memberUrl = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/" + "getMember";
return "订单服务调用会员服务:" + HttpClientUtils.doGet(memberUrl, null);
}
}