我想从Phoenix应用程序连接到Redis,但是无法连接。
我正在使用Phoenix v1.3.0。我安装了Redix软件包。在lib / myapp.ex中,我有以下代码
defmodule myapp do
use Application
# See http://elixir-lang.org/docs/stable/elixir/Application.html
# for more information on OTP Applications
def start(_type, _args) do
import Supervisor.Spec
# Get all configuration used for Cache module
pool_size = Application.get_env(:myapp, :redis_pool_size)
redis_host = Application.get_env(:myapp, :redis_host)
redis_port = Application.get_env(:myapp, :redis_port)
# Define workers and child supervisors to be supervised
children = [
# Start the Ecto repository
supervisor(myapp.Repo, []),
# Start the endpoint when the application starts
supervisor(myapp.Endpoint, []),
#Start redis supervisor
supervisor(myapp.Cache.Supervisor, [
%{
pool_size: pool_size,
host: redis_host,
port: redis_port
}
])
# supervisor(Kafka.Endpoint, [])
]
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: myapp.Supervisor]
Supervisor.start_link(children, opts)
end
# Tell Phoenix to update the endpoint configuration
# whenever the application is updated.
def config_change(changed, _new, removed) do
myapp.Endpoint.config_change(changed, removed)
:ok
end
end
我在lib / myapp / cache / cache.ex中
defmodule MyApp.Cache do
require Logger
def setex(segment, key, value, ttl \\ nil) do
ttl = ttl || get_default_ttl()
pid = get_pid()
key = build_key(segment, key)
command = ["SETEX", key, ttl, value]
run_command(pid, command)
end
def get(segment, key) do
pid = get_pid()
key = build_key(segment, key)
command = ["GET", key]
run_command(pid, command)
end
def flush_all do
pid = get_pid()
command = ["FLUSHALL"]
run_command(pid, command)
end
defp get_default_ttl(), do: Application.get_env(:myapp, :redis_ttl)
defp get_app_name(), do: Application.get_env(:myapp, :app_name)
defp get_pool_size(), do: Application.get_env(:myapp, :redis_pool_size)
defp build_key(segment, key), do: "#{get_app_name()}:#{segment}-#{key}"
defp get_pid, do: :"redix_#{random_index()}"
defp random_index(), do: rem(System.unique_integer([:positive]), get_pool_size())
defp run_command(pid, command) do
Logger.debug("Running command: #{inspect(command)} in Redis")
Redix.command(pid, command)
end
end
在lib / myapp / cache / supervisor.ex中,我有
defmodule MyApp.Cache.Supervisor do
use Supervisor
def start_link(opts) do
Supervisor.start_link(__MODULE__, opts, name: __MODULE__)
end
def init(%{
pool_size: pool_size,
host: host,
port: port
}) do
children =
for i <- 0..(pool_size - 1) do
Supervisor.child_spec(
{Redix, [host: host, port: port, name: :"redix_#{i}"]},
id: {Redix, i}
)
end
Supervisor.init(children, strategy: :one_for_one)
end
end
现在,当我运行MyApp.get("1", "2")
时,出现以下错误:
(ArgumentError)参数错误(stdlib) :ets.lookup(:telemetry_handler_table,[:redix,:pipeline])
我签入Redis,键和值确实存在。我该如何解决?
谢谢
答案 0 :(得分:0)
现在,当我运行MyApp.get(“ 1”,“ 2”)时,出现以下错误:
没有名为MyApp的模块-您编写了defmodule myapp
-在该模块中没有名为get()
的函数。与其描述您所做的事情,不如复制并粘贴您在iex和输出中执行的命令。
在使用mix创建新的phoenix项目时,应该有一个名为myapp/lib/myapp/application.ex
的文件,该文件定义了模块defmodule MyApp.Application
,其中包含您为文件lib/myapp.ex
发布的代码。
此:
pid = get_pid()
是一个命名错误的函数,因为它不返回pid -它返回一个原子。
还请检查一下:
iex(21)> for _ <- 1..20, do: System.unique_integer([:positive])
[9412, 9444, 9476, 9508, 9540, 9572, 9604, 9636, 9668,
9700, 9732, 9764, 9796, 9828, 9860, 9892, 9924, 9956,
9988, 10020]
iex(22)> for _ <- 1..20, do: rem(System.unique_integer([:positive]), 4)
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
请注意,在第一个数字列表中,每个数字比前一个数字多32个。您想要的功能是:
Enum.random(1..get_pool_size() )
现在查看输出:
for _ <- 1..20, do: Enum.random(1..4)
[2, 2, 1, 3, 3, 2, 4, 2, 3, 1, 4, 2, 1, 1, 4, 1, 1, 4, 1, 2]
这里没有理由使用0索引:
for i <- 0..(pool_size - 1) do
让自己轻松一点:
for i <- 1..pool_size do
这是一个连接到在本地主机上运行的redis服务器的phoenix项目的简单示例:
~$ redis-server
50136:C 11 Jul 2019 21:26:30.954 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
50136:C 11 Jul 2019 21:26:30.954 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=50136, just started
50136:C 11 Jul 2019 21:26:30.954 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
50136:M 11 Jul 2019 21:26:30.955 * Increased maximum number of open files to 10032 (it was originally set to 256).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 5.0.5 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in standalone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 50136
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
50136:M 11 Jul 2019 21:26:30.957 # Server initialized
50136:M 11 Jul 2019 21:26:30.957 * Ready to accept connections
foo = your_app
foo / lib / foo / applicaton.ex:
defmodule Foo.Application do
# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
@moduledoc false
use Application
def start(_type, _args) do
# List all child processes to be supervised
children = [
# Start the Ecto repository
Foo.Repo,
# Start the endpoint when the application starts
FooWeb.Endpoint,
# Starts a worker by calling: Foo.Worker.start_link(arg)
# {Foo.Worker, arg},
{Redix, host: "localhost", name: :redix}
]
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: Foo.Supervisor]
Supervisor.start_link(children, opts)
end
# Tell Phoenix to update the endpoint configuration
# whenever the application is updated.
def config_change(changed, _new, removed) do
FooWeb.Endpoint.config_change(changed, removed)
:ok
end
end
foo / mix.exs:
defmodule Foo.MixProject do
use Mix.Project
def project do
[
app: :foo,
version: "0.1.0",
elixir: "~> 1.5",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
start_permanent: Mix.env() == :prod,
aliases: aliases(),
deps: deps()
]
end
# Configuration for the OTP application.
#
# Type `mix help compile.app` for more information.
def application do
[
mod: {Foo.Application, []},
extra_applications: [:logger, :runtime_tools]
]
end
# Specifies which paths to compile per environment.
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]
# Specifies your project dependencies.
#
# Type `mix help deps` for examples and options.
defp deps do
[
{:phoenix, "~> 1.4.0"},
{:phoenix_pubsub, "~> 1.1"},
{:phoenix_ecto, "~> 4.0"},
{:ecto_sql, "~> 3.0"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.11"},
{:phoenix_live_reload, "~> 1.2", only: :dev},
{:gettext, "~> 0.11"},
{:jason, "~> 1.0"},
{:plug_cowboy, "~> 2.0"},
{:mox, "~> 0.5.1"},
{:redix, ">= 0.0.0"},
{:castore, ">= 0.0.0"}
]
end
# Aliases are shortcuts or tasks specific to the current project.
# For example, to create, migrate and run the seeds file at once:
#
# $ mix ecto.setup
#
# See the documentation for `Mix` for more info on aliases.
defp aliases do
[
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
"ecto.reset": ["ecto.drop", "ecto.setup"],
test: ["ecto.create --quiet", "ecto.migrate", "test"]
]
end
end
在iex中:
~/phoenix_apps/foo$ iex -S mix
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (1.8.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Redix.command(:redix, ["SET", "connections", 10])
{:ok, "OK"}
iex(2)> Redix.command(:redix, ["INCR", "connections"])
{:ok, 11}
iex(3)>