先把以下链接的代码完成在根据笔记网下走
https://blog.csdn.net/weixin_38305440/article/details/102775484
文章目录
- 随堂笔记
- 笔记乱码问题
- 课程安排
- 课程要求
- sp01-commons
- eureka
- VMware
- 安装配置 RabbitMQ
- Order
- RabbitMQ
- ACK 和 qos=1
- 发布和订阅
- 作业
- rabbitmq
- 配置中心
- bus
- sleuth+zipkin
- rpc模式
- 作业
- 拼多商城
- Solr
- Docker
- redis
- web应用 + mysql
- eureka 和 item
- 作业
- k8s部署spring cloud应用
- Spring Cloud
- RabbitMQ
- Lucene Solr
- Docker
- Kubernetes
- 进入 item 目录, 重新执行上面两步, 重修构建镜像
- 作业
- k8s部署spring cloud应用
- Spring Cloud
- RabbitMQ
- Lucene Solr
- Docker
- Kubernetes
随堂笔记
这是随堂笔记, 详细内容请参考在线笔记:
https://blog.csdn.net/weixin_38305440
笔记乱码问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wW1NmhEq-1605679244364)(note.assets/image-20200501102330884.png)]
# 课前准备先做这几件事
注册csdn账号
注册 github 和 gitee.com 账号
创建项目,使用课前资料中的pom.xml,更新下载依赖
下载课前资料
天翼网盘不限速:
https://cloud.189.cn/t/2auEfqVZFJNv (访问码:jp2d)
百度网盘非会员限速:
https://pan.baidu.com/s/19tOuVOYJsplssj3kLvfzcA在线笔记地址
https://blog.csdn.net/weixin_38305440
课程安排
Spring Cloud - 6天(重点)
RabbitMQ - 2天(重点)
Lucene Solr - 1天
Docker + Kubernetes - 5天(重点)
课程要求
严格按照笔记来做
- 项目名
- 包名
- 类名
- …
好处
- 少踩坑
- 快速回退
贯穿项目
- 6天spring cloud是一个贯穿项目, 前后尽量保持一致
sp01-commons
public interface ItemService {
// 获取订单中的商品列表
List<Item> getItems(String orderId);
// 减少商品库存
void decreaseNumbers(List<Item> items);
}
public interface OrderService {
// 获取订单
Order getOrder(String orderId);
// 保存订单
void addOrder(Order order);
}
public interface UserService {
// 获取用户
User getUser(Integer id);
// 增加用户集分
void addScore(Integer userId, Integer score);
}
eureka
单台eureka服务器, 会自动配置一台默认的集群服务器 - localhost:8761
如果默认服务器不存在, 就会一次次反复尝试连接, 一次次反复出错.
自己配置集群后, 错误会消失.
VMware
最好使用最新版本的 VMware 15.x
能用 15 都用 15, 如果实在用不了也可以使用 12
课前资料\软件\VMware.zip
解压缩
可以先卸载旧版本, 然后安装 15.5.2
虚拟机
VMware15.x, 使用 CentOS-7-1908.zip
VMware12.x, 使用 CentOS-7-1908-vmware-12.zip
解压缩
双击 CentOS-7-1908.vmx
启动时选择 已复制该虚拟机
输入用户名密码
login: root
Password: root # 输入时没有任何反应, 但已经输入进去了
设置 NAT 网络网段
使用 192.168.64 网段
编辑–虚拟网络编辑器
如果没有管理员权限, 点击右下角更改设置
获取管理员权限
选择 VMnet8 网卡
设置虚拟机ip
在我给的虚拟机中, 添加了两个脚本文件, 可以方便地设置ip地址
./ip-static # 设置固定ip
./ip-dhcp # 动态分配ip
# 设置完ip后, 可以查看ip
ifconfig
# 测试网络通不通, ctrl+c结束
ping 192.168.64.1 # ping windows宿主机
ping www.baidu.com
VMware 网络设置笔记
https://blog.csdn.net/weixin_38305440/article/details/105082294
安装配置 RabbitMQ
-
把 CentOS-7-1908 虚拟机创建链接克隆: rabbitmq
-
启动 rabbitmq, 配置ip地址
./ip-static ip: 192.168.64.140 ifconfig ping 192.168.64.1
-
windows中, 用xshell 和 win-scp (或filezilla) 连接 140 服务器
- win-scp或filezilla连接时, 使用
SFTP
协议
- win-scp或filezilla连接时, 使用
-
课前资料\亿发课前资料(需要解压)\rabbitmq\rabbitmq-install.zip
-
解压rabbitmq-install.zip
-
用win-scp或filezilla上传 rabbitmq-install 目录
-
切换到这个目录, 安装离线文件
cd rabbitmq-install rpm -ivh *.rpm
Order
- 添加依赖:
- feign
- hystrix
- actuator
- yml
- feign.hystrx.enabled=true
- m.e.w.e.i=hystrix.stream
- 主程序注解
- @SpringCloudApplication
- @EnableFeignClients
RabbitMQ
package rabbitmq.m1_simple;
import java.io.IOException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Test1 {
public static void main(String[] args) throws Exception {
//1. 连接
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140"); //www.wht6.cn
f.setPort(5672); // 注意不是15672, 如果是默认5672端口, 这个设置可以省略
f.setUsername("admin");
f.setPassword("admin");
Connection con = f.newConnection();
Channel c = con.createChannel();
//2. 向服务器发送指令,要求服务器准备好队列: helloworld
//定义队列
c.queueDeclare("helloworld",false,false,false,null);
//3. 向指定的队列发送数据
//第四个参数是发送的消息数据, 必须是 byte[] 数组
c.basicPublish("", "helloworld", null,
("Hello world! "+System.currentTimeMillis()).getBytes());
System.out.println("消息已发送");
c.close();
con.close();
}
}
package rabbitmq.m1_simple;
import java.io.IOException;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class Test2 {
public static void main(String[] args) throws Exception {
//1. 连接
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140"); //www.wht6.cn
f.setPort(5672); //默认端口5672可以不设置
f.setUsername("admin");
f.setPassword("admin");
Connection con = f.newConnection();
Channel c = con.createChannel();
//2. 定义队列
//参数: 队列名,是否是持久队列,是否是消费者独占队列,没有消费者时是否自动删除,其他的参数属性配置
c.queueDeclare("helloworld",false,false,false,null);
//回调对象
DeliverCallback deliverCallback = new DeliverCallback() {
public void handle(String consumerTag, Delivery message) throws IOException {
byte[] a = message.getBody();
String msg = new String(a);
System.out.println("收到: "+msg);
}
};
CancelCallback cancelCallback = new CancelCallback() {
public void handle(String consumerTag) throws IOException {
}
};
//3. 从队列接收数据
c.basicConsume("helloworld", true, deliverCallback, cancelCallback);
}
}
package rabbitmq.m2_work;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
public class Test1 {
public static void main(String[] args) throws Exception {
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140"); //www.wht6.cn
f.setUsername("admin");
f.setPassword("admin");
//f.setVirtualHost("/wht");
Channel c = f.newConnection().createChannel();
//定义队列
c.queueDeclare("helloworld",false,false,false,null);
//发送数据
while (true) {
System.out.print("输入:");
String msg = new Scanner(System.in).nextLine();
c.basicPublish("", "helloworld", null, msg.getBytes());
}
}
}
package rabbitmq.m2_work;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class Test2 {
public static void main(String[] args) throws Exception {
//1. 连接
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140"); //www.wht6.cn
f.setUsername("admin");
f.setPassword("admin");
//f.setVirtualHost("/wht");
Channel c = f.newConnection().createChannel();
//2. 定义队列
c.queueDeclare("helloworld",false,false,false,null); //是否持久队列,是否排他队列,是否自动删除,其他属性
DeliverCallback deliverCallback = new DeliverCallback() {
public void handle(String consumerTag, Delivery message) throws IOException {
byte[] a = message.getBody();
String msg = new String(a);
System.out.println("收到: "+msg);
// "sdfs.dfs........sdf....sdf.......sd.sdfs........sf....sdf.........."
for (int i = 0; i < msg.length(); i++) {
if ('.' == msg.charAt(i)) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
System.out.println("消息处理结束\n");
}
};
CancelCallback cancelCallback = new CancelCallback() {
public void handle(String consumerTag) throws IOException {
}
};
//3. 消费数据
c.basicConsume("helloworld", true, deliverCallback, cancelCallback);
}
}
ACK 和 qos=1
package rabbitmq.m2_work;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class Test2 {
public static void main(String[] args) throws Exception {
//1. 连接
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140"); //www.wht6.cn
f.setUsername("admin");
f.setPassword("admin");
//f.setVirtualHost("/wht");
Channel c = f.newConnection().createChannel();
//2. 定义队列
c.queueDeclare("helloworld",false,false,false,null); //是否持久队列,是否排他队列,是否自动删除,其他属性
DeliverCallback deliverCallback = new DeliverCallback() {
public void handle(String consumerTag, Delivery message) throws IOException {
byte[] a = message.getBody();
String msg = new String(a);
System.out.println("收到: "+msg);
// "sdfs.dfs........sdf....sdf.......sd.sdfs........sf....sdf.........."
for (int i = 0; i < msg.length(); i++) {
if ('.' == msg.charAt(i)) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
//发送回执
//回执, 是否确认之前收到的所有消息
c.basicAck(message.getEnvelope().getDeliveryTag(), false);
System.out.println("消息处理结束\n");
}
};
CancelCallback cancelCallback = new CancelCallback() {
public void handle(String consumerTag) throws IOException {
}
};
// qos - 1 每次只抓取一条消息, 消息处理完成之前, 不抓取下一条
// 只在手动确认模式下有效
c.basicQos(1);
//3. 消费数据
/*
* 第二个参数
* true - 自动ACK
* false - 手动确认, 需要手动发送消息回执
*/
c.basicConsume("helloworld", false, deliverCallback, cancelCallback);
}
}
发布和订阅
package rabbitmq.m3_publishsubscribe;
import java.util.Scanner;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
public class Test1 {
public static void main(String[] args) throws Exception {
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140"); //www.wht6.cn
f.setUsername("admin");
f.setPassword("admin");
//f.setVirtualHost("/wht");
Channel c = f.newConnection().createChannel();
//定义交换机
c.exchangeDeclare("logs", "fanout");
//发送数据
while (true) {
System.out.print("输入:");
String msg = new Scanner(System.in).nextLine();
/*
* 第一个参数
* 空串 - 默认的直连交换机(direct)
*
* 第二个参数
* 对于发布和订阅模式无效
*/
c.basicPublish("logs", "", null, msg.getBytes());
}
}
}
作业
- 下载第5章代码, 重做 7到19
- 下载第17章代码, 重做 18,19
rabbitmq
package rabbitmq.m3_publishsubscribe;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class Test2 {
public static void main(String[] args) throws Exception {
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140"); // www.wht6.cn
f.setPort(5672);
f.setUsername("admin");
f.setPassword("admin");
//f.setVirtualHost("/xxxxxxxx");
Channel c = f.newConnection().createChannel();
// 1.定义交换机 2.定义队列 3.绑定
c.exchangeDeclare("logs", "fanout");
// 服务器随机命名,非持久,排他(独占),自动删除,其他属性
String queue = c.queueDeclare().getQueue();
// 第三个参数,对于fanout交换机无效
c.queueBind(queue, "logs", "");
DeliverCallback deliverCallback = new DeliverCallback() {
public void handle(String consumerTag, Delivery message) throws IOException {
String msg = new String(message.getBody());
System.out.println("收到: "+msg);
}
};
CancelCallback cancelCallback = new CancelCallback() {
public void handle(String consumerTag) throws IOException {
}
};
// 正常从队列接收数据
c.basicConsume(queue, true, deliverCallback, cancelCallback);
}
}
package rabbitmq.m4_routing;
import java.util.Scanner;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
public class Test1 {
public static void main(String[] args) throws Exception {
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140"); //www.wht6.cn
f.setUsername("admin");
f.setPassword("admin");
//f.setVirtualHost("/wht");
Channel c = f.newConnection().createChannel();
// 定义交换机
//c.exchangeDeclare("direct_logs", "direct");
c.exchangeDeclare("direct_logs", BuiltinExchangeType.DIRECT);
while (true) {
System.out.print("输入消息:");
String msg = new Scanner(System.in).nextLine();
System.out.print("输入路由键:");
String key = new Scanner(System.in).nextLine();
// 第二个参数是路由键, 用路由键做关键词匹配,决定把消息发到哪个队列
c.basicPublish("direct_logs", key, null, msg.getBytes());
}
}
}
package rabbitmq.m4_routing;
import java.io.IOException;
import java.util.Scanner;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class Test2 {
public static void main(String[] args) throws Exception {
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140"); //www.wht6.cn
f.setUsername("admin");
f.setPassword("admin");
//f.setVirtualHost("/wht");
Channel c = f.newConnection().createChannel();
//1.定义交换机 2.定义随机队列 3.绑定
c.exchangeDeclare("direct_logs", BuiltinExchangeType.DIRECT);
String queue = c.queueDeclare().getQueue();
System.out.println("输入绑定键,用空格隔开: "); // "aaaa bbb cccccc"
String s = new Scanner(System.in).nextLine();
String[] a = s.split("\\s+");
for (String key : a) {
c.queueBind(queue, "direct_logs", key);
}
DeliverCallback deliverCallback = new DeliverCallback() {
public void handle(String consumerTag, Delivery message) throws IOException {
// 取出消息数据, 和路由键
String msg = new String(message.getBody());
String key = message.getEnvelope().getRoutingKey();
System.out.println("收到: "+key+" - "+msg);
}
};
CancelCallback cancelCallback = new CancelCallback() {
public void handle(String consumerTag) throws IOException {
}
};
//正常接收消费数据
c.basicConsume(queue, true, deliverCallback, cancelCallback);
}
}
package rabbitmq.m5_topic;
import java.util.Scanner;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
public class Test1 {
public static void main(String[] args) throws Exception {
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140"); //www.wht6.cn
f.setUsername("admin");
f.setPassword("admin");
//f.setVirtualHost("/wht");
Channel c = f.newConnection().createChannel();
// 定义交换机
c.exchangeDeclare("topic_logs", BuiltinExchangeType.TOPIC);
//发送数据
while (true) {
System.out.print("输入消息: ");
String msg = new Scanner(System.in).nextLine();
System.out.print("输入路由键: ");
String key = new Scanner(System.in).nextLine(); // aaaa.bbb.ccccccc.ddd
c.basicPublish("topic_logs", key, null, msg.getBytes());
}
}
}
package rabbitmq.m5_topic;
import java.io.IOException;
import java.util.Scanner;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class Test2 {
public static void main(String[] args) throws Exception {
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140"); //www.wht6.cn
f.setUsername("admin");
f.setPassword("admin");
//f.setVirtualHost("/wht");
Channel c = f.newConnection().createChannel();
// 定义交换机, 定义随机队列, 绑定
c.exchangeDeclare("topic_logs", BuiltinExchangeType.TOPIC);
String queue = c.queueDeclare().getQueue();
System.out.println("输入绑定键,用空格隔开: ");
String s = new Scanner(System.in).nextLine();
String[] a = s.split("\\s+");
for (String key : a) {
c.queueBind(queue, "topic_logs", key);
}
DeliverCallback deliverCallback = new DeliverCallback() {
public void handle(String consumerTag, Delivery message) throws IOException {
// 取出消息和路由键
String msg = new String(message.getBody());
String key = message.getEnvelope().getRoutingKey();
System.out.println("收到: "+key+" - "+msg);
}
};
CancelCallback cancelCallback = new CancelCallback() {
public void handle(String consumerTag) throws IOException {
}
};
// 消费数据
c.basicConsume(queue, true, deliverCallback, cancelCallback);
}
}
配置中心
- 远程仓库
- 远程仓库四个文件
- 如果自己的仓库不能用,可以用我的仓库
- https://gitee.com/benwang6/sp-config
- 搭建配置中心
- uri - 远程仓库的地址
- search-path - config子目录
- @EnableConfigServer
- 确认
- http://eureka1:2001/ 需要看到
config-server
的注册信息 - http://localhost:6001/item-service/dev
- http://localhost:6001/user-service/dev
- http://localhost:6001/order-service/dev
- http://localhost:6001/zuul/dev
- http://eureka1:2001/ 需要看到
- 配置中心客户端服务
- 添加 config client 依赖(注意不是config client(PCF))
- bootstrap.yml
- 启动测试
- 先启动 5, 等待5完全启动!!!
- 再启动12, 等待12完全启动!!!
- 确认 http://eureka1:2001/ 有 config-server的注册信息
- 启动2,3,4,11
- 确认
- 控制台是否在连接 6001, 下载配置信息
bus
-
修改 2,3,4,11,12 项目
- 添加bus和rabbitmq依赖
- 配置rabbitmq的连接信息
- 12项目 - 直接修改 application.yml
- 2,3,4,11项目 - config项目中的四个配置文件, 修改后推送到远程仓库
-
修改 12 项目, 暴露 bus-refresh 端点
-
按顺序启动项目
-
启动 rabbitmq 服务器
-
启动5, 等待完全启动!!!
-
启动12, 等待完全启动!!! 确认 http://eureka1:2001 有没有注册信息
-
确认配置文件可访问
http://localhost:6001/item-service/dev
http://localhost:6001/user-service/dev
http://localhost:6001/order-service/dev
http://localhost:6001/zuul/dev
-
-
再启动 2,3,4,11, 确认控制台有连接 6001 的日志
-
确认 http://localhost:6001/actuator 有没有 bus-refresh
-
sleuth+zipkin
- 添加sleuth依赖, 产生链路跟踪数据
- 添加zipkin client依赖
- rabbitmq 依赖, 配置rabbitmq连接信息
- spring.zipkin.sender.type=rabbit
rpc模式
package rabbitmq.m6_rpc;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class RpcServer {
public static void main(String[] args) throws Throwable {
//1. 接收客户端的调用数据: n值, 返回队列名, 关联id
//2. 执行运算求出斐波那契数
//3. 发回计算结果, 要携带关联id
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140"); //www.wht6.cn
f.setUsername("admin");
f.setPassword("admin");
//f.setVirtualHost("/wht");
Channel c = f.newConnection().createChannel();
//定义调用队列
c.queueDeclare("rpc_queue",false,false,false,null);
DeliverCallback deliverCallback = new DeliverCallback() {
public void handle(String consumerTag, Delivery message) throws IOException {
//收到调用数据, n值, 返回队列名, 关联id
String msg = new String(message.getBody());
String replyTo = message.getProperties().getReplyTo();
String cid = message.getProperties().getCorrelationId();
System.out.println(msg+", "+replyTo+", "+cid);
//执行运算
long result = fbnq(Integer.parseInt(msg));
//发回计算结果, 向 replyTo 队列发送, 携带 cid
BasicProperties props =
new BasicProperties.Builder()
.correlationId(cid)
.build();
c.basicPublish("", replyTo, props, (""+result).getBytes());
System.out.println("已向客户端发回结果");
}
};
CancelCallback cancelCallback = new CancelCallback() {
public void handle(String consumerTag) throws IOException {
}
};
//从rpc_queue消费数据
c.basicConsume("rpc_queue", true, deliverCallback, cancelCallback);
}
/*
* 计算斐波那契数的服务
* 接收的参数是求第几个斐波那契数
*
* 1 1 2 3 5 8 13 21 34 55 89 144 233 ....
*/
static long fbnq(int n) {
if (n == 1 || n == 2) {
return 1;
}
return fbnq(n-1) + fbnq(n-2);
}
}
package rabbitmq.m6_rpc;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class TestABQ {
static BlockingQueue<Double> q = new ArrayBlockingQueue<>(10);
public static void main(String[] args) {
//放数据
new Thread() {
public void run() {
System.out.println("\n线程1 - 按回车放入数据");
new Scanner(System.in).nextLine();
double d = Math.random();
q.offer(d);//放入数据
System.out.println("线程1 - 放入数据:"+d);
}
}.start();
//取数据
new Thread() {
public void run() {
try {
System.out.println("线程2 - 正在获取数据");
Double d = q.take();
System.out.println("线程2 - 已经获取数据: "+d);
} catch (InterruptedException e) {
}
}
}.start();
}
}
package rabbitmq.m6_rpc;
import java.io.IOException;
import java.util.Scanner;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
public class RpcClient {
static BlockingQueue<String> q = new ArrayBlockingQueue<>(10);
public static void main(String[] args) throws Exception {
while (true) {
System.out.print("求第几个斐波那契数:");
int n = new Scanner(System.in).nextInt();
long r = f(n);
System.out.println(r);
}
}
private static long f(int n) throws Exception {
//1. 发送调用数据
//2. 接收执行结果
ConnectionFactory f = new ConnectionFactory();
f.setHost("192.168.64.140"); //www.wht6.cn
f.setUsername("admin");
f.setPassword("admin");
//f.setVirtualHost("/wht");
Channel c = f.newConnection().createChannel();
// 发送的数据: n, 返回队列的队列名, 关联id
c.queueDeclare("rpc_queue",false,false,false,null);
String queue = c.queueDeclare().getQueue(); //服务器随机命名,非持久,排他,自动删除
String cid = UUID.randomUUID().toString();
BasicProperties props =
new BasicProperties.Builder()
.replyTo(queue)
.correlationId(cid)
.build();
c.basicPublish("", "rpc_queue", props, (""+n).getBytes());
System.out.println("已发送调用");
System.out.println("主线程不必等待, 继续执行其他运算......");
System.out.println("直到需要结果时, 再取结果");
DeliverCallback deliverCallback = new DeliverCallback() {
public void handle(String consumerTag, Delivery message) throws IOException {
//处理从服务器返回的计算结果
//把计算结果放入一个集合
String msg = new String(message.getBody());
String cid2 = message.getProperties().getCorrelationId();
//模拟判断关联id的匹配
if (cid.equals(cid2)) {
q.offer(msg);
}
}
};
CancelCallback cancelCallback = new CancelCallback() {
public void handle(String consumerTag) throws IOException {
}
};
//接收结果
c.basicConsume(queue, true, deliverCallback, cancelCallback);
//主线程从集合取结果
return Long.parseLong(q.take());
}
}
作业
- 下载第5章代码, 从第7章重做
- 下载第17章代码, 从第18章重做
- 下载第21章代码, 从第23章重做
拼多商城
-
导入项目
- 亿发课前资料\solr\06-拼多项目
- 项目解压缩
- 导入eclipse, 导入"existing maven project"
-
导入数据库
-
亿发课前资料\solr\04-拼多数据库\pd.sql
-
sqlyog 连接mysql, 导如 pd.sql
-
-
oracle的mysql 8
- pom.xml
- mysql 驱动, 添加版本:
<version>8.0.20</version>
- mysql 驱动, 添加版本:
- application.yml
- mysql连接地址, 添加timezone参数:
&serverTimezone=Asia/Shanghai
- mysql连接地址, 添加timezone参数:
- 启动项目
- 启动类:
RunPdApp
- 启动类:
- 注册登录
- 如果填的用户名,email,电话重复,不能注册
- 添加收货地址
Solr
准备服务器
-
克隆 centos-7-1908: solr
-
设置ip
./ip-static ip: 192.168.64.170
-
xshell 和 winscp(或filezilla) 连接 170 服务器
安装配置JDK
- 上传
jdk-8u212-linux-x64.tar.gz
- 解压缩 jdk
tar xf jdk-8u212-linux-x64.tar.gz -C /usr/local/
- 配置环境变量
cd /usr/local/jdk1.8.0_212
pwd #查看jdk的完整路径, 并复制这个路径
# 一会一块做这个设置, 不要自己乱动
vim /etc/profile
# 在文件末尾添加:
JAVA_HOME=/usr/local/jdk1.8.0_212
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=.
export JAVA_HOME PATH CLASSPATH
#退出编辑后, 让配置文件立即生效
source /etc/profile
- 确认
java -version
javac -version
安装配置Solr
-
上传
solr-8.1.1.tgz
-
解压缩
cd ~
tar xf solr-8.1.1.tgz -C /usr/local
- 启动solr服务器
cd /usr/local/solr-8.1.1
bin/solr start -force
- 打开端口,访问测试
firewall-cmd --zone=public --add-port=8983/tcp --permanent
firewall-cmd --reload
http://192.168.64.170:8983
创建 core (核心): pd
在pd核心配置中文分词器: ik分词
pd核心设置文档的字段
配置从mysql导入数据
# mysql 5 或 mariadb
grant all on *.* to 'root'@'%' identified by 'root';
# mysql 8
create user 'root'@'%' identified by 'root';
grant all privileges on *.* to 'root'@'%';
dih-config.xml
数据库连接信息, 和查询语句
solrconfig.xml
指定上面的配置文件文件名
导入数据失败
- 下载我的三个配置文件, 传到你的 solr 服务器
- dih-config.xml, 使用 windows 的物理网络ip
- 关闭windows防火墙
- 检查 mysql 驱动jar文件有没有
Docker
- Centos-7-1908 克隆: docker
- 设置 ip
./ip-static
ip: 192.168.64.150
导入后面要是用的镜像
课前资料/devops课前资料/docker
5个 *-image.gz 文件, 上传到服务器
把镜像压缩文件, 导入到docker
docker load -i centos7-docker-image.gz
docker load -i mariadb-docker-image.gz
docker load -i redis-docker-image.gz
docker load -i solr-docker-image.gz
docker load -i tomcat-docker-image.gz
# 镜像列表
docker images
centos7 容器
docker run \
-it \
--name centos7 \
centos:7 \
bash
# 在容器内, 可以执行命令, 进行测试
ls
pwd
ps
# 退出容器, 回到宿主机
exit
容器命令
# 可以先把之前同名的 centos7 容器删除
docker rm -f centos7
# 启动一个新的容器, 命名为 centos7
docker run \
-dit \
--name centos7 \
centos:7
# 查看容器列表
docker ps # 列出正在运行的容器
docker ps -a # 列出全部容器, 包括已经关闭的容器
进入容器执行指定命令
docker exec -it centos7 ls
docker exec -it centos7 pwd
docker exec -it centos7 ps
docker exec -it centos7 mkdir dir1
docker exec -it centos7 ls # 查看容器内部新建的 dir1 目录
docker exec -it centos7 bash
# 退出命令行
exit
目录挂载
# 容器停止时,自动删除容器
# --rm \
# 如果左侧宿主机目录不存在, 会自动创建目录
#-v /usr/app:/opt/app \
docker run \
-dit \
--name centos7 \
--rm \
-v /usr/app:/opt/app \
centos:7
# 进入容器
docker exec -it centos7 bash
echo 111111111111 > /opt/app/f1
cd /opt/app
ls
cat f1
# 在宿主机查看文件
exit
cd /usr/app
ls
cat f1
# 停止容器(停止时,容器会被自动删除)
docker container stop centos7
docker ps -a
ls
cat f1
# 创建数据卷
docker volume create my-vol
# 查看数据卷
docker inspect my-vol
# 启动容器,挂载数据卷
docker run \
-dit \
--name centos7 \
--rm \
-v my-vol:/webapp \
centos:7
# 进入容器
docker exec -it centos7 bash
echo 111111111111 > /webapp/f1
cd /webapp
ls
cat f1
# 在宿主机查看文件
exit
cd /var/lib/docker/volumes/my-vol/_data
ls
cat f1
端口映射
docker run \
-d \
--name tomcat80 \
-p 80:8080 \
--rm \
tomcat
docker ps
docker logs tomcat80
# 浏览器访问
# http://192.168.64.150
Docker 虚拟网络
docker network create my-net
docker network ls
docker inspect my-net
ifconfig
# 启动容器,连入my-net网络
docker run -dit --name app1 --rm --network my-net centos:7
docker run -dit --name app2 --rm --network my-net centos:7
# 查看容器描述
docker inspect app1
docker inspect app2
# 从宿主机ping两个容器
ping 172.18.0.2
ping 172.18.0.3
# 从app1, ping宿主机和app2
docker exec -it app1 ping 172.18.0.1
docker exec -it app1 ping 172.18.0.3
docker exec -it app1 ping app2
Dockerfile构建镜像
-
新建文件夹, 把Dockerfile和其他需要的文件,放入这个目录
mkdir tomcat7 在tomcat7目录下, 放入: - Dockerfile - jdk-8u212-linux-x64.tar.gz - apache-tomcat-7.0.96.tar.gz cd tomcat7 # 末尾的点, 表示当前目录, 在当前目录下寻找Dockerfile, 和其他所有文件 docker build -t tomcat:7 . # 构建完成后, 查看镜像 docker images
redis
docker run -d --name redis7000 -p 7000:6379 redis
docker exec -it redis7000 redis-cli
keys *
set a b
get a
flushall
docker run -d --name redis7001 -p 7001:6379 redis
docker run -d --name redis7002 -p 7002:6379 redis
docker exec -it redis7000 redis-cli
keys *
exit
docker exec -it redis7001 redis-cli
keys *
exit
docker exec -it redis7002 redis-cli
keys *
exit
web应用 + mysql
# 删除 my-net 网络
docker network rm my-net
# 创建 dockernet
docker network create --subnet 172.18.0.0/24 dockernet
# 创建 mysql-data 数据卷
docker volume create mysql-data
# 启动mysql
docker run \
-d \
--rm \
--name mysql \
-v mysql-data:/var/lib/mysql \
-p 3306:3306 \
--net dockernet \
--ip 172.18.0.11 \
-e MYSQL_ROOT_PASSWORD=root \
mariadb
# 准备web应用的 war 文件
rm -rf /opt/webapps
mkdir /opt/webapps
# 把 ROOT.war 上传到 /opt/webapps
# 启动tomcat
docker run \
-d \
--name tomcat \
--rm \
-v /opt/webapps:/usr/tomcat/webapps \
-p 80:8080 \
--net dockernet \
--ip 172.18.0.12 \
tomcat:7
eureka 和 item
不加配置中心,链路跟踪
-
下载 第18章 代码, 导入 1,2,5 三个项目
-
修改 2,5 项目的 application.yml, 注册ip地址
eureka:
instance:
prefer-ip-address: true
-
三个项目打包jar文件
右键 — run as — maven build …
goal: install
下面勾选: skip tests
构建镜像
准备三个目录
- jdk8
- Dockerfile
- jdk-8u212-linux-x64.tar.gz
- eureka
- Dockerfile
- sp05-eureka-0.0.1-SNAPSHOT.jar
- item
- Dockerfile
- sp02-itemservice-0.0.1-SNAPSHOT.jar
jdk8的Dockerfile和镜像构建
cat <<EOF > Dockerfile
FROM centos:7
ADD jdk-8u212-linux-x64.tar.gz /opt/
ENV JAVA_HOME=/opt/jdk1.8.0_212 \
PATH=$PATH:/opt/jdk1.8.0_212/bin
EOF
# 构建jdk8镜像
docker build -t jdk:8 .
eureka的Dockerfile和镜像构建
cat <<EOF > Dockerfile
FROM jdk:8
COPY sp05-eureka-0.0.1-SNAPSHOT.jar /opt/
ENTRYPOINT ["java", "-jar", "/opt/sp05-eureka-0.0.1-SNAPSHOT.jar"]
CMD ["--spring.profiles.active=eureka1", "--server.port=2001"]
EOF
# 构建eureka:1镜像
docker build -t eureka:1 .
item的Dockerfile和镜像构建
cat <<EOF > Dockerfile
FROM jdk:8
COPY sp02-itemservice-0.0.1-SNAPSHOT.jar /opt/
ENTRYPOINT ["java", "-jar", "/opt/sp02-itemservice-0.0.1-SNAPSHOT.jar"]
CMD ["--server.port=8001"]
EOF
# 构建item:8001镜像
docker build -t item:8001 .
# 重新构建 item 镜像
docker rmi -f item:8001 # 删镜像
docker rm -f item8001 # 删容器
# 进入 item 目录, 重新执行上面两步, 重修构建镜像
启动eureka容器
# 如果已经启动了eureka,先删除
docker rm -f eureka1
# 启动eureka,连接到dockernet网络
docker run \
-d \
--name eureka1 \
-p 2001:2001 \
--net dockernet \
eureka:1
# 启动item,连接到dockernet网络
docker run \
-d \
--name item8001 \
-p 8001:8001 \
--net dockernet \
item:8001
# 访问测试:
http://192.168.64.150:2001
http://192.168.64.150:8001/u56u56u45y3t
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RuEvEnH1-1605679244368)(note.assets/image-20200519115125418.png)]
作业
- 下载 第17章代码, 从第18章重做
- rabbitmq, 订单流量削峰
k8s部署spring cloud应用
5个文件夹
eureka
Dockerfile
sp05-eureka-0.0.1-SNAPSHOT.jar
item
Dockerfile
sp02-itemservice-0.0.1-SNAPSHOT.jar
jdk
Dockerfile
jdk-8u212-linux-x64.tar.gz
order
Dockerfile
sp04-orderservice-0.0.1-SNAPSHOT.jar
user
Dockerfile
sp03-userservice-0.0.1-SNAPSHOT.jar
上传到 191
- 上传5个文件夹
- 上传centos7的镜像, 或者可以在线拉取:
docker pull centos:7
- 把docker目录下的
centos7-docker-image.gz
传到服务器 - 执行导入:
docker load -i centos7-docker-image.gz
- 把docker目录下的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pNKwgdgC-1605679244369)(note.assets/image-20200523143726045.png)]
Spring Cloud
- 微服务全家桶
- Netflix 开源项目
- eureka
- ribbon
- hystrix
- feign
- zuul
- hystrix dashboard+turbine
- Spring Cloud Alibaba
RabbitMQ
-
使用场景: 解耦, 削峰, 异步调用
-
你的项目中如何使用RabbitMQ: 订单的流量削峰
-
六种模式
- 简单
- 工作
- 发布和订阅
- 路由
- 主题
- RPC
Lucene Solr
-
全文检索引擎
-
索引: 倒排索引
Docker
-
容器化
-
开发,测试,运维, 环境完全一致
Kubernetes
- 自动化容器部署工具
- 核心组件
- Pod
- 控制器
- ReplicationController
- ReplicSet
- Service
- Deployment
item 镜像
docker rmi -f item:8001 # 删镜像
docker rm -f item8001 # 删容器
进入 item 目录, 重新执行上面两步, 重修构建镜像
### 启动eureka容器
```shell
# 如果已经启动了eureka,先删除
docker rm -f eureka1
# 启动eureka,连接到dockernet网络
docker run \
-d \
--name eureka1 \
-p 2001:2001 \
--net dockernet \
eureka:1
# 启动item,连接到dockernet网络
docker run \
-d \
--name item8001 \
-p 8001:8001 \
--net dockernet \
item:8001
# 访问测试:
http://192.168.64.150:2001
http://192.168.64.150:8001/u56u56u45y3t
[外链图片转存中…(img-RuEvEnH1-1605679244368)]
作业
- 下载 第17章代码, 从第18章重做
- rabbitmq, 订单流量削峰
k8s部署spring cloud应用
5个文件夹
eureka
Dockerfile
sp05-eureka-0.0.1-SNAPSHOT.jar
item
Dockerfile
sp02-itemservice-0.0.1-SNAPSHOT.jar
jdk
Dockerfile
jdk-8u212-linux-x64.tar.gz
order
Dockerfile
sp04-orderservice-0.0.1-SNAPSHOT.jar
user
Dockerfile
sp03-userservice-0.0.1-SNAPSHOT.jar
上传到 191
- 上传5个文件夹
- 上传centos7的镜像, 或者可以在线拉取:
docker pull centos:7
- 把docker目录下的
centos7-docker-image.gz
传到服务器 - 执行导入:
docker load -i centos7-docker-image.gz
- 把docker目录下的
[外链图片转存中…(img-pNKwgdgC-1605679244369)]
Spring Cloud
- 微服务全家桶
- Netflix 开源项目
- eureka
- ribbon
- hystrix
- feign
- zuul
- hystrix dashboard+turbine
- Spring Cloud Alibaba
RabbitMQ
-
使用场景: 解耦, 削峰, 异步调用
-
你的项目中如何使用RabbitMQ: 订单的流量削峰
-
六种模式
- 简单
- 工作
- 发布和订阅
- 路由
- 主题
- RPC
Lucene Solr
-
全文检索引擎
-
索引: 倒排索引
Docker
-
容器化
-
开发,测试,运维, 环境完全一致
Kubernetes
- 自动化容器部署工具
- 核心组件
- Pod
- 控制器
- ReplicationController
- ReplicSet
- Service
- Deployment