一、远程调用
考试时不会,求救室友 自己有个方法不会实现,但是别人会实现,让别做的过程,就是远程调用
1.1好处
社会的分工
二、实现调用
Socket IO 流 反射
2.1 实现流程
2.2 室友的实现
ServerSocket
public class ClassmateApp {
public static void main(String
[] args
) throws Exception
{
ServerSocket serverSocket
= new ServerSocket(8888);
System
.out
.println("手机打开了,开始等待。。。");
Socket socket
= serverSocket
.accept();
System
.out
.println("菜逼的题目来了");
System
.out
.println("获取它的题目");
InputStream inputStream
= socket
.getInputStream();
ObjectInputStream objectInputStream
= new
ObjectInputStream(inputStream
);
String question
= (String
)objectInputStream
.readObject();
System
.out
.println("接受到菜逼的题目为"+question
);
Integer result
= 1 + 1 ;
System
.out
.println("答案算出来了");
System
.out
.println("发送答案");
OutputStream outputStream
= socket
.getOutputStream();
ObjectOutputStream objectOutputStream
= new
ObjectOutputStream(outputStream
);
objectOutputStream
.writeObject(result
);
System
.out
.println("答案发送成功");
close(objectOutputStream
,outputStream
,objectInputStream
,inputStream
,socket
,
serverSocket
);
}
public static void close(Closeable
...claseables
) {
for (Closeable closeable
: claseables
) {
if(null
!=closeable
) {
try {
closeable
.close();
} catch (IOException e
) {
e
.printStackTrace();
}finally {
closeable
= null
;
}
}
}
}
}
2.2 自己的实现
Sokcet
public class SlefApp {
public static void main(String
[] args
) throws UnknownHostException
,
IOException
, ClassNotFoundException
{
System
.out
.println("1 开始考试");
String question
= "1 + 1 =?";
System
.out
.println("这个题目"+question
+",不会,求救室友");
System
.out
.println("把题目发给室友");
Socket socket
= new Socket("localhost", 8888);
OutputStream outputStream
= socket
.getOutputStream();
ObjectOutputStream objectOutputStream
= new
ObjectOutputStream(outputStream
);
objectOutputStream
.writeObject(question
);
System
.out
.println("题目发送完毕");
InputStream inputStream
= socket
.getInputStream();
ObjectInputStream objectInputStream
= new ObjectInputStream(inputStream
);
Object answer
= objectInputStream
.readObject();
System
.out
.println("室友的答案接收完毕");
System
.out
.println("我写上去:1 +1 = "+answer
);
close(objectInputStream
,inputStream
,objectOutputStream
,
outputStream
,socket
);
}
public static void close(Closeable
...claseables
) {
for (Closeable closeable
: claseables
) {
if(null
!=closeable
) {
try {
closeable
.close();
} catch (IOException e
) {
e
.printStackTrace();
}finally {
closeable
= null
;
}
}
}
}
}
三、远程调用建模
3.1 我
服务的消费者
3.2 室友
服务的提供者,提供算出来1+1 = ? 答案
3.3 调用的内容->某种服务
1 +1 = ? 调用一个接口里面的方法
3.4 题目
3.5 答案
四、实现该模型
4.1 创建api 项目
Api 里面非常简单,只有一个接口
public interface AddService {
Integer
add(Integer a
,Integer b
);
Integer
desc(Integer a
,Integer b
);
}
4.2 服务的消费者
Maven 项目
4.2.1 服务提供者实现api
在pom.xml 文件里面依赖
<dependencies>
<dependency>
<groupId>com
.sxt
</groupId
>
<artifactId>api
</artifactId
>
<version>6.0</version
>
</dependency
>
</dependencies
>
实现接口
public class AddServiceImpl implements AddService{
@Override
public Integer
add(Integer a
, Integer b
) {
return a
+ b
;
}
@Override
public Integer
desc(Integer a
, Integer b
) {
return a
- b
;
}
}
4.2.2 服务提供者监听端口
public class ClassMateApp {
public static void main(String
[] args
) {
ServerSocket serverSocket
= null
;
try {
serverSocket
= new ServerSocket(8888);
} catch (IOException e
) {
e
.printStackTrace();
}
while(true) {
start(serverSocket
);
}
}
public static void start(ServerSocket serverSocket
) {
try {
System
.out
.println("开始监听菜逼的题目");
Socket socket
= serverSocket
.accept();
InputStream in
= socket
.getInputStream();
ObjectInputStream objectInputStream
= new ObjectInputStream(in
);
Request request
= (Request
)objectInputStream
.readObject();
Response answer
= getAnswer(request
);
OutputStream outputStream
= socket
.getOutputStream();
ObjectOutputStream objectOutputStream
= new
ObjectOutputStream(outputStream
);
objectOutputStream
.writeObject(answer
);
closes(objectOutputStream
,outputStream
,objectInputStream
,in
,socket
);
} catch (Exception e
) {
e
.printStackTrace();
}
}
public static void closes(Closeable
...closeables
) {
for (Closeable closeable
: closeables
) {
if(null
!=closeable
) {
try {
closeable
.close();
} catch (IOException e
) {
e
.printStackTrace();
closeable
= null
;
}
}
}
}
private static Response
getAnswer(Request request
)
throws ClassNotFoundException
, NoSuchMethodException
,
IllegalAccessException
, InvocationTargetException
{
String interfaceName
= request
.getInterfaceName();
String methodName
= request
.getMethodName();
Object
[] args2
= request
.getArgs();
Class
<?> interfcs
= Class
.forName(interfaceName
);
Object objectImpl
= getImplClass(interfcs
);
Class
<?>[] parameterTypes
= new Class<?>[args2
.length
];
for (int i
= 0; i
< parameterTypes
.length
; i
++) {
parameterTypes
[i
] = args2
[i
].getClass();
}
Method method
= objectImpl
.getClass().getMethod(methodName
, parameterTypes
);
Object result
= method
.invoke(objectImpl
, args2
);
Response response
= new Response();
response
.setResult(result
);
return response
;
}
private static Object
getImplClass(Class
<?> interfcs
) {
return new AddServiceImpl();
}
}
4.3 服务的消费者
4.3.1 服务消费者消费该接口
Pom.xml依赖
<dependencies>
<dependency>
<groupId>com
.sxt
</groupId
>
<artifactId>api
</artifactId
>
<version>6.0</version
>
</dependency
>
</dependencies
>
调用:
public class SelfConsumer {
public static void main(String
[] args
) {
System
.out
.println("我在考试");
System
.out
.println("有个题目 : 1 + 1= ? 不会");
System
.out
.println("求救室友");
AddService addServiceProxy
=
(AddService
)ProxyObjectFactory
.createProxy(AddService
.class);
Integer result
= addServiceProxy
.add(4, 6);
System
.out
.println("答案已经获取到了"+result
);
Integer desc
= addServiceProxy
.desc(5, 1);
System
.out
.println("答案已经获取到了"+desc
);
}
}
4.3.2 代理对象的调用细节
public class ProxyObjectFactory {
public static Object
createProxy(Class
<?> clazz
) {
return
Proxy
.newProxyInstance(ProxyObjectFactory
.class.getClassLoader(),
new Class<?>[] {clazz
}, new InvocationHandler() {
public Object
invoke(Object proxy
, Method method
, Object
[]
args
) throws Throwable
{
可
),你要调用这个对象里面的那个方法
(方法的名称
),还有这个方法的参数(args)
Response reps
= rpc(new Request(clazz
.getName(),
method
.getName(), args
));
return reps
.getResult();
}
});
}
public static Response
rpc(Request request
) {
Response response
= null
;
try {
Socket socket
= new Socket("localhost", 8888);
OutputStream outputStream
= socket
.getOutputStream();
ObjectOutputStream objectOutputStream
=
new ObjectOutputStream(outputStream
);
objectOutputStream
.writeObject(request
);
InputStream inputStream
= socket
.getInputStream();
ObjectInputStream objectInputStream
=
new ObjectInputStream(inputStream
);
response
= (Response
)objectInputStream
.readObject();
closes(objectInputStream
,inputStream
,objectOutputStream
,
outputStream
,socket
);
} catch (Exception e
) {
e
.printStackTrace();
}
return response
;
}
public static void closes(Closeable
...closeables
) {
for (Closeable closeable
: closeables
) {
if(null
!=closeable
) {
try {
closeable
.close();
} catch (IOException e
) {
e
.printStackTrace();
closeable
= null
;
}
}
}
}
}
五、引入负载均衡的概念
从一个列表里面选一个出来的过程
5.1 高并发
一个使用慢不过来,又请了一个室友 调用太多,一个人忙不过来 如何在3 个室友里面选一个出来
5.2 服务端的负载均衡
类似nginx 的模式,由服务决定访问那个地址
5.3 客户端的负载均衡
5.4 使用客户端的负载均衡来调用不同的室友
{ Localhost:8888 Localhost:7777 Localhost:9999 }
5.5 注册中心的引入
5.6 室友的启动后需要注册自己
5.7 我调用时,需要从注册中心拉取服务的列表
5.8 注册中心该怎么做?
Map<String,List> appCenter; { K: 服务名称, V:服务的地址 } Zookeeper 是最通用的注册中心