#575 小米路由器局域网不能互通
局域网 网络问题 路由器 小米路由器 WiFi 2021-06-27同一个 WiFi 内,笔记本和台式机无法 Ping 通。
虽然觉得可能性非常小,但还是关闭防火墙试了一下,果然没用。
最后在路由器上下工夫,经过两天的试验,发现可能和小米路由器有关系。
如果发现连接不上了,切换一下 WiFi 加密方式,似乎就正常。
也可能是断开重启的功劳。
总之,不知道原因。
coding in a complicated world
同一个 WiFi 内,笔记本和台式机无法 Ping 通。
虽然觉得可能性非常小,但还是关闭防火墙试了一下,果然没用。
最后在路由器上下工夫,经过两天的试验,发现可能和小米路由器有关系。
如果发现连接不上了,切换一下 WiFi 加密方式,似乎就正常。
也可能是断开重启的功劳。
总之,不知道原因。
除了 CPython 之外的几种比较知名的 Python 实现:
Python 本身的性能现在还很有待提升,但是为什么没有阻碍它的推广呢?
因为 Python 常常被当作是一种胶水语言,它有很好的与 C 互操作性,一直维护与 C 库对接的 API,也就是说很容易可以通过 C 拓展来提升性能。
PyPy 据说能有很大提升Pyston LLVM 编译器架构 + JITPsyco http://psyco.sourceforge.net/ 已经没有维护了,据说只维护到 Python 2.4Pyrex 编译成 C 模块Cython Pyrex 的分支, 更加接近 Python 语法一些Numba https://github.com/numba/numbaNuitka 尝试将 Python 代码编译成 C/C++Parakeet https://github.com/iskandr/parakeet 项目没有维护了Shedskin https://github.com/shedskin/shedskin 现在少有维护了SWIG: C/C++ 写的代码自动绑定到 Python,就是说生成一个 Python 可以调用的 .so 模块pybind11Boost.Python直接开发 CPython 拓展模块(include <Python.h>)也可以,但我不觉得这是一个好办法。
ctypes Python 标准库常用的一个 Python 图表工具。
基于 NumPy 的一个数据分析工具。
Include/object.h
/* Nothing is actually declared to be a PyObject, but every pointer to
* a Python object can be cast to a PyObject*. This is inheritance built
* by hand. Similarly every pointer to a variable-size Python object can,
* in addition, be cast to PyVarObject*.
*/
typedef struct _object {
_PyObject_HEAD_EXTRA // 如果开启了 Py_TRACE_REFS 增加一个 _ob_next, _ob_prev
// 使 all live heap objects 组成一个双向链表
Py_ssize_t ob_refcnt; // 长整型
PyTypeObject *ob_type;
} PyObject;
/* Cast argument to PyObject* type. */
#define _PyObject_CAST(op) ((PyObject*)(op))
#define _PyObject_CAST_CONST(op) ((const PyObject*)(op))
typedef struct {
PyObject ob_base;
Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;
/* Cast argument to PyVarObject* type. */
#define _PyVarObject_CAST(op) ((PyVarObject*)(op))
#define Py_REFCNT(ob) (_PyObject_CAST(ob)->ob_refcnt)
#define Py_TYPE(ob) (_PyObject_CAST(ob)->ob_type)
#define Py_SIZE(ob) (_PyVarObject_CAST(ob)->ob_size)
相当于所有 Python 对象的父类,包含类型,引用计数等信息。
注释说的很清楚,不会有直接声明的 PyObject 变量,只会有 PyObject* 指针,所有指向 Python 对象的指针都可以转换成 PyObject*。
表示 ob_size 个 PyObject,也就是说 PyVarObject 是一个 PyObject 的容器。
NumPy 提供了一个高效的数据结构(数组/矩阵)及对应运算支持,据说效率和 C 接近,是 Python 科学计算生态的基础。
RabbitMQ 是啥就不说了,怎么安装部署也不说了,就记录一下 RabbitMQ 在 Golang 开发中的应用。
说明:采用 github.com/streadway/amqp 库。
func (ch *Channel) Publish(exchange, key string, mandatory, immediate bool, msg Publishing) error
func (ch *Channel) Consume(queue, consumer string, autoAck, exclusive, noLocal, noWait bool, args Table) (<-chan Delivery, error)
amqp.Dial -> amqp.Connectionamqp.Connection.Channel -> amqp.Channelconn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
if err != nil {
log.Fatalf("Failed to connect to RabbitMQ: %s", err)
}
ch, err := conn.Channel()
if err != nil {
log.Fatalf("Failed to open a channel: %s", err)
}
事先把 MQ 配好就行,但从稳妥起见,还是在连接时加上比较好。
amqp.Channel.QueueDeclareamqp.Channel.ExchangeDeclareamqp.Channel.QueueBindq, err := ch.QueueDeclare(
"hello", // 队列名称
true, // 持久化
false, // 自动删除
false, // 独占
false, // 等待服务器回应
nil, // 额外参数
)
if err != nil {
log.Fatalf("Failed to declare a queue: %s", err)
}
amqp.Channel.Publisherr = ch.Publish(
"", // exchange
q.Name, // routing key
false, // mandatory
false, // immediate
amqp.Publishing{
ContentType: "text/plain",
Body: []byte("hello world"),
})
if err != nil {
log.Fatalf("Failed to publish a message: %s", err)
}
amqp.Connection.Closeamqp.Channel.Close和生产者基本一致。只是调用的的是 chan.Consume 而不是 chan.Publish。
然后就是配置阶段,消费者只用关心队列在不在。
package main
import (
"context"
"encoding/json"
"log"
"time"
"github.com/streadway/amqp"
)
// Consumer RabbitMQ 消费者
type Consumer struct {
conn *amqp.Connection
channel *amqp.Channel
queue string
}
// NewConsumer 创建消费者
func NewConsumer(conn *amqp.Connection, ch *amqp.Channel, queueName string) (*Consumer, error) {
// 声明队列
_, err = DeclareQueue(ch, queueName)
if err != nil {
return nil, err
}
return &Consumer{
conn: conn,
channel: ch,
queue: queueName,
}, nil
}
// Consume 消费消息
func (c *Consumer) Consume(ctx context.Context, workerID int) error {
// 设置 QoS
err := c.channel.Qos(
1, // prefetch count
0, // prefetch size
false, // global
)
if err != nil {
return err
}
// 开始消费
msgs, err := c.channel.Consume(
c.queue, // queue
"", // consumer
false, // auto-ack
false, // exclusive
false, // no-local
false, // no-wait
nil, // args
)
if err != nil {
return err
}
log.Printf("消费者 %d 已启动,等待消息...", workerID)
for {
select {
case <-ctx.Done():
log.Printf("消费者 %d 停止", workerID)
return nil
case msg, ok := <-msgs:
if !ok {
log.Printf("消费者 %d 消息通道关闭", workerID)
return nil
}
// 处理消息
var message Message
if err := json.Unmarshal(msg.Body, &message); err != nil {
log.Printf("解析消息失败: %v", err)
msg.Nack(false, false) // 拒绝消息,不重新入队
continue
}
// 模拟处理时间
log.Printf("消费者 %d 处理消息: %+v", workerID, message)
time.Sleep(1 * time.Second)
// 确认消息
if err := msg.Ack(false); err != nil {
log.Printf("确认消息失败: %v", err)
}
}
}
}
// Close 关闭连接
func (c *Consumer) Close() {
if c.channel != nil {
c.channel.Close()
}
if c.conn != nil {
c.conn.Close()
}
}
* 表示一个单词,# 表示若干个单词)Universally Unique Identifier 通用唯一识别码
是 ISO/IEC 标准,也定义在 IETF 的 RFC4122 中。
128 位,也就是 16 字节,通常使用 32 位 16 进制数字,以 8-4-4-4-12 的形式表示,例如:d09abf7e-3e39-11ec-9dbc-b1755772e461
最近听说一种新的 ID 生成器,叫做 NanoID,很多地方那个都把它拿来和 UUID 做对比。
我的结论:NanoID 没啥了不起,就是个随机字符串,取代不了 UUID。